diff --git a/.deepsource.toml b/.deepsource.toml
deleted file mode 100644
index aebeb0f..0000000
--- a/.deepsource.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-version = 1
-
-[[analyzers]]
-name = "python"
-enabled = true
-
- [analyzers.meta]
- runtime_version = "3.x.x"
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index aaa5539..227c0a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,74 +1,6 @@
-# Config file
-config.json
-
-# Byte-compiled / optimized / DLL files
+config.py
+*.session*
+*database.sqlite*
__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-.env/
-venv/
-.venv/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# 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
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-#Ipython Notebook
-.ipynb_checkpoints
-
-# PyCharm
-.idea
-
-# Database file
-uno.sqlite3
+*/__pycache__/
+config.py
diff --git a/AUTHORS.md b/AUTHORS.md
deleted file mode 100644
index d3dc17a..0000000
--- a/AUTHORS.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Credits
-
-`mau_mau_bot` was originally written and maintained by [Jannes Höke](https://github.com/jh0ker)
-
-`UnuRobot` is now maintained by [Amano LLC](https://github.com/AmanoTeam)
-
-## Contributors
-
-The following wonderful people contributed directly or indirectly to this project:
-
-- [imlonghao](https://github.com/imlonghao)
-- [Iuri Guilherme](https://github.com/iuriguilherme)
-- [pan93412](https://github.com/pan93412)
-- [qubitnerd](https://github.com/qubitnerd)
-- [SYHGroup](https://github.com/SYHGroup)
-
-Please add yourself here alphabetically when you submit your first pull request.
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index bb84073..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,17 +0,0 @@
-FROM python:alpine3.4
-
-RUN apk add --no-cache gettext
-
-WORKDIR /app/
-COPY requirements.txt .
-RUN pip install -r requirements.txt
-
-COPY . .
-
-RUN cd locales && find . -maxdepth 2 -type d -name 'LC_MESSAGES' -exec ash -c 'msgfmt {}/unobot.po -o {}/unobot.mo' \;
-
-
-VOLUME /app/data
-ENV UNO_DB /app/data/uno.sqlite3
-
-ENTRYPOINT python3 ./bot.py
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 2def0e8..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
- GNU AFFERO GENERAL PUBLIC LICENSE
- Version 3, 19 November 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 Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-our General Public Licenses are 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.
-
- 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.
-
- Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
- A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate. Many developers of free software are heartened and
-encouraged by the resulting cooperation. However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
- The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community. It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server. Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
- An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals. This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
- 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
-
- Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software. This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
- 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 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 work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
- 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 AGPL, see
-.
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 47f9660..0000000
--- a/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# UnuRobot
-
-[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](./LICENSE)
-[![Translation status](https://hosted.weblate.org/widgets/unurobot/-/bot/svg-badge.svg)](https://hosted.weblate.org/engage/unurobot/)
-
-Telegram Bot that allows you to play the popular card game UNO via inline queries. The bot currently runs as [@UnuRobot](http://t.me/UnuRobot).
-
-To run the bot yourself, you will need:
-
-- Python (tested with 3.7+)
-- The [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) module
-- [Pony ORM](https://ponyorm.com/)
-
-## Setup
-
-- Get a bot token from [@BotFather](http://t.me/BotFather) and change configurations in `config.json`.
-- Convert all language files from `.po` files to `.mo` by executing the bash script `compile.sh` located in the `locales` folder.
- Another option is: `find . -maxdepth 2 -type d -name 'LC_MESSAGES' -exec bash -c 'msgfmt {}/unobot.po -o {}/unobot.mo' \;`.
-- Use `/setinline` and `/setinlinefeedback` with BotFather for your bot.
-- Use `/setcommands` and submit the list of commands in commandlist.txt
-- Install requirements (using a `virtualenv` is recommended): `pip install -r requirements.txt`
-
-You can change some gameplay parameters like turn times, minimum amount of players and default gamemode in `config.json`.
-Current gamemodes available: Classic, Fast (Sanic), Wild, Text and 7-0. Check the details with the `/modes` command.
-
-Then run the bot with `python3 bot.py`.
-
-Code documentation is minimal but there.
-
-## Translating
-
-- Our translations are being done at our [Weblate](https://hosted.weblate.org/projects/unurobot/bot/) project.
- You can contribute to the currently supported languages or translate to a new language.
diff --git a/TRANSLATORS.md b/TRANSLATORS.md
deleted file mode 100644
index 5cde736..0000000
--- a/TRANSLATORS.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Translators
-
-The following awesome people contributed to this project by translating it:
-
-| Locale | Translators |
-|--------|-------------|
-| ca_CA | [retiolus](https://github.com/retiolus) |
-| de_DE | [Jannes Höke](https://github.com/jh0ker) |
-| es_ES | [José.A Rojo](https://github.com/J4RV), [Ricardo Valverde Hernández](https://t.me/rivh1), Victor, Yuga |
-| id_ID | [Erwin Guo](https://www.facebook.com/erwinfransiscus) |
-| it_IT | Carola Mariano, ɳick |
-| ml_IN | [Adhith T](https://github.com/adhitht123) |
-| nb_NO | [Allan Nordhøy](https://github.com/comradekingu) |
-| pt_BR | [Iuri Guilherme](https://github.com/iuriguilherme), [João Rodrigo Couto de Oliveira](http://twitter.com/JoaoRodrigoJR) |
-| pt | [Silvério Santos](https://github.com/SantosSi) |
-| zh_CN | [imlonghao](https://github.com/imlonghao), [XhyEax](https://github.com/XhyEax) |
-| zh_HK | [Jed Cheng](https://www.facebook.com/profile.php?id=100002258388821) |
-| zh_TW | [Eugene Lam](https://www.facebook.com/eugenelam1118), [jimchen5209](https://www.youtube.com/user/jimchen5209), [pan93412](https://www.github.com/pan93412) |
-
-Please add yourself here alphabetically when you submit your first translation.
diff --git a/actions.py b/actions.py
deleted file mode 100644
index e5518e4..0000000
--- a/actions.py
+++ /dev/null
@@ -1,277 +0,0 @@
-import contextlib
-import logging
-
-from telegram.ext import ContextTypes
-
-import card as c
-from config import MIN_FAST_TURN_TIME, TIME_REMOVAL_AFTER_SKIP
-from errors import DeckEmptyError, NotEnoughPlayersError
-from internationalization import __
-from shared_vars import gm
-from user_setting import UserSetting
-from utils import display_name, game_is_running, send_async
-
-logger = logging.getLogger(__name__)
-
-
-class Countdown:
- player = None
- job_queue = None
-
- def __init__(self, player, job_queue) -> None:
- self.player = player
- self.job_queue = job_queue
-
-
-# TODO do_skip() could get executed in another thread (it can be a job), so it looks like it can't use game.translate?
-async def do_skip(context: ContextTypes.DEFAULT_TYPE, player):
- game = player.game
- skipped_player = game.current_player
- next_player = game.current_player.next
- job_queue = context.job_queue
-
- if skipped_player.waiting_time > 0:
- skipped_player.anti_cheat += 1
- skipped_player.waiting_time -= TIME_REMOVAL_AFTER_SKIP
- skipped_player.waiting_time = max(skipped_player.waiting_time, 0)
- with contextlib.suppress(DeckEmptyError):
- skipped_player.draw()
- n = skipped_player.waiting_time
- await send_async(
- game,
- text=__(
- "Waiting time to skip this player has "
- "been reduced to {time} seconds.\n"
- "Next player: {name}",
- multi=game.translate,
- ).format(time=n, name=display_name(next_player.user)),
- )
- logger.info("%s was skipped!", display_name(player.user))
- game.turn()
- if job_queue:
- start_player_countdown(context, game)
-
- else:
- chat = game.chat
- try:
- gm.leave_game(skipped_player.user, chat)
- await send_async(
- game,
- text=__(
- "{name1} ran out of time "
- "and has been removed from the game!\n"
- "Next player: {name2}",
- multi=game.translate,
- ).format(
- name1=display_name(skipped_player.user),
- name2=display_name(next_player.user),
- ),
- )
- logger.info("%s was skipped!", display_name(player.user))
- if job_queue:
- start_player_countdown(context, game)
-
- except NotEnoughPlayersError:
- await send_async(
- game,
- text=__(
- "{name} ran out of time "
- "and has been removed from the game!\n"
- "The game ended.",
- multi=game.translate,
- ).format(name=display_name(skipped_player.user)),
- )
-
- gm.end_game(chat, skipped_player.user)
-
-
-def remove_cards(player, result_id):
- card = c.from_str(result_id)
- player.rm(card)
-
-
-async def subport(context: ContextTypes.DEFAULT_TYPE, player, pi):
- game = player.game
- user = player.user
-
- us = UserSetting.get(id=user.id) or UserSetting(id=user.id)
-
- if us.stats:
- us.cards_played += 1
-
- await verifi(context, player)
- await verifi(context, pi)
-
- game.turn()
-
-
-async def verifi(context: ContextTypes.DEFAULT_TYPE, player):
- game = player.game
- chat = game.chat
- user = player.user
-
- us = UserSetting.get(id=user.id) or UserSetting(id=user.id)
-
- if len(player.cards) == 1:
- await send_async(game, text="UNO!")
-
- if len(player.cards) == 0:
- await send_async(
- game,
- text=__("{name} won!", multi=game.translate).format(name=user.first_name),
- )
-
- if us.stats:
- us.games_played += 1
-
- if game.players_won == 0:
- us.first_places += 1
-
- game.players_won += 1
-
- try:
- gm.leave_game(user, chat)
- except NotEnoughPlayersError:
- await send_async(game, text=__("Game ended!", multi=game.translate))
-
- us2 = UserSetting.get(id=game.current_player.user.id)
- if us2 and us2.stats:
- us2.games_played += 1
-
- gm.end_game(chat, user)
-
-
-async def do_play_card(context: ContextTypes.DEFAULT_TYPE, player, result_id):
- """Plays the selected card and sends an update to the group if needed."""
- card = c.from_str(result_id)
- player.play(card)
- game = player.game
- chat = game.chat
- user = player.user
-
- us = UserSetting.get(id=user.id) or UserSetting(id=user.id)
-
- if us.stats:
- us.cards_played += 1
-
- if game.choosing_color:
- await send_async(game, text=__("Please choose a color", multi=game.translate))
-
- if len(player.cards) == 1:
- await send_async(game, text="UNO!")
-
- if len(player.cards) == 0:
- await send_async(
- game,
- text=__("{name} won!", multi=game.translate).format(name=user.first_name),
- )
-
- if us.stats:
- us.games_played += 1
-
- if game.players_won == 0:
- us.first_places += 1
-
- game.players_won += 1
-
- try:
- gm.leave_game(user, chat)
- except NotEnoughPlayersError:
- await send_async(game, text=__("Game ended!", multi=game.translate))
-
- us2 = UserSetting.get(id=game.current_player.user.id)
- if us2 and us2.stats:
- us2.games_played += 1
-
- gm.end_game(chat, user)
-
-
-async def do_draw(context: ContextTypes.DEFAULT_TYPE, player):
- """Does the drawing."""
- game = player.game
- draw_counter_before = game.draw_counter
-
- try:
- player.draw()
- except DeckEmptyError:
- await send_async(
- game,
- text=__("There are no more cards in the deck.", multi=game.translate),
- )
-
- if (
- game.last_card.value == c.DRAW_TWO or game.last_card.special == c.DRAW_FOUR
- ) and draw_counter_before > 0:
- game.turn()
-
-
-async def do_call_bluff(context: ContextTypes.DEFAULT_TYPE, player):
- """Handles the bluff calling."""
- game = player.game
-
- if player.prev.bluffing:
- await send_async(
- game,
- text=__(
- "Bluff called! Giving 4 cards to {name}",
- multi=game.translate,
- ).format(name=player.prev.user.first_name),
- )
-
- try:
- player.prev.draw()
- except DeckEmptyError:
- await send_async(
- game,
- text=__("There are no more cards in the deck.", multi=game.translate),
- )
-
- else:
- game.draw_counter += 2
- await send_async(
- game,
- text=__(
- "{name1} didn't bluff! Giving 6 cards to {name2}",
- multi=game.translate,
- ).format(name1=player.prev.user.first_name, name2=player.user.first_name),
- )
- try:
- player.draw()
- except DeckEmptyError:
- await send_async(
- game,
- text=__("There are no more cards in the deck.", multi=game.translate),
- )
-
- game.turn()
-
-
-def start_player_countdown(context: ContextTypes.DEFAULT_TYPE, game):
- player = game.current_player
- time = player.waiting_time
-
- time = max(time, MIN_FAST_TURN_TIME)
-
- if game.mode == "fast":
- if game.job:
- game.job.schedule_removal()
-
- job = context.job_queue.run_once(
- skip_job,
- time,
- data=Countdown(player, context.job_queue),
- )
-
- logger.info(
- "Started countdown for player: %s. %s seconds.",
- display_name(player.user),
- time,
- )
- player.game.job = job
-
-
-async def skip_job(context: ContextTypes.DEFAULT_TYPE):
- player = context.job.data.player
- game = player.game
- if game_is_running(game):
- await do_skip(context, player)
diff --git a/bot.py b/bot.py
old mode 100755
new mode 100644
index 6562f2c..3b1d8ee
--- a/bot.py
+++ b/bot.py
@@ -1,976 +1,18 @@
-#!/usr/bin/env python3
-#
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+from config import bot
+from hydrogram import idle
+from tortoise import run_async
+from version import ascii_art
+from db import connect_database
+import os
-import logging
-from datetime import datetime
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
-from telegram.constants import ParseMode
-from telegram.ext import (
- CallbackQueryHandler,
- ChosenInlineResultHandler,
- CommandHandler,
- ContextTypes,
- InlineQueryHandler,
- MessageHandler,
- filters,
-)
+async def main():
+ os.system("clear")
+ print(ascii_art)
+ await connect_database()
+ await bot.start()
+ await idle()
+ await bot.stop()
-import card as c
-import settings
-import simple_commands
-from actions import (
- do_call_bluff,
- do_draw,
- do_play_card,
- do_skip,
- remove_cards,
- start_player_countdown,
- subport,
-)
-from config import DEFAULT_GAMEMODE, MIN_PLAYERS, WAITING_TIME
-from errors import (
- AlreadyJoinedError,
- DeckEmptyError,
- LobbyClosedError,
- NoGameInChatError,
- NotEnoughPlayersError,
-)
-from internationalization import _, __, game_locales, user_locale
-from results import (
- add_call_bluff,
- add_card,
- add_choose_color,
- add_choose_player,
- add_draw,
- add_gameinfo,
- add_mode_classic,
- add_mode_fast,
- add_mode_sete,
- add_mode_text,
- add_mode_wild,
- add_no_game,
- add_not_started,
- add_other_cards,
- add_pass,
-)
-from shared_vars import application, gm
-from simple_commands import help_handler
-from utils import (
- answer_async,
- display_name,
- error,
- game_is_running,
- send_async,
- user_is_creator,
- user_is_creator_or_admin,
-)
-logging.basicConfig(
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
- level=logging.INFO,
-)
-logger = logging.getLogger(__name__)
-
-
-@user_locale
-async def notify_me(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for /notify_me command, pm people for next game."""
- chat = update.message.chat
-
- if update.message.chat.type == "private":
- await send_async(
- chat,
- text=_(
- "Send this command in a group to be notified "
- "when a new game is started there.",
- ),
- message_thread_id=update.message.message_thread_id,
- )
- else:
- try:
- gm.remind_dict[chat.id].add(update.message.from_user)
- except KeyError:
- gm.remind_dict[chat.id] = {update.message.from_user}
-
- await send_async(
- chat,
- text=_(
- "Okay, you will be notified in a private message "
- "when the next game is started in this chat. "
- "Make sure that I'm allowed to send you messages.",
- ),
- message_thread_id=update.message.message_thread_id,
- )
-
-
-@user_locale
-async def new_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /new command."""
- if update.message.chat.type == "private":
- await help_handler(update, context)
-
- else:
- if update.message.chat_id in gm.remind_dict:
- for user in gm.remind_dict[update.message.chat_id]:
- await send_async(
- user,
- text=_("A new game has been started in {title}").format(
- title=update.message.chat.title,
- ),
- )
-
- del gm.remind_dict[update.message.chat_id]
-
- game = gm.new_game(update.message.chat, update.message.message_thread_id)
- game.starter = update.message.from_user
- game.owner.append(update.message.from_user.id)
- game.mode = DEFAULT_GAMEMODE
- await send_async(
- game,
- text=_(
- "Created a new game! Join the game with /join "
- "and start the game with /start",
- ),
- )
-
-
-@user_locale
-async def kill_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /kill command."""
- chat = update.message.chat
- user = update.message.from_user
- games = gm.chatid_games.get(chat.id)
-
- if update.message.chat.type == "private":
- await help_handler(update, context)
- return
-
- if not games:
- await send_async(
- chat,
- text=_("There is no running game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = games[-1]
-
- if await user_is_creator_or_admin(user, game, context, chat):
- try:
- gm.end_game(chat, user)
- await send_async(game, text=__("Game ended!", multi=game.translate))
-
- except NoGameInChatError:
- await send_async(
- game,
- text=_(
- "The game is not started yet. "
- "Join the game with /join and start the game with /start",
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
-
-@user_locale
-async def join_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /join command."""
- chat = update.message.chat
-
- if update.message.chat.type == "private":
- await help_handler(update, context)
- return
-
- try:
- gm.join_game(update.message.from_user, chat)
-
- except LobbyClosedError:
- await send_async(
- chat,
- text=_("The lobby is closed"),
- message_thread_id=update.message.message_thread_id,
- )
-
- except NoGameInChatError:
- await send_async(
- chat,
- text=_("No game is running at the moment. Create a new game with /new"),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
-
- except AlreadyJoinedError:
- await send_async(
- chat,
- text=_("You already joined the game. Start the game with /start"),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
-
- except DeckEmptyError:
- await send_async(
- chat,
- text=_(
- "There are not enough cards left in the deck for "
- "new players to join.",
- ),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
-
- else:
- await send_async(
- chat,
- text=_("Joined the game"),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
-
-
-@user_locale
-async def leave_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /leave command."""
- chat = update.message.chat
- user = update.message.from_user
-
- player = gm.player_for_user_in_chat(user, chat)
-
- if player is None:
- await send_async(
- chat,
- text=_("You are not playing in a game in this group."),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
- return
-
- game = player.game
- user = update.message.from_user
-
- try:
- gm.leave_game(user, chat)
-
- except NoGameInChatError:
- await send_async(
- game,
- text=_("You are not playing in a game in this group."),
- reply_to_message_id=update.message.message_id,
- )
-
- except NotEnoughPlayersError:
- gm.end_game(chat, user)
- await send_async(game, text=__("Game ended!", multi=game.translate))
-
- else:
- if game.started:
- await send_async(
- game,
- text=__("Okay. Next Player: {name}", multi=game.translate).format(
- name=display_name(game.current_player.user),
- ),
- reply_to_message_id=update.message.message_id,
- )
- else:
- await send_async(
- game,
- text=__(
- "{name} left the game before it started.",
- multi=game.translate,
- ).format(name=display_name(user)),
- reply_to_message_id=update.message.message_id,
- )
-
-
-@user_locale
-async def kick_player(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /kick command."""
- if update.message.chat.type == "private":
- await help_handler(update, context)
- return
-
- chat = update.message.chat
- user = update.message.from_user
-
- try:
- game = gm.chatid_games[chat.id][-1]
-
- except (KeyError, IndexError):
- await send_async(
- chat,
- text=_("No game is running at the moment. Create a new game with /new"),
- message_thread_id=update.message.message_thread_id,
- reply_to_message_id=update.message.message_id,
- )
- return
-
- if not game.started:
- await send_async(
- game,
- text=_(
- "The game is not started yet. "
- "Join the game with /join and start the game with /start",
- ),
- reply_to_message_id=update.message.message_id,
- )
- return
-
- if await user_is_creator_or_admin(user, game, context, chat):
- if update.message.reply_to_message:
- kicked = update.message.reply_to_message.from_user
-
- try:
- gm.leave_game(kicked, chat)
-
- except NoGameInChatError:
- await send_async(
- game,
- text=_(
- "Player {name} is not found in the current game.".format(
- name=display_name(kicked),
- ),
- ),
- reply_to_message_id=update.message.message_id,
- )
- return
-
- except NotEnoughPlayersError:
- gm.end_game(chat, user)
- await send_async(
- game,
- text=_(
- f"{display_name(kicked)} was kicked by {display_name(user)}",
- ),
- )
- await send_async(game, text=__("Game ended!", multi=game.translate))
- return
-
- await send_async(
- game,
- text=_(
- f"{display_name(kicked)} was kicked by {display_name(user)}",
- ),
- )
-
- else:
- await send_async(
- game,
- text=_(
- "Please reply to the person you want to kick and type /kick again.",
- ),
- reply_to_message_id=update.message.message_id,
- )
- return
-
- await send_async(
- game,
- text=__("Okay. Next Player: {name}", multi=game.translate).format(
- name=display_name(game.current_player.user),
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
-
-async def select_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for callback queries to select the current game."""
- chat_id = int(update.callback_query.data)
- user_id = update.callback_query.from_user.id
- players = gm.userid_players[user_id]
- for player in players:
- if player.game.chat.id == chat_id:
- gm.userid_current[user_id] = player
- break
- else:
- await send_async(
- update.callback_query.message.chat,
- text=_("Game not found."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- async def selected(bot):
- back = [
- [
- InlineKeyboardButton(
- text=_("Back to last group"),
- switch_inline_query="",
- ),
- ],
- ]
- await context.bot.answerCallbackQuery(
- update.callback_query.id,
- text=_("Please switch to the group you selected!"),
- show_alert=False,
- )
-
- await context.bot.editMessageText(
- chat_id=update.callback_query.message.chat_id,
- message_id=update.callback_query.message.message_id,
- text=_(
- "Selected group: {group}\n"
- "Make sure that you switch to the correct "
- "group!",
- ).format(group=gm.userid_current[user_id].game.chat.title),
- reply_markup=InlineKeyboardMarkup(back),
- parse_mode=ParseMode.HTML,
- )
-
- await selected(context.bot)
-
-
-@game_locales
-async def status_update(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Remove player from game if user leaves the group."""
- chat = update.message.chat
-
- user = update.message.left_chat_member
-
- try:
- gm.leave_game(user, chat)
- game = gm.player_for_user_in_chat(user, chat).game
-
- except NoGameInChatError:
- pass
- except NotEnoughPlayersError:
- gm.end_game(chat, user)
- await send_async(
- chat,
- text=__("Game ended!", multi=game.translate),
- message_thread_id=update.message.message_thread_id,
- )
- else:
- await send_async(
- game,
- text=__("Removing {name} from the game", multi=game.translate).format(
- name=display_name(user),
- ),
- )
-
-
-@game_locales
-@user_locale
-async def start_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /start command."""
- args = context.args
-
- if update.message.chat.type != "private":
- chat = update.message.chat
-
- try:
- game = gm.chatid_games[chat.id][-1]
- except (KeyError, IndexError):
- await send_async(
- chat,
- text=_(
- "There is no game running in this chat. Create "
- "a new one with /new",
- ),
- )
- return
-
- if game.started:
- await send_async(game, text=_("The game has already started"))
-
- elif len(game.players) < MIN_PLAYERS:
- await send_async(
- game,
- text=__(
- "At least {minplayers} players must /join the game "
- "before you can start it",
- ).format(minplayers=MIN_PLAYERS),
- )
-
- else:
- # Starting a game
- game.start()
-
- for player in game.players:
- player.draw_first_hand()
- choice = [
- [
- InlineKeyboardButton(
- text=_("Make your choice!"),
- switch_inline_query_current_chat="",
- ),
- ],
- ]
- first_message = __(
- "First player: {name}\n"
- "Use /close to stop people from joining the game.\n"
- "Enable multi-translations with /enable_translations",
- multi=game.translate,
- ).format(name=display_name(game.current_player.user))
-
- async def send_first():
- """Send the first card and player."""
- await context.bot.send_sticker(
- chat.id,
- sticker=c.STICKERS[str(game.last_card)],
- message_thread_id=game.thread_id,
- )
-
- await send_async(
- game,
- text=first_message,
- reply_markup=InlineKeyboardMarkup(choice),
- )
-
- await send_first()
- start_player_countdown(context, game)
-
- elif len(args) and args[0] == "select":
- players = gm.userid_players[update.message.from_user.id]
-
- groups = []
- for player in players:
- title = player.game.chat.title
-
- if player is gm.userid_current[update.message.from_user.id]:
- title = f"- {player.game.chat.title} -"
-
- groups.append(
- [
- InlineKeyboardButton(
- text=title,
- callback_data=str(player.game.chat.id),
- ),
- ],
- )
-
- await send_async(
- game,
- text=_("Please select the group you want to play in."),
- reply_markup=InlineKeyboardMarkup(groups),
- )
-
- else:
- await help_handler(update, context)
-
-
-@user_locale
-async def close_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /close command."""
- chat = update.message.chat
- user = update.message.from_user
- games = gm.chatid_games.get(chat.id)
-
- if not games:
- await send_async(
- chat,
- text=_("There is no running game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = games[-1]
-
- if user.id in game.owner:
- game.open = False
- await send_async(
- game,
- text=_("Closed the lobby. No more players can join this game."),
- )
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- return
-
-
-@user_locale
-async def open_game(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /open command."""
- chat = update.message.chat
- user = update.message.from_user
- games = gm.chatid_games.get(chat.id)
-
- if not games:
- await send_async(
- chat,
- text=_("There is no running game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = games[-1]
-
- if user.id in game.owner:
- game.open = True
- await send_async(
- game,
- text=_("Opened the lobby. New players may /join the game."),
- )
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- return
-
-
-@user_locale
-async def enable_translations(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /enable_translations command."""
- chat = update.message.chat
- user = update.message.from_user
- games = gm.chatid_games.get(chat.id)
-
- if not games:
- await send_async(
- chat,
- text=_("There is no running game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = games[-1]
-
- if user.id in game.owner:
- game.translate = True
- await send_async(
- game,
- text=_("Enabled multi-translations. Disable with /disable_translations"),
- )
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- return
-
-
-@user_locale
-async def disable_translations(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /disable_translations command."""
- chat = update.message.chat
- user = update.message.from_user
- games = gm.chatid_games.get(chat.id)
-
- if not games:
- await send_async(
- chat,
- text=_("There is no running game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = games[-1]
-
- if user.id in game.owner:
- game.translate = False
- await send_async(
- game,
- text=_(
- "Disabled multi-translations. "
- "Enable them again with "
- "/enable_translations",
- ),
- )
- else:
- await send_async(
- game,
- text=_("Only the game creator ({name}) and admin can do that.").format(
- name=game.starter.first_name,
- ),
- reply_to_message_id=update.message.message_id,
- )
-
- return
-
-
-@game_locales
-@user_locale
-async def skip_player(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /skip command."""
- chat = update.message.chat
- user = update.message.from_user
-
- player = gm.player_for_user_in_chat(user, chat)
- if not player:
- await send_async(
- chat,
- text=_("You are not playing in a game in this chat."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- game = player.game
- skipped_player = game.current_player
-
- started = skipped_player.turn_started
- now = datetime.now()
- delta = (now - started).seconds
-
- # You can't skip if the current player still has time left
- # You can skip yourself even if you have time left (you'll still draw)
- if delta < skipped_player.waiting_time and player != skipped_player:
- n = skipped_player.waiting_time - delta
- await send_async(
- game,
- text=_("Please wait {time} second", "Please wait {time} seconds", n).format(
- time=n,
- ),
- reply_to_message_id=update.message.message_id,
- )
- else:
- await do_skip(context, player)
-
-
-@game_locales
-@user_locale
-async def reply_to_query(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for inline queries.
- Builds the result list for inline queries and answers to the client.
- """
- results = []
- switch = None
-
- try:
- user = update.inline_query.from_user
- user_id = user.id
- players = gm.userid_players[user_id]
- player = gm.userid_current[user_id]
- game = player.game
- except KeyError:
- add_no_game(results)
- else:
- # The game has not started.
- # The creator may change the game mode, other users just get a "game has not started" message.
- if not game.started:
- if user_is_creator(user, game):
- add_mode_classic(results)
- add_mode_fast(results)
- add_mode_wild(results)
- add_mode_text(results)
- add_mode_sete(results)
- else:
- add_not_started(results)
-
- elif user_id == game.current_player.user.id:
- if game.choosing_color:
- add_choose_color(results, game)
- add_other_cards(player, results, game)
- elif game.choosing_player:
- add_choose_player(player.user.id, results, game)
- else:
- if not player.drew:
- add_draw(player, results)
-
- else:
- add_pass(results, game)
-
- if game.last_card.special == c.DRAW_FOUR and game.draw_counter:
- add_call_bluff(results, game)
-
- playable = player.playable_cards()
- added_ids = [] # Duplicates are not allowed
-
- for card in sorted(player.cards):
- add_card(
- game,
- card,
- results,
- can_play=(card in playable and str(card) not in added_ids),
- )
- added_ids.append(str(card))
-
- add_gameinfo(game, results)
-
- else:
- for card in sorted(player.cards):
- add_card(game, card, results, can_play=False)
-
- for result in results:
- result._frozen = False
- result.id += ":%d" % player.anti_cheat
- result._frozen = True
-
- if players and game and len(players) > 1:
- switch = _("Current game: {game}").format(game=game.chat.title)
-
- await answer_async(
- context,
- update.inline_query.id,
- results,
- cache_time=0,
- switch_pm_text=switch,
- switch_pm_parameter="select",
- )
-
-
-@game_locales
-@user_locale
-async def process_result(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for chosen inline results.
- Checks the players actions and acts accordingly.
- """
- try:
- user = update.chosen_inline_result.from_user
- player = gm.userid_current[user.id]
- game = player.game
- result_id = update.chosen_inline_result.result_id
- except (KeyError, AttributeError):
- return
-
- logger.debug("Selected result: %s", result_id)
-
- result_id, anti_cheat = result_id.split(":")
- last_anti_cheat = player.anti_cheat
- player.anti_cheat += 1
- if result_id in ("hand", "gameinfo", "nogame"):
- return
- elif result_id.startswith("mode_"):
- # First 5 characters are 'mode_', the rest is the gamemode.
- mode = result_id[5:]
- game.set_mode(mode)
- logger.info("Gamemode changed to %s", mode)
- await send_async(game, text=__(f"Gamemode changed to {mode}"))
- return
- elif len(result_id) == 36: # UUID result
- return
- elif int(anti_cheat) != last_anti_cheat:
- await send_async(
- game,
- text=__("Cheat attempt by {name}", multi=game.translate).format(
- name=display_name(player.user),
- ),
- )
- return
- elif result_id == "call_bluff":
- await reset_waiting_time(context, player)
- await do_call_bluff(context, player)
- elif "7" in result_id and game.mode == "7-0" and "player" not in result_id:
- game.choosing_player = True
- await send_async(game, text="Please choose a player to switch cards")
- remove_cards(player, result_id)
- elif "0" in result_id and game.mode == "7-0" and "player" not in result_id:
- await reset_waiting_time(context, player)
- await do_play_card(context, player, result_id)
- b = {a: i.cards for a, i in enumerate(game.players)}
- for a, i in enumerate(game.players, start=1):
- i.cards = b.get(a, b[0])
- elif result_id == "draw":
- await reset_waiting_time(context, player)
- await do_draw(context, player)
- elif result_id == "pass":
- game.turn()
- elif "player" in result_id:
- n = result_id[7:]
- for a, i in enumerate(game.players):
- if a == int(n):
- v = i.user.id
- pi = gm.userid_current[v]
- pq = pi.cards
- pn = player.cards
- pi.cards = pn
- player.cards = pq
- await subport(context, player, pi)
- elif result_id in c.COLORS:
- game.choose_color(result_id)
- else:
- await reset_waiting_time(context, player)
- await do_play_card(context, player, result_id)
-
- if game_is_running(game):
- nextplayer_message = __("Next player: {name}", multi=game.translate).format(
- name=display_name(game.current_player.user),
- )
- choice = [
- [
- InlineKeyboardButton(
- text=_("Make your choice!"),
- switch_inline_query_current_chat="",
- ),
- ],
- ]
- await send_async(
- game,
- text=nextplayer_message,
- reply_markup=InlineKeyboardMarkup(choice),
- )
- start_player_countdown(context, game)
-
-
-async def reset_waiting_time(context, player):
- """Resets waiting time for a player and sends a notice to the group."""
- if player.waiting_time < WAITING_TIME:
- player.waiting_time = WAITING_TIME
- await send_async(
- player.game.thread_id,
- text=__(
- "Waiting time for {name} has been reset to {time} seconds",
- multi=player.game.translate,
- ).format(name=display_name(player.user), time=WAITING_TIME),
- )
-
-
-# Add all handlers to the application and run the bot
-application.add_handler(InlineQueryHandler(reply_to_query))
-application.add_handler(ChosenInlineResultHandler(process_result))
-application.add_handler(CallbackQueryHandler(select_game))
-application.add_handler(CommandHandler("start", start_game))
-application.add_handler(CommandHandler("new", new_game))
-application.add_handler(CommandHandler("kill", kill_game))
-application.add_handler(CommandHandler("join", join_game))
-application.add_handler(CommandHandler("leave", leave_game))
-application.add_handler(CommandHandler("kick", kick_player))
-application.add_handler(CommandHandler("open", open_game))
-application.add_handler(CommandHandler("close", close_game))
-application.add_handler(CommandHandler("enable_translations", enable_translations))
-application.add_handler(CommandHandler("disable_translations", disable_translations))
-application.add_handler(CommandHandler("skip", skip_player))
-application.add_handler(CommandHandler("notify_me", notify_me))
-simple_commands.register()
-settings.register()
-application.add_handler(
- MessageHandler(filters.StatusUpdate.LEFT_CHAT_MEMBER, status_update),
-)
-application.add_error_handler(error)
-
-# start the bot
-application.run_polling(drop_pending_updates=True)
+run_async(main())
diff --git a/card.py b/card.py
index 2f97fd8..407d48a 100644
--- a/card.py
+++ b/card.py
@@ -1,20 +1,6 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+import os
+import json
-# Colors
RED = "r"
BLUE = "b"
GREEN = "g"
@@ -55,7 +41,6 @@
REVERSE,
SKIP,
)
-WILD_VALUES = (ONE, TWO, THREE, FOUR, FIVE, DRAW_TWO, REVERSE, SKIP)
# Special cards
CHOOSE = "colorchooser"
@@ -63,155 +48,9 @@
SPECIALS = (CHOOSE, DRAW_FOUR)
-STICKERS = {
- "b_0": "CAACAgQAAxkDAAI372NtY-V641fF6HhAA4Vuc6CbI_LeAALZAQACX1eZAAEqnpNt3SpG_ysE",
- "b_1": "CAACAgQAAxkDAAI38GNtY-UvkNQN3h5p5n_dfNbhPV9HAALbAQACX1eZAAHluPl_BVzaDisE",
- "b_2": "CAACAgQAAxkDAAI38WNtY-X4Gvnxt4mofZ-Uv_zmGWHRAALdAQACX1eZAAEFe5JBdpP-cysE",
- "b_3": "CAACAgQAAxkDAAI38mNtY-av7Gm6hUEdRs_mONWGzKoGAALfAQACX1eZAAFQJXWHQ2D7uisE",
- "b_4": "CAACAgQAAxkDAAI382NtY-YXxHbN1MfXSl6FbzwgWq5vAALhAQACX1eZAAHo1SP4devY_ysE",
- "b_5": "CAACAgQAAxkDAAI39GNtY-dNEOn0i1luuPjPOHvqyasxAALjAQACX1eZAALf6g-FruzaKwQ",
- "b_6": "CAACAgQAAxkDAAI39WNtY-df9ew41xXE6ARS3VHDKg0NAALlAQACX1eZAAHwMoU1Nb4OgisE",
- "b_7": "CAACAgQAAxkDAAI39mNtY-ftENXWBUBNqNTomh-NeufNAALnAQACX1eZAAFOBAnoop1fWisE",
- "b_8": "CAACAgQAAxkDAAI392NtY-idvjst_LSKlwP2cEDnS3WpAALpAQACX1eZAAHmKrizqjwJ3isE",
- "b_9": "CAACAgQAAxkDAAI3-GNtY-jEw-hh0ei6OxSl2r4DehmIAALrAQACX1eZAAHvul-ZztVWiisE",
- "b_draw": "CAACAgQAAxkDAAI3-WNtY-nrtJj_c48YtjbPwydARdwJAALtAQACX1eZAAGdURg9n6qvEysE",
- "b_skip": "CAACAgQAAxkDAAI3-mNtY-kVI0dIVd38sOvZrZmtRCv_AALxAQACX1eZAAHAf0ks_Y82JysE",
- "b_reverse": "CAACAgQAAxkDAAI3-2NtY-p4_EUUTVDYKX12SMcKA9IbAALvAQACX1eZAAFjAZc535XzNSsE",
- "g_0": "CAACAgQAAxkDAAI3_GNtY-qvO3V8NwHojOpf8aIpbnYvAAL3AQACX1eZAAH7m-CsNWDzBSsE",
- "g_1": "CAACAgQAAxkDAAI3_WNtY-r28bGOeJGKL7ZtEwUrWXzfAAL5AQACX1eZAAFVNSG--aqs9CsE",
- "g_2": "CAACAgQAAxkDAAI3_mNtY-sjqfdB5nu7iKPFqHRItFerAAL7AQACX1eZAAHDX5Qn7VbSdCsE",
- "g_3": "CAACAgQAAxkDAAI3_2NtY-ueCVLB_KL8Xz0itFJGWNbYAAL9AQACX1eZAAGwUxSSKSNPaisE",
- "g_4": "CAACAgQAAxkDAAI4AAFjbWPsRRrrb0KdkF5SGCO87ni9sAAC_wEAAl9XmQABARICqk9L7OArBA",
- "g_5": "CAACAgQAAxkDAAI4AWNtY-zlRyWdS69Z4bcwBgklRcBEAAIBAgACX1eZAAGN2wN5nVhf3ysE",
- "g_6": "CAACAgQAAxkDAAI4AmNtY-zXK3F2NTz-XaFeDk2rsP7NAAIDAgACX1eZAAFaJA80kw1XfSsE",
- "g_7": "CAACAgQAAxkDAAI4A2NtY-0dqOmBW9-XK_BbtXg0OLRaAAIFAgACX1eZAAGDbLTCiNGLBisE",
- "g_8": "CAACAgQAAxkDAAI4BGNtY-2kF7oUCmvU_AbU9lmudtZqAAIHAgACX1eZAAGnWrRTRZj7gSsE",
- "g_9": "CAACAgQAAxkDAAI4BWNtY-60BpqwiJQ8-p93unknqHi2AAIJAgACX1eZAAHODOPdhwzltysE",
- "g_draw": "CAACAgQAAxkDAAI4BmNtY-53H6EJgbUQSeEpguubOevXAAILAgACX1eZAAFWg06uGplHVysE",
- "g_skip": "CAACAgQAAxkDAAI4B2NtY-5VirooDDZAWu4ENrVBBoFHAAIPAgACX1eZAAHn-hBXxRvYQisE",
- "g_reverse": "CAACAgQAAxkDAAI4CGNtY-_G8b0fBt0N3OBgx9CIwJziAAINAgACX1eZAAFMYqmCS3vfySsE",
- "r_0": "CAACAgQAAxkDAAI4CWNtY-9LOKHb1FqCn3GmqxOYCo_fAAIRAgACX1eZAAHK9atgT_cu_isE",
- "r_1": "CAACAgQAAxkDAAI4CmNtY_Dxb_ivl-VHFRDPgHVOilCVAAITAgACX1eZAAH_6pt2airFESsE",
- "r_2": "CAACAgQAAxkDAAI4C2NtY_B9bP3cd73NvBd-Un8yZTYzAAIVAgACX1eZAAHQrmSSeMDfgCsE",
- "r_3": "CAACAgQAAxkDAAI4DGNtY_Hqk5RPHjNn50jy_ImBPYZLAAIXAgACX1eZAAFeHWWPa-piRysE",
- "r_4": "CAACAgQAAxkDAAI4DWNtY_HqY4wNkPulTWHIY9d2Fep-AAIZAgACX1eZAAE7VUWywkd3KCsE",
- "r_5": "CAACAgQAAxkDAAI4DmNtY_Lb9j5Qi5RVPEaSW3uZWAnlAAIbAgACX1eZAAF1s0b9V-PUJCsE",
- "r_6": "CAACAgQAAxkDAAI4D2NtY_Kklm1t7E0KShmWTbXEwnpNAAIdAgACX1eZAAF8hSz11exIUisE",
- "r_7": "CAACAgQAAxkDAAI4EGNtY_LoR07j-LayjpoVlEPLCCe0AAIfAgACX1eZAAEVnCo1RKSqnCsE",
- "r_8": "CAACAgQAAxkDAAI4EWNtY_OrIOu5PPIUTZ-cn0FBFcT2AAIhAgACX1eZAAEhXezQrbzKOisE",
- "r_9": "CAACAgQAAxkDAAI4EmNtY_PI6uILsPHkkyIDFp4ivFBJAAIjAgACX1eZAAHN4GBkUaxpqisE",
- "r_draw": "CAACAgQAAxkDAAI4E2NtY_SNrUaYiRbAIEi9c_X-veafAAIlAgACX1eZAAGZvG1zNp2cVisE",
- "r_skip": "CAACAgQAAxkDAAI4FGNtY_SrNSCK9k9FO9Xji2fb9LJMAAIpAgACX1eZAAFprUDwYHBu3SsE",
- "r_reverse": "CAACAgQAAxkDAAI4FWNtY_V41t8UX4XtxugfwVMibbqLAAInAgACX1eZAAGay7EvXnoVZisE",
- "y_0": "CAACAgQAAxkDAAI4FmNtY_XYaAevT9wxGiAxI1n6e_spAAIrAgACX1eZAAG1mgAB2D5sIc8rBA",
- "y_1": "CAACAgQAAxkDAAI4F2NtY_aD1zsrQYWtYoeePhDN1bcvAAItAgACX1eZAAHqNCCjuSEQjisE",
- "y_2": "CAACAgQAAxkDAAI4GGNtY_Y9kN6nzxvk8KwX8SnwTntmAAIvAgACX1eZAAH4u547rBAiBCsE",
- "y_3": "CAACAgQAAxkDAAI4GWNtY_dJwM67rmUFcLEtByedoFJdAAIxAgACX1eZAAFBQ00TMrpMeisE",
- "y_4": "CAACAgQAAxkDAAI4GmNtY_d6JUufI61BWnqI4DTVRxMVAAIzAgACX1eZAAF7IOqIuGqyDSsE",
- "y_5": "CAACAgQAAxkDAAI4G2NtY_dxij19aBCA7Tjf5ytWzXgNAAI1AgACX1eZAAHyIiYzI-E-LisE",
- "y_6": "CAACAgQAAxkDAAI4HGNtY_hPQ2iuWWmADOUYR-P-nNVFAAI3AgACX1eZAAH_E8fuZ374hysE",
- "y_7": "CAACAgQAAxkDAAI4HWNtY_jp9tXZ3lpAV83tzDcazcA4AAI5AgACX1eZAAHPK6qSI6Ku_CsE",
- "y_8": "CAACAgQAAxkDAAI4HmNtY_kQwEGUW6F38bBIYXfspzarAAI7AgACX1eZAAHXiL4XwJi0eysE",
- "y_9": "CAACAgQAAxkDAAI4H2NtY_kJ_ofl80XkaVobKpd-IgqQAAI9AgACX1eZAAGG_opl6vQSOCsE",
- "y_draw": "CAACAgQAAxkDAAI4IGNtY_qbKj2mnuJVlTai4F6se8MNAAI_AgACX1eZAAFrjyuhcA2ksysE",
- "y_skip": "CAACAgQAAxkDAAI4IWNtY_rKy-RTeKjfZT0RAYNNreVhAAJDAgACX1eZAAF1m63alvMoxysE",
- "y_reverse": "CAACAgQAAxkDAAI4ImNtY_vaX0rQZ_5ZUeFTpMa2ZQABOwACQQIAAl9XmQABCHpDm7MPbakrBA",
- "draw_four": "CAACAgQAAxkDAAI4I2NtY_vr1Fa4_Q2Y6dxOopNX7sSsAAL1AQACX1eZAAHXOgABZUCgVkkrBA",
- "colorchooser": "CAACAgQAAxkDAAI4JGNtY_vpncCbuHH2xDLokQWxUAXSAALzAQACX1eZAAHI5jbpFQE9bCsE",
- "option_draw": "CAACAgQAAxkDAAI4JWNtY_zry4NT2JAlWjTryYiuec4nAAL4AgACX1eZAAH-TdXSlvEa2ysE",
- "option_pass": "CAACAgQAAxkDAAI4JmNtY_yMlr6rB3UdTikR3zFCk8kVAAL6AgACX1eZAAFuilR5QnD-VysE",
- "option_bluff": "CAACAgQAAxkDAAI4J2NtY_2Dmt5Mi4iZhsUh32OeNVe7AALKAgACX1eZAAHBw478rNqN0CsE",
- "option_info": "CAACAgQAAxkDAAI4KGNtY_3tO0Sxhu5NzF1UA3tdUnklAALEAgACX1eZAAGi2Qy93IIQwisE",
-}
-
-STICKERS_GREY = {
- "b_0": "CAACAgQAAxkDAAI4KWNtY_3SM2AGtecbGE8XDjlWvcKxAAJFAgACX1eZAAHwXYFNZhQaIysE",
- "b_1": "CAACAgQAAxkDAAI4KmNtY_7zNsvijvvGZAJmuxcYVgizAAJHAgACX1eZAAF_ZxC64wgdNCsE",
- "b_2": "CAACAgQAAxkDAAI4K2NtY_4z7XEHPzcliqJth5G3ds6vAAJJAgACX1eZAAF-GuNgJ25IAAErBA",
- "b_3": "CAACAgQAAxkDAAI4LGNtY_9ZPE9nPCPJQ0Rjf_zOkTsiAAJLAgACX1eZAAHIJQ71XJ39mCsE",
- "b_4": "CAACAgQAAxkDAAI4LWNtY_--OWOFczobsp10PPj5p9pZAAJNAgACX1eZAAEjmR2mhJ8SsSsE",
- "b_5": "CAACAgQAAxkDAAI4LmNtZAABTkAAAT7kcgxZkdA3rcZmxM0AAk8CAAJfV5kAASN8DC8z_yexKwQ",
- "b_6": "CAACAgQAAxkDAAI4L2NtZAABOSkvi7YF9opHBHILrQukJwACUQIAAl9XmQABv35eqFpp188rBA",
- "b_7": "CAACAgQAAxkDAAI4MGNtZAABcb94kfODfzBiW7R6caIITgACUwIAAl9XmQABv8VaivrtncwrBA",
- "b_8": "CAACAgQAAxkDAAI4MWNtZAEPZcxI8yZZJ7mtvLEhRyQyAAJVAgACX1eZAAF8hUb4bS_NdCsE",
- "b_9": "CAACAgQAAxkDAAI4MmNtZAHG55HKa6LNKc496jAPrUCzAAJXAgACX1eZAAGXAmJ0BKvi1ysE",
- "b_draw": "CAACAgQAAxkDAAI4M2NtZALeN87Xgly5X7j5XK0dfaznAAJZAgACX1eZAAFS-DsDXK7zdisE",
- "b_skip": "CAACAgQAAxkDAAI4NGNtZAJR4ZxfKgABx3HNLp-9w8fNagACXQIAAl9XmQABc7AYk0bGSHorBA",
- "b_reverse": "CAACAgQAAxkDAAI4NWNtZAKP0DU5ZIh-4eID9fwEqWDhAAJbAgACX1eZAAHRLf8w4EEJfysE",
- "g_0": "CAACAgQAAxkDAAI4NmNtZAMTsoTxk-Gzg61XUbgiWmuDAAJjAgACX1eZAAG_c8FzjSBlOCsE",
- "g_1": "CAACAgQAAxkDAAI4N2NtZAOMsFWlo1a6VbET_L4Z33qjAAJlAgACX1eZAAH2R3CHmHduZCsE",
- "g_2": "CAACAgQAAxkDAAI4OGNtZASmomincPijzQaGuhzS4NT3AAJnAgACX1eZAAHB14u8vZ5pjSsE",
- "g_3": "CAACAgQAAxkDAAI4OWNtZATXrH2F0kmklBKkx5-yLbqeAAJpAgACX1eZAAFaZGnJmMcN9CsE",
- "g_4": "CAACAgQAAxkDAAI4OmNtZARrtuTkDtrmFwSWGCMNNyzVAAJrAgACX1eZAAF3KxLEqQq8KysE",
- "g_5": "CAACAgQAAxkDAAI4O2NtZAXsq9mIqylmXkuqblUSZ_s5AAJtAgACX1eZAAGObwogvTEInCsE",
- "g_6": "CAACAgQAAxkDAAI4PGNtZAXYyNLL6UnAXV2J5fcYDSjcAAJvAgACX1eZAAEpOGFMRnLGmSsE",
- "g_7": "CAACAgQAAxkDAAI4PWNtZAYp5RXbOKe2_RQkDLNHRnQsAAJxAgACX1eZAAEe_yu4DVELEisE",
- "g_8": "CAACAgQAAxkDAAI4PmNtZAZuRr1ubCO9SBPYf5uVwxOVAAJzAgACX1eZAAH26plyNxWZuCsE",
- "g_9": "CAACAgQAAxkDAAI4P2NtZAZ-4ux439AfgakLYhj7NkL7AAJ1AgACX1eZAAGrwYoTMk8UPSsE",
- "g_draw": "CAACAgQAAxkDAAI4QGNtZAcDJt3SZBIXhpzxAw-0pCjgAAJ3AgACX1eZAAFnlFIJWhbZIysE",
- "g_skip": "CAACAgQAAxkDAAI4QWNtZAdu6EvL3cTpvKgvVvS5TM8oAAJ7AgACX1eZAAFO5CqgPxquYSsE",
- "g_reverse": "CAACAgQAAxkDAAI4QmNtZAhYEij-J99P6WZprlvTrO1FAAJ5AgACX1eZAAE9cd3JVwlSEisE",
- "r_0": "CAACAgQAAxkDAAI4Q2NtZAhJMx2vsEJ0VqZf4K4vnICEAAJ9AgACX1eZAAEZAg2nRervSCsE",
- "r_1": "CAACAgQAAxkDAAI4RGNtZAggA5W5F360ygp-Kt5511ZGAAJ_AgACX1eZAAFtLPMD6heoDysE",
- "r_2": "CAACAgQAAxkDAAI4RWNtZAneP8mxTRUYpxCIcSZxrRzaAAKBAgACX1eZAAGuvzFU0Su89SsE",
- "r_3": "CAACAgQAAxkDAAI4RmNtZAkm-2Z3z4dgngqsNQKlAAEUIgACgwIAAl9XmQABBRY8MBWexokrBA",
- "r_4": "CAACAgQAAxkDAAI4R2NtZAr32JAr0Q5mSzPrZuPKAAEMAAOFAgACX1eZAAHZFzRnwree-ysE",
- "r_5": "CAACAgQAAxkDAAI4SGNtZAo06aPW8Bt2bEfhuAwYIAihAAKHAgACX1eZAAHsdpjtu9I2ISsE",
- "r_6": "CAACAgQAAxkDAAI4SWNtZArDcMo4iVhDv3V2PkjmODGWAAKJAgACX1eZAAG2D__a-tqZBSsE",
- "r_7": "CAACAgQAAxkDAAI4SmNtZAsNc-unKFxRAUfRgRpIu8zGAAKLAgACX1eZAAGXaAtw5YFztSsE",
- "r_8": "CAACAgQAAxkDAAI4S2NtZAtXBBjw_QmbUnPCqOjcPciqAAKNAgACX1eZAAGkCOaURWQl8CsE",
- "r_9": "CAACAgQAAxkDAAI4TGNtZAxdvNd9s7XbaETEDpraDSB8AAKPAgACX1eZAAH-WS6bmv9CgSsE",
- "r_draw": "CAACAgQAAxkDAAI4TWNtZAz-9sSylYycGwF82_5ceXLOAAKRAgACX1eZAAF2dldgt636fysE",
- "r_skip": "CAACAgQAAxkDAAI4TmNtZAwwZq3xqWgdKCELX9yXNNDHAAKVAgACX1eZAAGedr9LYgVebCsE",
- "r_reverse": "CAACAgQAAxkDAAI4T2NtZA1_h1jpVObJt7ZnGWC0EJu_AAKTAgACX1eZAAECR8T0lu-KmysE",
- "y_0": "CAACAgQAAxkDAAI4UGNtZA3XHBEqHJ4oD2s1vu019fCAAAKXAgACX1eZAALmpUbJzkaKKwQ",
- "y_1": "CAACAgQAAxkDAAI4UWNtZA70oPDw_EYnua3I_yHnoU0HAAKZAgACX1eZAAGB_02-C22PkysE",
- "y_2": "CAACAgQAAxkDAAI4UmNtZA73r_BBydbo0QL4Lrp6zzRgAAKbAgACX1eZAAHVmZUJxJwqmCsE",
- "y_3": "CAACAgQAAxkDAAI4U2NtZA7ITY2cWf3hZhbqbRFA2rznAAKdAgACX1eZAAGnajv8YZQj-ysE",
- "y_4": "CAACAgQAAxkDAAI4VGNtZA_w89jaIqKJT3mJ3jf4sNfqAAKfAgACX1eZAAEmxeENpAa35SsE",
- "y_5": "CAACAgQAAxkDAAI4VWNtZA9pJt03yLW1UVqmabBu03CRAAKhAgACX1eZAAH2evQmPPzx8isE",
- "y_6": "CAACAgQAAxkDAAI4VmNtZBBLaA_cEcY1-cmo4oRl7kFUAAKjAgACX1eZAAGYOfBpuoRg_CsE",
- "y_7": "CAACAgQAAxkDAAI4V2NtZBC1E-0IzKlEqkiFlLtGQ2djAAKlAgACX1eZAAFYxwrVWROuiysE",
- "y_8": "CAACAgQAAxkDAAI4WGNtZBDuCE40_AciHh4BlfOxvd4EAAKnAgACX1eZAAF10j1L6rASCSsE",
- "y_9": "CAACAgQAAxkDAAI4WWNtZBERcGe9cafGmVQMrn--6VyEAAKpAgACX1eZAAGV1nEmuqjoJCsE",
- "y_draw": "CAACAgQAAxkDAAI4WmNtZBHW7Ik5O4gDp80GEnME_8opAAKrAgACX1eZAAGfJ2XK_ooNFisE",
- "y_skip": "CAACAgQAAxkDAAI4W2NtZBLpZ4ilI48Wl42H2--LNZleAAKvAgACX1eZAAEVSSkTcHxJXCsE",
- "y_reverse": "CAACAgQAAxkDAAI4XGNtZBJeXdZLAWEB9hQVadvba2mLAAKtAgACX1eZAAEiP9aakPoiDysE",
- "draw_four": "CAACAgQAAxkDAAI4XWNtZBOEsZAZxOHFAttWBmLf5WSOAAJhAgACX1eZAAHWx9PCWaCqkysE",
- "colorchooser": "CAACAgQAAxkDAAI4XmNtZBPR9vYmNzz7P7Hq24wrLE16AAJfAgACX1eZAAH4WHYrSCRGIisE",
-}
-
-
-class Card:
- """This class represents an UNO card."""
-
- def __init__(self, color, value, special=None) -> None:
- self.color = color
- self.value = value
- self.special = special
-
- def __str__(self) -> str:
- return self.special or f"{self.color}_{self.value}"
-
- def __repr__(self) -> str:
- if self.special:
- return f'{COLOR_ICONS.get(self.color, "")}{COLOR_ICONS[BLACK]}{" ".join([s.capitalize() for s in self.special.split("_")])}'
-
- else:
- return f"{COLOR_ICONS[self.color]}{self.value.capitalize()}"
-
- def __eq__(self, other):
- """Needed for sorting the cards."""
- return str(self) == str(other)
-
- def __lt__(self, other):
- """Needed for sorting the cards."""
- return str(self) < str(other)
-
-
-def from_str(string):
- """Decodes a Card object from a string."""
- if string in SPECIALS:
- return Card(None, None, string)
- color, value = string.split("_")
- return Card(color, value)
+cards = {}
+for filename in os.listdir("cards"):
+ if filename.endswith(".json"):
+ name = filename.split(".")[0]
+ with open(f"cards/{filename}", "r") as f:
+ cards[name] = json.load(f)
diff --git a/cards/classic.json b/cards/classic.json
new file mode 100644
index 0000000..b01c2ac
--- /dev/null
+++ b/cards/classic.json
@@ -0,0 +1,152 @@
+{
+ "STICKERS": {
+ "b_0": "CAACAgQAAxkDAAI372NtY-V641fF6HhAA4Vuc6CbI_LeAALZAQACX1eZAAEqnpNt3SpG_ysE",
+ "b_1": "CAACAgQAAxkDAAI38GNtY-UvkNQN3h5p5n_dfNbhPV9HAALbAQACX1eZAAHluPl_BVzaDisE",
+ "b_2": "CAACAgQAAxkDAAI38WNtY-X4Gvnxt4mofZ-Uv_zmGWHRAALdAQACX1eZAAEFe5JBdpP-cysE",
+ "b_3": "CAACAgQAAxkDAAI38mNtY-av7Gm6hUEdRs_mONWGzKoGAALfAQACX1eZAAFQJXWHQ2D7uisE",
+ "b_4": "CAACAgQAAxkDAAI382NtY-YXxHbN1MfXSl6FbzwgWq5vAALhAQACX1eZAAHo1SP4devY_ysE",
+ "b_5": "CAACAgQAAxkDAAI39GNtY-dNEOn0i1luuPjPOHvqyasxAALjAQACX1eZAALf6g-FruzaKwQ",
+ "b_6": "CAACAgQAAxkDAAI39WNtY-df9ew41xXE6ARS3VHDKg0NAALlAQACX1eZAAHwMoU1Nb4OgisE",
+ "b_7": "CAACAgQAAxkDAAI39mNtY-ftENXWBUBNqNTomh-NeufNAALnAQACX1eZAAFOBAnoop1fWisE",
+ "b_8": "CAACAgQAAxkDAAI392NtY-idvjst_LSKlwP2cEDnS3WpAALpAQACX1eZAAHmKrizqjwJ3isE",
+ "b_9": "CAACAgQAAxkDAAI3-GNtY-jEw-hh0ei6OxSl2r4DehmIAALrAQACX1eZAAHvul-ZztVWiisE",
+ "b_draw": "CAACAgQAAxkDAAI3-WNtY-nrtJj_c48YtjbPwydARdwJAALtAQACX1eZAAGdURg9n6qvEysE",
+ "b_skip": "CAACAgQAAxkDAAI3-mNtY-kVI0dIVd38sOvZrZmtRCv_AALxAQACX1eZAAHAf0ks_Y82JysE",
+ "b_reverse": "CAACAgQAAxkDAAI3-2NtY-p4_EUUTVDYKX12SMcKA9IbAALvAQACX1eZAAFjAZc535XzNSsE",
+ "g_0": "CAACAgQAAxkDAAI3_GNtY-qvO3V8NwHojOpf8aIpbnYvAAL3AQACX1eZAAH7m-CsNWDzBSsE",
+ "g_1": "CAACAgQAAxkDAAI3_WNtY-r28bGOeJGKL7ZtEwUrWXzfAAL5AQACX1eZAAFVNSG--aqs9CsE",
+ "g_2": "CAACAgQAAxkDAAI3_mNtY-sjqfdB5nu7iKPFqHRItFerAAL7AQACX1eZAAHDX5Qn7VbSdCsE",
+ "g_3": "CAACAgQAAxkDAAI3_2NtY-ueCVLB_KL8Xz0itFJGWNbYAAL9AQACX1eZAAGwUxSSKSNPaisE",
+ "g_4": "CAACAgQAAxkDAAI4AAFjbWPsRRrrb0KdkF5SGCO87ni9sAAC_wEAAl9XmQABARICqk9L7OArBA",
+ "g_5": "CAACAgQAAxkDAAI4AWNtY-zlRyWdS69Z4bcwBgklRcBEAAIBAgACX1eZAAGN2wN5nVhf3ysE",
+ "g_6": "CAACAgQAAxkDAAI4AmNtY-zXK3F2NTz-XaFeDk2rsP7NAAIDAgACX1eZAAFaJA80kw1XfSsE",
+ "g_7": "CAACAgQAAxkDAAI4A2NtY-0dqOmBW9-XK_BbtXg0OLRaAAIFAgACX1eZAAGDbLTCiNGLBisE",
+ "g_8": "CAACAgQAAxkDAAI4BGNtY-2kF7oUCmvU_AbU9lmudtZqAAIHAgACX1eZAAGnWrRTRZj7gSsE",
+ "g_9": "CAACAgQAAxkDAAI4BWNtY-60BpqwiJQ8-p93unknqHi2AAIJAgACX1eZAAHODOPdhwzltysE",
+ "g_draw": "CAACAgQAAxkDAAI4BmNtY-53H6EJgbUQSeEpguubOevXAAILAgACX1eZAAFWg06uGplHVysE",
+ "g_skip": "CAACAgQAAxkDAAI4B2NtY-5VirooDDZAWu4ENrVBBoFHAAIPAgACX1eZAAHn-hBXxRvYQisE",
+ "g_reverse": "CAACAgQAAxkDAAI4CGNtY-_G8b0fBt0N3OBgx9CIwJziAAINAgACX1eZAAFMYqmCS3vfySsE",
+ "r_0": "CAACAgQAAxkDAAI4CWNtY-9LOKHb1FqCn3GmqxOYCo_fAAIRAgACX1eZAAHK9atgT_cu_isE",
+ "r_1": "CAACAgQAAxkDAAI4CmNtY_Dxb_ivl-VHFRDPgHVOilCVAAITAgACX1eZAAH_6pt2airFESsE",
+ "r_2": "CAACAgQAAxkDAAI4C2NtY_B9bP3cd73NvBd-Un8yZTYzAAIVAgACX1eZAAHQrmSSeMDfgCsE",
+ "r_3": "CAACAgQAAxkDAAI4DGNtY_Hqk5RPHjNn50jy_ImBPYZLAAIXAgACX1eZAAFeHWWPa-piRysE",
+ "r_4": "CAACAgQAAxkDAAI4DWNtY_HqY4wNkPulTWHIY9d2Fep-AAIZAgACX1eZAAE7VUWywkd3KCsE",
+ "r_5": "CAACAgQAAxkDAAI4DmNtY_Lb9j5Qi5RVPEaSW3uZWAnlAAIbAgACX1eZAAF1s0b9V-PUJCsE",
+ "r_6": "CAACAgQAAxkDAAI4D2NtY_Kklm1t7E0KShmWTbXEwnpNAAIdAgACX1eZAAF8hSz11exIUisE",
+ "r_7": "CAACAgQAAxkDAAI4EGNtY_LoR07j-LayjpoVlEPLCCe0AAIfAgACX1eZAAEVnCo1RKSqnCsE",
+ "r_8": "CAACAgQAAxkDAAI4EWNtY_OrIOu5PPIUTZ-cn0FBFcT2AAIhAgACX1eZAAEhXezQrbzKOisE",
+ "r_9": "CAACAgQAAxkDAAI4EmNtY_PI6uILsPHkkyIDFp4ivFBJAAIjAgACX1eZAAHN4GBkUaxpqisE",
+ "r_draw": "CAACAgQAAxkDAAI4E2NtY_SNrUaYiRbAIEi9c_X-veafAAIlAgACX1eZAAGZvG1zNp2cVisE",
+ "r_skip": "CAACAgQAAxkDAAI4FGNtY_SrNSCK9k9FO9Xji2fb9LJMAAIpAgACX1eZAAFprUDwYHBu3SsE",
+ "r_reverse": "CAACAgQAAxkDAAI4FWNtY_V41t8UX4XtxugfwVMibbqLAAInAgACX1eZAAGay7EvXnoVZisE",
+ "y_0": "CAACAgQAAxkDAAI4FmNtY_XYaAevT9wxGiAxI1n6e_spAAIrAgACX1eZAAG1mgAB2D5sIc8rBA",
+ "y_1": "CAACAgQAAxkDAAI4F2NtY_aD1zsrQYWtYoeePhDN1bcvAAItAgACX1eZAAHqNCCjuSEQjisE",
+ "y_2": "CAACAgQAAxkDAAI4GGNtY_Y9kN6nzxvk8KwX8SnwTntmAAIvAgACX1eZAAH4u547rBAiBCsE",
+ "y_3": "CAACAgQAAxkDAAI4GWNtY_dJwM67rmUFcLEtByedoFJdAAIxAgACX1eZAAFBQ00TMrpMeisE",
+ "y_4": "CAACAgQAAxkDAAI4GmNtY_d6JUufI61BWnqI4DTVRxMVAAIzAgACX1eZAAF7IOqIuGqyDSsE",
+ "y_5": "CAACAgQAAxkDAAI4G2NtY_dxij19aBCA7Tjf5ytWzXgNAAI1AgACX1eZAAHyIiYzI-E-LisE",
+ "y_6": "CAACAgQAAxkDAAI4HGNtY_hPQ2iuWWmADOUYR-P-nNVFAAI3AgACX1eZAAH_E8fuZ374hysE",
+ "y_7": "CAACAgQAAxkDAAI4HWNtY_jp9tXZ3lpAV83tzDcazcA4AAI5AgACX1eZAAHPK6qSI6Ku_CsE",
+ "y_8": "CAACAgQAAxkDAAI4HmNtY_kQwEGUW6F38bBIYXfspzarAAI7AgACX1eZAAHXiL4XwJi0eysE",
+ "y_9": "CAACAgQAAxkDAAI4H2NtY_kJ_ofl80XkaVobKpd-IgqQAAI9AgACX1eZAAGG_opl6vQSOCsE",
+ "y_draw": "CAACAgQAAxkDAAI4IGNtY_qbKj2mnuJVlTai4F6se8MNAAI_AgACX1eZAAFrjyuhcA2ksysE",
+ "y_skip": "CAACAgQAAxkDAAI4IWNtY_rKy-RTeKjfZT0RAYNNreVhAAJDAgACX1eZAAF1m63alvMoxysE",
+ "y_reverse": "CAACAgQAAxkDAAI4ImNtY_vaX0rQZ_5ZUeFTpMa2ZQABOwACQQIAAl9XmQABCHpDm7MPbakrBA",
+ "draw_four": "CAACAgQAAxkDAAI4I2NtY_vr1Fa4_Q2Y6dxOopNX7sSsAAL1AQACX1eZAAHXOgABZUCgVkkrBA",
+ "colorchooser": "CAACAgQAAxkDAAI4JGNtY_vpncCbuHH2xDLokQWxUAXSAALzAQACX1eZAAHI5jbpFQE9bCsE",
+ "option_draw": "CAACAgQAAxkDAAI4JWNtY_zry4NT2JAlWjTryYiuec4nAAL4AgACX1eZAAH-TdXSlvEa2ysE",
+ "option_pass": "CAACAgQAAxkDAAI4JmNtY_yMlr6rB3UdTikR3zFCk8kVAAL6AgACX1eZAAFuilR5QnD-VysE",
+ "option_bluff": "CAACAgQAAxkDAAI4J2NtY_2Dmt5Mi4iZhsUh32OeNVe7AALKAgACX1eZAAHBw478rNqN0CsE",
+ "option_info": "CAACAgQAAxkDAAI4KGNtY_3tO0Sxhu5NzF1UA3tdUnklAALEAgACX1eZAAGi2Qy93IIQwisE"
+ },
+ "STICKERS_GREY": {
+ "b_0": "CAACAgQAAxkDAAI4KWNtY_3SM2AGtecbGE8XDjlWvcKxAAJFAgACX1eZAAHwXYFNZhQaIysE",
+ "b_1": "CAACAgQAAxkDAAI4KmNtY_7zNsvijvvGZAJmuxcYVgizAAJHAgACX1eZAAF_ZxC64wgdNCsE",
+ "b_2": "CAACAgQAAxkDAAI4K2NtY_4z7XEHPzcliqJth5G3ds6vAAJJAgACX1eZAAF-GuNgJ25IAAErBA",
+ "b_3": "CAACAgQAAxkDAAI4LGNtY_9ZPE9nPCPJQ0Rjf_zOkTsiAAJLAgACX1eZAAHIJQ71XJ39mCsE",
+ "b_4": "CAACAgQAAxkDAAI4LWNtY_--OWOFczobsp10PPj5p9pZAAJNAgACX1eZAAEjmR2mhJ8SsSsE",
+ "b_5": "CAACAgQAAxkDAAI4LmNtZAABTkAAAT7kcgxZkdA3rcZmxM0AAk8CAAJfV5kAASN8DC8z_yexKwQ",
+ "b_6": "CAACAgQAAxkDAAI4L2NtZAABOSkvi7YF9opHBHILrQukJwACUQIAAl9XmQABv35eqFpp188rBA",
+ "b_7": "CAACAgQAAxkDAAI4MGNtZAABcb94kfODfzBiW7R6caIITgACUwIAAl9XmQABv8VaivrtncwrBA",
+ "b_8": "CAACAgQAAxkDAAI4MWNtZAEPZcxI8yZZJ7mtvLEhRyQyAAJVAgACX1eZAAF8hUb4bS_NdCsE",
+ "b_9": "CAACAgQAAxkDAAI4MmNtZAHG55HKa6LNKc496jAPrUCzAAJXAgACX1eZAAGXAmJ0BKvi1ysE",
+ "b_draw": "CAACAgQAAxkDAAI4M2NtZALeN87Xgly5X7j5XK0dfaznAAJZAgACX1eZAAFS-DsDXK7zdisE",
+ "b_skip": "CAACAgQAAxkDAAI4NGNtZAJR4ZxfKgABx3HNLp-9w8fNagACXQIAAl9XmQABc7AYk0bGSHorBA",
+ "b_reverse": "CAACAgQAAxkDAAI4NWNtZAKP0DU5ZIh-4eID9fwEqWDhAAJbAgACX1eZAAHRLf8w4EEJfysE",
+ "g_0": "CAACAgQAAxkDAAI4NmNtZAMTsoTxk-Gzg61XUbgiWmuDAAJjAgACX1eZAAG_c8FzjSBlOCsE",
+ "g_1": "CAACAgQAAxkDAAI4N2NtZAOMsFWlo1a6VbET_L4Z33qjAAJlAgACX1eZAAH2R3CHmHduZCsE",
+ "g_2": "CAACAgQAAxkDAAI4OGNtZASmomincPijzQaGuhzS4NT3AAJnAgACX1eZAAHB14u8vZ5pjSsE",
+ "g_3": "CAACAgQAAxkDAAI4OWNtZATXrH2F0kmklBKkx5-yLbqeAAJpAgACX1eZAAFaZGnJmMcN9CsE",
+ "g_4": "CAACAgQAAxkDAAI4OmNtZARrtuTkDtrmFwSWGCMNNyzVAAJrAgACX1eZAAF3KxLEqQq8KysE",
+ "g_5": "CAACAgQAAxkDAAI4O2NtZAXsq9mIqylmXkuqblUSZ_s5AAJtAgACX1eZAAGObwogvTEInCsE",
+ "g_6": "CAACAgQAAxkDAAI4PGNtZAXYyNLL6UnAXV2J5fcYDSjcAAJvAgACX1eZAAEpOGFMRnLGmSsE",
+ "g_7": "CAACAgQAAxkDAAI4PWNtZAYp5RXbOKe2_RQkDLNHRnQsAAJxAgACX1eZAAEe_yu4DVELEisE",
+ "g_8": "CAACAgQAAxkDAAI4PmNtZAZuRr1ubCO9SBPYf5uVwxOVAAJzAgACX1eZAAH26plyNxWZuCsE",
+ "g_9": "CAACAgQAAxkDAAI4P2NtZAZ-4ux439AfgakLYhj7NkL7AAJ1AgACX1eZAAGrwYoTMk8UPSsE",
+ "g_draw": "CAACAgQAAxkDAAI4QGNtZAcDJt3SZBIXhpzxAw-0pCjgAAJ3AgACX1eZAAFnlFIJWhbZIysE",
+ "g_skip": "CAACAgQAAxkDAAI4QWNtZAdu6EvL3cTpvKgvVvS5TM8oAAJ7AgACX1eZAAFO5CqgPxquYSsE",
+ "g_reverse": "CAACAgQAAxkDAAI4QmNtZAhYEij-J99P6WZprlvTrO1FAAJ5AgACX1eZAAE9cd3JVwlSEisE",
+ "r_0": "CAACAgQAAxkDAAI4Q2NtZAhJMx2vsEJ0VqZf4K4vnICEAAJ9AgACX1eZAAEZAg2nRervSCsE",
+ "r_1": "CAACAgQAAxkDAAI4RGNtZAggA5W5F360ygp-Kt5511ZGAAJ_AgACX1eZAAFtLPMD6heoDysE",
+ "r_2": "CAACAgQAAxkDAAI4RWNtZAneP8mxTRUYpxCIcSZxrRzaAAKBAgACX1eZAAGuvzFU0Su89SsE",
+ "r_3": "CAACAgQAAxkDAAI4RmNtZAkm-2Z3z4dgngqsNQKlAAEUIgACgwIAAl9XmQABBRY8MBWexokrBA",
+ "r_4": "CAACAgQAAxkDAAI4R2NtZAr32JAr0Q5mSzPrZuPKAAEMAAOFAgACX1eZAAHZFzRnwree-ysE",
+ "r_5": "CAACAgQAAxkDAAI4SGNtZAo06aPW8Bt2bEfhuAwYIAihAAKHAgACX1eZAAHsdpjtu9I2ISsE",
+ "r_6": "CAACAgQAAxkDAAI4SWNtZArDcMo4iVhDv3V2PkjmODGWAAKJAgACX1eZAAG2D__a-tqZBSsE",
+ "r_7": "CAACAgQAAxkDAAI4SmNtZAsNc-unKFxRAUfRgRpIu8zGAAKLAgACX1eZAAGXaAtw5YFztSsE",
+ "r_8": "CAACAgQAAxkDAAI4S2NtZAtXBBjw_QmbUnPCqOjcPciqAAKNAgACX1eZAAGkCOaURWQl8CsE",
+ "r_9": "CAACAgQAAxkDAAI4TGNtZAxdvNd9s7XbaETEDpraDSB8AAKPAgACX1eZAAH-WS6bmv9CgSsE",
+ "r_draw": "CAACAgQAAxkDAAI4TWNtZAz-9sSylYycGwF82_5ceXLOAAKRAgACX1eZAAF2dldgt636fysE",
+ "r_skip": "CAACAgQAAxkDAAI4TmNtZAwwZq3xqWgdKCELX9yXNNDHAAKVAgACX1eZAAGedr9LYgVebCsE",
+ "r_reverse": "CAACAgQAAxkDAAI4T2NtZA1_h1jpVObJt7ZnGWC0EJu_AAKTAgACX1eZAAECR8T0lu-KmysE",
+ "y_0": "CAACAgQAAxkDAAI4UGNtZA3XHBEqHJ4oD2s1vu019fCAAAKXAgACX1eZAALmpUbJzkaKKwQ",
+ "y_1": "CAACAgQAAxkDAAI4UWNtZA70oPDw_EYnua3I_yHnoU0HAAKZAgACX1eZAAGB_02-C22PkysE",
+ "y_2": "CAACAgQAAxkDAAI4UmNtZA73r_BBydbo0QL4Lrp6zzRgAAKbAgACX1eZAAHVmZUJxJwqmCsE",
+ "y_3": "CAACAgQAAxkDAAI4U2NtZA7ITY2cWf3hZhbqbRFA2rznAAKdAgACX1eZAAGnajv8YZQj-ysE",
+ "y_4": "CAACAgQAAxkDAAI4VGNtZA_w89jaIqKJT3mJ3jf4sNfqAAKfAgACX1eZAAEmxeENpAa35SsE",
+ "y_5": "CAACAgQAAxkDAAI4VWNtZA9pJt03yLW1UVqmabBu03CRAAKhAgACX1eZAAH2evQmPPzx8isE",
+ "y_6": "CAACAgQAAxkDAAI4VmNtZBBLaA_cEcY1-cmo4oRl7kFUAAKjAgACX1eZAAGYOfBpuoRg_CsE",
+ "y_7": "CAACAgQAAxkDAAI4V2NtZBC1E-0IzKlEqkiFlLtGQ2djAAKlAgACX1eZAAFYxwrVWROuiysE",
+ "y_8": "CAACAgQAAxkDAAI4WGNtZBDuCE40_AciHh4BlfOxvd4EAAKnAgACX1eZAAF10j1L6rASCSsE",
+ "y_9": "CAACAgQAAxkDAAI4WWNtZBERcGe9cafGmVQMrn--6VyEAAKpAgACX1eZAAGV1nEmuqjoJCsE",
+ "y_draw": "CAACAgQAAxkDAAI4WmNtZBHW7Ik5O4gDp80GEnME_8opAAKrAgACX1eZAAGfJ2XK_ooNFisE",
+ "y_skip": "CAACAgQAAxkDAAI4W2NtZBLpZ4ilI48Wl42H2--LNZleAAKvAgACX1eZAAEVSSkTcHxJXCsE",
+ "y_reverse": "CAACAgQAAxkDAAI4XGNtZBJeXdZLAWEB9hQVadvba2mLAAKtAgACX1eZAAEiP9aakPoiDysE",
+ "draw_four": "CAACAgQAAxkDAAI4XWNtZBOEsZAZxOHFAttWBmLf5WSOAAJhAgACX1eZAAHWx9PCWaCqkysE",
+ "colorchooser": "CAACAgQAAxkDAAI4XmNtZBPR9vYmNzz7P7Hq24wrLE16AAJfAgACX1eZAAH4WHYrSCRGIisE"
+ },
+ "CARDS": {
+ "SPECIALS": ["draw_four","colorchooser"],
+ "SPECIALS_INFO": {
+ "draw_four": [4,"."],
+ "colorchooser": [4,"^(?!.*draw).*$"]
+ },
+ "THEME_CARDS": [],
+ "COLORS": ["b","g","r","y"],
+ "COLOR_ICONS": {
+ "b": "🟦",
+ "g": "🟩",
+ "r": "🟥",
+ "y": "🟨",
+ "x": "❓"
+ },
+ "VALUES": ["0","1","2","3","4","5","6","7","8","9","draw","skip","reverse"],
+ "VALUES_ICONS": {
+ "0": "0️⃣",
+ "1": "1️⃣",
+ "2": "2️⃣",
+ "3": "3️⃣",
+ "4": "4️⃣",
+ "5": "5️⃣",
+ "6": "6️⃣",
+ "7": "7️⃣",
+ "8": "8️⃣",
+ "9": "9️⃣",
+ "draw": "+2",
+ "skip": "🚫",
+ "reverse": "🔁",
+ "colorchooser": "🌈",
+ "draw_four": "+4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/cards/colorblind.json b/cards/colorblind.json
new file mode 100644
index 0000000..7326074
--- /dev/null
+++ b/cards/colorblind.json
@@ -0,0 +1,179 @@
+{
+ "STICKERS": {
+ "b_0": "CAACAgQAAxkBAAIH7WWViIfZuQW92q6yTE6BQfXj-UWDAAL4EAACSPyQUbrUYl3Db1A4HgQ",
+ "b_1": "CAACAgQAAxkBAAIH8GWViIgsVZgNZsZYg_RaskmJCKJZAAJxEwAC74SYUVPWLgtyo7g5HgQ",
+ "b_2": "CAACAgQAAxkBAAIH82WViIklUQmKnrock1_yNBqqMhVJAALTFAACpWGZUfKsVIBvG1-PHgQ",
+ "b_3": "CAACAgQAAxkBAAIH9mWViIrIYOGeBv0MxhC6FWldvYQyAAI2DQACf7GYUd6_wh0X-J7THgQ",
+ "b_4": "CAACAgQAAxkBAAIH-WWViIvJL4MFx0Q10L4Y7J6tTgzOAAKVDgACNlqZUVwgv-lUHlwXHgQ",
+ "b_5": "CAACAgQAAxkBAAIH_GWViIuh16wb9Nb28sRG5uSV6ab5AAKuDAAC4vmZUe8QFnwIbmnlHgQ",
+ "b_6": "CAACAgQAAxkBAAIH_2WViIzaZQQttfD0R03vcmRiKyQWAAIOFQAC4ZGZUZBi-YQ7FzMEHgQ",
+ "b_7": "CAACAgQAAxkBAAIIAmWViI0Ur0TXzVyntbIFiUF70ngzAAIjEQAC_92YUS5W3f2SSBmDHgQ",
+ "b_8": "CAACAgQAAxkBAAIIBWWViI5BriPVz45ADl9kKBP73JTkAALbDQACgTqRUcbtaxxXgXaHHgQ",
+ "b_9": "CAACAgQAAxkBAAIICGWViI8P2ffbeW1mFnEG4sjeJ58MAAK9DQACtEyZUStZpJE_-CIpHgQ",
+ "b_draw": "CAACAgQAAxkBAAIIC2WViJGgz0IpM8FbgtwmtZVLeuj6AAKXDgACMX-QUc9ZKhgoHC3BHgQ",
+ "b_skip": "CAACAgQAAxkBAAIIDmWViJIq_Ib0JQ7UQ5clASSpFNuyAAL5DAACBtmYUaW1SWeyUM1RHgQ",
+ "b_reverse": "CAACAgQAAxkBAAIIEWWViJOq0hbTlIjYSLZw-7ct8OquAAKiDwACoMmZUQlCnlahydSdHgQ",
+ "g_0": "CAACAgQAAxkBAAIIFGWViJbNqv-dn_a5j2LuBSFhGKOPAAJODgAChDGYUXTuNH-98HjGHgQ",
+ "g_1": "CAACAgQAAxkBAAIIF2WViJd4nHU1y1ztouceDT1cfDHuAAJCDgACGSCYUaWyJ_2c21fCHgQ",
+ "g_2": "CAACAgQAAxkBAAIIGmWViJipH6ctdppuXX21KV-hUEl2AALYFQAC57-YUYQ2I9KNnFuJHgQ",
+ "g_3": "CAACAgQAAxkBAAIIHWWViJm1DwWP9SJoSSP-YCAvhaGjAAKnDgACM72YUcA7PwoPafsHHgQ",
+ "g_4": "CAACAgQAAxkBAAIIIGWViJrgai_4_1GWuNTq1SrwHoY6AAJGEAACoXuQURzAtqUt8N9oHgQ",
+ "g_5": "CAACAgQAAxkBAAIII2WViJuQB3lW1m169IogS1bu-dd2AAICDwACpcuYUcnKDYX_Jtu_HgQ",
+ "g_6": "CAACAgQAAxkBAAIIJmWViJ02ZaybQAg82BqZBXYSRQ_xAAJWFgAC0ruZUaKBGr8SQK5WHgQ",
+ "g_7": "CAACAgQAAxkBAAIIKWWViJ55lDw6091FOyalYKntdBRkAALZEgACtxyYUSP7wshU0BuyHgQ",
+ "g_8": "CAACAgQAAxkBAAIILGWViKIstE4URA2mdsL1qn6GVf-cAALoDAAC6-aYUcFFqsyKY5ZrHgQ",
+ "g_9": "CAACAgQAAxkBAAIIL2WViKVGxSTn0Do5onLQ3Ofzka4LAAITEQACw2SZUWvwNocY7CyCHgQ",
+ "g_draw": "CAACAgQAAxkBAAIIMmWViKdf2wdcUNpvrsc_u8cyzSpnAAKEDwACvFiZUf1yHkmnTQABuh4E",
+ "g_skip": "CAACAgQAAxkBAAIINWWViKiQLKGbJaNtyCoxw_Qyc0lDAAJsFwACqKeRUQ7CQm0NF-TaHgQ",
+ "g_reverse": "CAACAgQAAxkBAAIIOGWViKlE1G7Dq9BINwhi5e17RV_dAAIyEAAC9U6YUYfbzgshjtx6HgQ",
+ "r_0": "CAACAgQAAxkBAAIIO2WViKrN7GshtcQ44nYDgpXlvqQ9AALoDwACf9yRUc9YeqIFH_eMHgQ",
+ "r_1": "CAACAgQAAxkBAAIIPmWViKsB7yhwRpa-SkjkqIfqiDFeAALlDQACD4iZUTH5uVAjzxGtHgQ",
+ "r_2": "CAACAgQAAxkBAAIIQWWViKx4deWPc3S0fDskZsyKZ5D1AALWDQAC4yOZUSRCxWE3j0MwHgQ",
+ "r_3": "CAACAgQAAxkBAAIIRGWViK6lgng5gfXIYThsk1g76KS0AAKWEAACrLiZUdai-hpZ9Ab-HgQ",
+ "r_4": "CAACAgQAAxkBAAIIR2WViK_83kuSnMJ8nFSoi6VDxkAFAAIJGgACp_-RUWeXwAIvWuOnHgQ",
+ "r_5": "CAACAgQAAxkBAAIISmWViLIafepcDzkS08BMqkq7rZE3AAJXDwACOZqZUQS_ZNV4v1ylHgQ",
+ "r_6": "CAACAgQAAxkBAAIITWWViLWZySDZcTEnc66aLKx9URsxAAIdDgAC65SRUfYj7KfqdEFUHgQ",
+ "r_7": "CAACAgQAAxkBAAIIUGWViLZK1GPE83RP8VZ1G134HkzHAAI1DwACs_WRUXmuoe2TSlD4HgQ",
+ "r_8": "CAACAgQAAxkBAAIIU2WViLjJbF2IM6EfGh7Fi7Eylv_hAALUEAAC5AORUQ-Iih1SLpa_HgQ",
+ "r_9": "CAACAgQAAxkBAAIIVmWViLlb9lZw4rLF8zE92W492Y2WAALZDgACrWeQUczrPkLQp9_ZHgQ",
+ "r_draw": "CAACAgQAAxkBAAIIWWWViLqtM1UOYophQ9hlsIO-6CR2AAK9DwACpm6QUYSaRFKhJlATHgQ",
+ "r_skip": "CAACAgQAAxkBAAIIXGWViLw3gedDiTOUIuNBrUdTOaWNAAJGDgACnxuZUU4LrF0RllHDHgQ",
+ "r_reverse": "CAACAgQAAxkBAAIIX2WViL3N06HgWmOmAWwRTuf19J92AALlEAACDz2ZUTz4Rj_YOJ9wHgQ",
+ "y_0": "CAACAgQAAxkBAAIIYmWViL9dzEK2pkuaVGZDpGLHIh3aAAKtDgACvlaZUc1_r14GfZg4HgQ",
+ "y_1": "CAACAgQAAxkBAAIIZWWViMDADxyaFhJtHoj2OqLeJuXmAAJyDwACaoqZUd9V5Qje7-LsHgQ",
+ "y_2": "CAACAgQAAxkBAAIIaGWViMGoxYdaIaoz-5lQlAABhnZCEgACkA4AAuDImFEQ8qjFlcKplR4E",
+ "y_3": "CAACAgQAAxkBAAIIa2WViMLZtKOb5eAEYKPfbGQT4AXoAAL5DAACauiYUYCpWf5jw3vbHgQ",
+ "y_4": "CAACAgQAAxkBAAIIbmWViMIZL-SbEFuof3HZiwKxQOM-AAKNDgACY0uYUbzSTuR-DHU0HgQ",
+ "y_5": "CAACAgQAAxkBAAIIcWWViMP8mHHUUxjQTzZME_UqgOucAAKpDwACaBiYUfX97L9sxA1jHgQ",
+ "y_6": "CAACAgQAAxkBAAIIdGWViMQBqzJYS4zfGHLbPwac4xMnAAJ1DQAC5ZyYURsb-CbXAZgJHgQ",
+ "y_7": "CAACAgQAAxkBAAIId2WViMUli35f0n4JpRxn2z7TsxIBAALpDAAClAABmFEjw59G8tfe-R4E",
+ "y_8": "CAACAgQAAxkBAAIIemWViMYHsYK8A8zotkuQL7N9CUGqAAIBEAACL7aRUSJ8n471ZWKWHgQ",
+ "y_9": "CAACAgQAAxkBAAIIfWWViMbbYCRyvT1RHSb5LAxtpQFcAALEDQACFDyYUeOeX21QIdIsHgQ",
+ "y_draw": "CAACAgQAAxkBAAIIgGWViMeJKRPlJmIbw7w6-5EyzSRFAALPDgACdxmZUSEuFfXt6pfwHgQ",
+ "y_skip": "CAACAgQAAxkBAAIIg2WViMmxpEHw_qCaJGGFGv3FCvokAAI-FgACIZuQUb2Gm0U8uCPvHgQ",
+ "y_reverse": "CAACAgQAAxkBAAIIhmWViMomxSr2ZFGL4S45yqm9XlMRAAJPEAACqAWZUQlEHDh5aCcPHgQ",
+ "draw_four": "CAACAgQAAxkBAAIIiWWViM99yb-oIkGdZl69f-zLrDcjAAJhEAACueSZUaapceGNYQHEHgQ",
+ "colorchooser": "CAACAgQAAxkBAAIIjGWViNByhKosbeWF0U5byjtnNxQCAAKuDgAC9faZUSnH8GIMgTmdHgQ",
+ "option_draw": "CAACAgQAAxkBAAIIj2WViNj1FXsNWL95ZRUbPZJXJoX7AAL4AgACX1eZAAH-TdXSlvEa2x4E",
+ "option_pass": "CAACAgQAAxkBAAIIkmWViN0_ybsx490zyv0HFLw2sOzzAAL6AgACX1eZAAFuilR5QnD-Vx4E",
+ "option_bluff": "CAACAgQAAxkBAAIIlWWViOawFS22nDjGn3cB6svJ7ggkAALKAgACX1eZAAHBw478rNqN0B4E",
+ "option_info": "CAACAgQAAxkBAAIImGWViPjlUoOmQw7LWRFlgDq2a5u8AALEAgACX1eZAAGi2Qy93IIQwh4E"
+ },
+ "STICKERS_GREY": {
+ "b_0": "CAACAgQAAxkBAAIIm2WViPpU7jFNtr5MybalgKn-vxneAAJFAgACX1eZAAHwXYFNZhQaIx4E",
+ "b_1": "CAACAgQAAxkBAAIInmWViPtl57X2VaM5XSb6nr1YGSqZAAJHAgACX1eZAAF_ZxC64wgdNB4E",
+ "b_2": "CAACAgQAAxkBAAIIoWWViP0cJwFXikbDcrJ00t1K_xJXAAJJAgACX1eZAAF-GuNgJ25IAAEeBA",
+ "b_3": "CAACAgQAAxkBAAIIpGWViP4BDkd8vKhBxGnHvbjRu_8CAAJLAgACX1eZAAHIJQ71XJ39mB4E",
+ "b_4": "CAACAgQAAxkBAAIIp2WViP7A3X1R9vjYv0bmvOY-rUPIAAJNAgACX1eZAAEjmR2mhJ8SsR4E",
+ "b_5": "CAACAgQAAxkBAAIIqmWViP9fFkit6AU8yMRBi0nbvU6CAAJPAgACX1eZAAEjfAwvM_8nsR4E",
+ "b_6": "CAACAgQAAxkBAAIIrWWViQABRYTEtaNJlrWkobC-DWakRQACUQIAAl9XmQABv35eqFpp188eBA",
+ "b_7": "CAACAgQAAxkBAAIIsGWViQEyYkmw3Hp_6yEuDEZPg_UGAAJTAgACX1eZAAG_xVqK-u2dzB4E",
+ "b_8": "CAACAgQAAxkBAAIIs2WViQHf7qbfR_X1dOxCxDyKQVJ6AAJVAgACX1eZAAF8hUb4bS_NdB4E",
+ "b_9": "CAACAgQAAxkBAAIItmWViQLMnaQOj_1KJ4QB7v7CtgmlAAJXAgACX1eZAAGXAmJ0BKvi1x4E",
+ "b_draw": "CAACAgQAAxkBAAIIuWWViQQt6MhXUnHrxX6ujGLp9OoUAAJZAgACX1eZAAFS-DsDXK7zdh4E",
+ "b_skip": "CAACAgQAAxkBAAIIvGWViQXzcWvBVYYuv8gUbBvJmWNzAAJdAgACX1eZAAFzsBiTRsZIeh4E",
+ "b_reverse": "CAACAgQAAxkBAAIIv2WViQYnXthYtIst_A_lYy9wsFJUAAJbAgACX1eZAAHRLf8w4EEJfx4E",
+ "g_0": "CAACAgQAAxkBAAIIwmWViQfpxDfIp0PyGemF3zYUIOmgAAJjAgACX1eZAAG_c8FzjSBlOB4E",
+ "g_1": "CAACAgQAAxkBAAIIxWWViQgejt9YHBrForCHSWyvLnqtAAJlAgACX1eZAAH2R3CHmHduZB4E",
+ "g_2": "CAACAgQAAxkBAAIIyGWViQnnGcwMI9BRuuD5XkWTP2xQAAJnAgACX1eZAAHB14u8vZ5pjR4E",
+ "g_3": "CAACAgQAAxkBAAIIy2WViQq0QobbZleDp9ZJpFEbdmrMAAJpAgACX1eZAAFaZGnJmMcN9B4E",
+ "g_4": "CAACAgQAAxkBAAIIzmWViQpJScW-f97n0rQpOSOYYAeSAAJrAgACX1eZAAF3KxLEqQq8Kx4E",
+ "g_5": "CAACAgQAAxkBAAII0WWViQteMUvnKyrbndV_TWRSpMuKAAJtAgACX1eZAAGObwogvTEInB4E",
+ "g_6": "CAACAgQAAxkBAAII1GWViQxEufLsZ6qPMt_0muYHN0c4AAJvAgACX1eZAAEpOGFMRnLGmR4E",
+ "g_7": "CAACAgQAAxkBAAII12WViQ38LxBaAsypjKdrLorXOGB1AAJxAgACX1eZAAEe_yu4DVELEh4E",
+ "g_8": "CAACAgQAAxkBAAII2mWViQ5o2Qj2SD-2uqkvRLIkpY74AAJzAgACX1eZAAH26plyNxWZuB4E",
+ "g_9": "CAACAgQAAxkBAAII3WWViQ4X_eX6VuMP3gmi0Z8WUiIPAAJ1AgACX1eZAAGrwYoTMk8UPR4E",
+ "g_draw": "CAACAgQAAxkBAAII4GWViQ-wjvGkjoKeN7G_VN7QeAbFAAJ3AgACX1eZAAFnlFIJWhbZIx4E",
+ "g_skip": "CAACAgQAAxkBAAII42WViRBlqJS24Dpe9jckZjx9NhFrAAJ7AgACX1eZAAFO5CqgPxquYR4E",
+ "g_reverse": "CAACAgQAAxkBAAII5mWViRGErVTAmwzzL8Gaw6m1uEJWAAJ5AgACX1eZAAE9cd3JVwlSEh4E",
+ "r_0": "CAACAgQAAxkBAAII6WWViRPUrdPmRLxJB_wPYSEz9VzJAAJ9AgACX1eZAAEZAg2nRervSB4E",
+ "r_1": "CAACAgQAAxkBAAII7GWViRTYSpKji8JFsJ7grOJpqR63AAJ_AgACX1eZAAFtLPMD6heoDx4E",
+ "r_2": "CAACAgQAAxkBAAII72WViRSJl1uLaIrhIlvDHumJ9WW7AAKBAgACX1eZAAGuvzFU0Su89R4E",
+ "r_3": "CAACAgQAAxkBAAII8mWViRWQGHlRWTZ9izrjtocY12kKAAKDAgACX1eZAAEFFjwwFZ7GiR4E",
+ "r_4": "CAACAgQAAxkBAAII9WWViRYsYsaPYMtVNqEQI14epvFuAAKFAgACX1eZAAHZFzRnwree-x4E",
+ "r_5": "CAACAgQAAxkBAAII-GWViRc1hhpZfuknLhDcTFE4fAwkAAKHAgACX1eZAAHsdpjtu9I2IR4E",
+ "r_6": "CAACAgQAAxkBAAII-2WViRhw6hgkC2hTtz5M01PWq4iaAAKJAgACX1eZAAG2D__a-tqZBR4E",
+ "r_7": "CAACAgQAAxkBAAII_mWViRh0xCPOW62vVVX3eW8qVcYXAAKLAgACX1eZAAGXaAtw5YFztR4E",
+ "r_8": "CAACAgQAAxkBAAIJAWWViRna-E8mEMrtaJgEN6kadagKAAKNAgACX1eZAAGkCOaURWQl8B4E",
+ "r_9": "CAACAgQAAxkBAAIJBGWViRpz1cu-hntkeMicpiUWFV1fAAKPAgACX1eZAAH-WS6bmv9CgR4E",
+ "r_draw": "CAACAgQAAxkBAAIJB2WViRvF9IaFuwLG8Aml_lXaIuVUAAKRAgACX1eZAAF2dldgt636fx4E",
+ "r_skip": "CAACAgQAAxkBAAIJCmWViRz7AyvfbVzBEGknm69vAlgCAAKVAgACX1eZAAGedr9LYgVebB4E",
+ "r_reverse": "CAACAgQAAxkBAAIJDWWViR3n0qcDtix_O4w8xWjd9U_1AAKTAgACX1eZAAECR8T0lu-Kmx4E",
+ "y_0": "CAACAgQAAxkBAAIJEGWViR87oSq_59nWAAFy01lTX4JdxgAClwIAAl9XmQAC5qVGyc5Gih4E",
+ "y_1": "CAACAgQAAxkBAAIJE2WViSD6-Sq3oTIMqVz-J9zOmIddAAKZAgACX1eZAAGB_02-C22Pkx4E",
+ "y_2": "CAACAgQAAxkBAAIJFmWViSEE44UOkY4s8r0LLBtvmjcbAAKbAgACX1eZAAHVmZUJxJwqmB4E",
+ "y_3": "CAACAgQAAxkBAAIJGWWViSGVT72rqzZe98CDc4lP66KnAAKdAgACX1eZAAGnajv8YZQj-x4E",
+ "y_4": "CAACAgQAAxkBAAIJHGWViSLM42LKJuClX_EVkJIUqhb8AAKfAgACX1eZAAEmxeENpAa35R4E",
+ "y_5": "CAACAgQAAxkBAAIJH2WViSMRJDYER1V6jctmpe4_LnjBAAKhAgACX1eZAAH2evQmPPzx8h4E",
+ "y_6": "CAACAgQAAxkBAAIJImWViSTTa8PENvS4oBsjCjyxsOq0AAKjAgACX1eZAAGYOfBpuoRg_B4E",
+ "y_7": "CAACAgQAAxkBAAIJJWWViSX62G9bAiolY1qdo7wt-lu_AAKlAgACX1eZAAFYxwrVWROuix4E",
+ "y_8": "CAACAgQAAxkBAAIJKGWViSYRfMC3KTuSH8FBi3GuERF3AAKnAgACX1eZAAF10j1L6rASCR4E",
+ "y_9": "CAACAgQAAxkBAAIJK2WViSaZDLJsteU3mN3JaZgxbUiQAAKpAgACX1eZAAGV1nEmuqjoJB4E",
+ "y_draw": "CAACAgQAAxkBAAIJLmWViSfj0w5rRfqv3G7Ehafi-cmIAAKrAgACX1eZAAGfJ2XK_ooNFh4E",
+ "y_skip": "CAACAgQAAxkBAAIJMWWViSiyvVRcF4fuiitl0tKoZyZ1AAKvAgACX1eZAAEVSSkTcHxJXB4E",
+ "y_reverse": "CAACAgQAAxkBAAIJNGWViSkfoWKkDlIjj5qEdo5I-W0QAAKtAgACX1eZAAEiP9aakPoiDx4E",
+ "draw_four": "CAACAgQAAxkBAAIJN2WViSw_fFBkTPJ6F984sRBdaXBDAAJhAgACX1eZAAHWx9PCWaCqkx4E",
+ "colorchooser": "CAACAgQAAxkBAAIJOmWViS0VcoFfcxzhI8MIvv7NuJZXAAJfAgACX1eZAAH4WHYrSCRGIh4E"
+ },
+ "CARDS": {
+ "SPECIALS": [
+ "draw_four",
+ "colorchooser"
+ ],
+ "SPECIALS_INFO": {
+ "draw_four": [
+ 4,
+ "."
+ ],
+ "colorchooser": [
+ 4,
+ "^(?!.*draw).*$"
+ ]
+ },
+ "THEME_CARDS": [],
+ "COLORS": [
+ "b",
+ "g",
+ "r",
+ "y"
+ ],
+ "COLOR_ICONS": {
+ "b": "blue",
+ "g": "green",
+ "r": "red",
+ "y": "yellow"
+ },
+ "VALUES": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "draw",
+ "skip",
+ "reverse"
+ ],
+ "VALUES_ICONS": {
+ "0": "0️⃣",
+ "1": "1️⃣",
+ "2": "2️⃣",
+ "3": "3️⃣",
+ "4": "4️⃣",
+ "5": "5️⃣",
+ "6": "6️⃣",
+ "7": "7️⃣",
+ "8": "8️⃣",
+ "9": "9️⃣",
+ "draw": "+2",
+ "skip": "🚫",
+ "reverse": "🔁",
+ "colorchooser": "🌈",
+ "draw_four": "+4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/cards/minimalist.json b/cards/minimalist.json
new file mode 100644
index 0000000..2aca3c7
--- /dev/null
+++ b/cards/minimalist.json
@@ -0,0 +1,190 @@
+{
+ "STICKERS": {
+ "b_0": "CAACAgEAAxkDAAEDe6tllA16pjgNwKfYPSG2fa3-RWCLZgACAwIAAsJ8kUXyk7MLF9xdBh4E",
+ "b_1": "CAACAgEAAxkDAAEDe6xllA18NuZNUwJvWlQd4oM1ET_DGQACqQMAAnHukEXmnSMIA9EHZh4E",
+ "b_2": "CAACAgEAAxkDAAEDe61llA1_v5dlOv1S_43ufmWuI9jGKwACXQIAAv_qkEVgclfo22dTXx4E",
+ "b_3": "CAACAgEAAxkDAAEDe65llA2By62MlWJL1KoSwAABXX6FJ8MAAhIDAAJ0vpBF7s5S-tulgzceBA",
+ "b_4": "CAACAgEAAxkDAAEDe69llA2EotC8Sxq2BV0_UNLFHiCraAACZwIAAhZvkUVhDXOLwAahsR4E",
+ "b_5": "CAACAgEAAxkDAAEDe7BllA2GMRqzd1XwtbPsB21ysznGggACKgMAAl3TkUU4NWqARyrisR4E",
+ "b_6": "CAACAgEAAxkDAAEDe7FllA2IGUW-kUGfNUNo1yLkEhlTKwACZQIAAkEamUXoN8eyf3WbVR4E",
+ "b_7": "CAACAgEAAxkDAAEDe7JllA2Kl-KJ4CzGnWR6bvmWdsuT3gACPgIAAr9DkUXKlfdmjxSZUx4E",
+ "b_8": "CAACAgEAAxkDAAEDe7NllA2MWfQmdO8qYnV-xd9Tm8pblgAC2AIAAqIskUUWu-bHbGOF8R4E",
+ "b_9": "CAACAgEAAxkDAAEDe7RllA2OcK42iYTR8YHEJLvqzqgZCAACkwIAAgbhkEW3VEnx24JUBh4E",
+ "b_draw": "CAACAgEAAxkDAAEDe7VllA2eJar5j6ts-sL1xCCZBaCKCQACBgMAAkYMkUVyqsDxtyrruR4E",
+ "b_skip": "CAACAgEAAxkDAAEDe7ZllA2gqoH1ykM-E62WG4JKVb0evwAC5AIAAoMOkUXTMcadXYpdLR4E",
+ "b_reverse": "CAACAgEAAxkDAAEDe7dllA2ing8hJqUzPezMWG-u9NJhlAACAwMAAlFCkEUfaBJjzqysoR4E",
+ "g_0": "CAACAgEAAxkDAAEDe7hllA2lB0XmfQX5HerEZEz37IILdwACcQIAAswfkUVCj6ddvIx5iR4E",
+ "g_1": "CAACAgEAAxkDAAEDe7lllA2nl8MoGoxPec0DhQ_rvhBoLAACDwMAApnYkEU_b4TvaFm6-B4E",
+ "g_2": "CAACAgEAAxkDAAEDe7pllA2pP4FIrMKVOnCgvgesr5hhOQACSAIAAruTkEXqutZPzXqcXx4E",
+ "g_3": "CAACAgEAAxkDAAEDe7tllA2r9sc-h0p5781yXUxmIjG30QACCwIAAqnskEWxoXpxAW_zch4E",
+ "g_4": "CAACAgEAAxkDAAEDe7xllA2tI7jBpElvA-v9_y11syRh5AACQQMAAkh4kUWGlbmFagXAQB4E",
+ "g_5": "CAACAgEAAxkDAAEDe71llA2vGXcCAxbTfq3quZMhjtfQHgACbgIAApcckUVhphMsBYqfJx4E",
+ "g_6": "CAACAgEAAxkDAAEDe75llA2xHxOm-TiqMLml4YfVgIGHugACPgIAAi_OkEUiL81ENcLfSx4E",
+ "g_7": "CAACAgEAAxkDAAEDe79llA2yzUGRwz_nGdHVmyYKXdtUIAACDQMAAhSVkEVK2TL696mHEh4E",
+ "g_8": "CAACAgEAAxkDAAEDe8BllA20x6V1fiYfPK0AAZubQti3x90AAgkCAAI68ZFFxalNVgrhumweBA",
+ "g_9": "CAACAgEAAxkDAAEDe8FllA22AtfyKfEy2D1TD9yBg_vjhwAC8gIAAvp_kEUHMIge7TYyKB4E",
+ "g_draw": "CAACAgEAAxkDAAEDe8JllA24zAKP_EPj3WxQxWoCPY4edAACRAIAAujlkEXQU7jwZxRZiB4E",
+ "g_skip": "CAACAgEAAxkBAAIM12ZfWhoZlohTFinVWlZsgdV5CCEkAAITAgACuh2QRcLStZTh5J7VHgQ",
+ "g_reverse": "CAACAgEAAxkDAAEDe8RllA29Dre8XGZlqa4AAfSEXjS9LQYAAqsCAAKkLJFFiweqZ2bqu1QeBA",
+ "r_0": "CAACAgEAAxkDAAEDe8VllA3B-RkLpk1nq0jdcwy9BoSkHgACkAIAAloBkUX_0_LhZSJczR4E",
+ "r_1": "CAACAgEAAxkDAAEDe8ZllA3EVB2FIhJGiPIrtAACEeGVkgACggIAAuUMkUXYO2A7fOgafR4E",
+ "r_2": "CAACAgEAAxkDAAEDe8dllA3GdC6M4zzPTt8hxQNIQ7slzgACGAIAAv7xkEXl-k_R6oY76x4E",
+ "r_3": "CAACAgEAAxkDAAEDe8hllA3JRFrTn-sd5PRN4xWCM90tHwACGgMAAuC2kEXPCeJ41Blilx4E",
+ "r_4": "CAACAgEAAxkDAAEDe8lllA3MMqjbGbOk65ZW-iKojTrsFAAC5QIAAr8akUWeAsacvKVD7B4E",
+ "r_5": "CAACAgEAAxkDAAEDe8pllA3O9EyO50Rao1PvMn0fED0i7gAChwIAAhmTkEXI8f4hQtAPgB4E",
+ "r_6": "CAACAgEAAxkDAAEDe8tllA7PL1JfkjtApb9xfoFTDvDd2QACyAEAAnxpkUUXkvlBf7LZaR4E",
+ "r_7": "CAACAgEAAxkDAAEDe8xllA3TwEfjLkRJOk3bCYuMd_BhgAACtAEAAoGNkUW3IDX6hbLIRR4E",
+ "r_8": "CAACAgEAAxkDAAEDe81llA3Whl0dV_B5gN-LYVHHFFzJBAAC9wEAAl1lkEX1oBklhfbG7h4E",
+ "r_9": "CAACAgEAAxkDAAEDe85llA3ZKoQVIMWcAkgHEUebPu1BkwACpAIAAkG5kEWg5cauEqb-Eh4E",
+ "r_draw": "CAACAgEAAxkDAAEDe89llA3bEXr4bslsjfbgKJxX6_soWAACbAMAAiXikEUOrMwjMnq71h4E",
+ "r_skip": "CAACAgEAAxkDAAEDe9BllA3e3VxyE6B9kKt_o0uo3gO0QgAC_gIAAsVPkUXDxwuskYP9wB4E",
+ "r_reverse": "CAACAgEAAxkDAAEDe9FllA3h6JFRqSvdtHK7AzPGKhR93QAC3gIAAqXNkEVHBrFdkXLu8B4E",
+ "y_0": "CAACAgEAAxkDAAEDe9JllA3jVjW8wkE9VFRUdbvukteHigACTgIAAsdskUUJCGkroV6nOx4E",
+ "y_1": "CAACAgEAAxkDAAEDe9NllA3mM3HzFiwpLbIZmn1y7og-ogAC6QEAApAEkEVBGUptZYFNtx4E",
+ "y_2": "CAACAgEAAxkDAAEDe9RllA3pSe6Pq6XfdXrGSUwO_XnNRwAC9QIAAumPkUWO0RtAwk-gqh4E",
+ "y_3": "CAACAgEAAxkDAAEDe9ZllA3yb8nE9KLHDwf4TpLVSQi8PwACKAMAAlZkkEX3DMzHkfKt4x4E",
+ "y_4": "CAACAgEAAxkDAAEDe9dllA31GtSoqcIH83bG6E_-e_LMGwACcwIAAvhqkUVHXHrGg4bzkB4E",
+ "y_5": "CAACAgEAAxkDAAEDe9hllA34eX3HlQVCB3yz4jE_hxkcPgACvAIAAlrSkUXmuFcRjj_Ykh4E",
+ "y_6": "CAACAgEAAxkDAAEDe9lllA38BYT4tiz3UynZ1KlgBeE9zwACjAIAAucGkEUklwtxCimr8h4E",
+ "y_7": "CAACAgEAAxkDAAEDe9pllA3_D9P4Z8gbdSrJolueNEReHgACpAIAAmLqkEW8I1ITQ-K4UR4E",
+ "y_8": "CAACAgEAAxkDAAEDe9tllA4CfpWusm9qPlMzZB4d1OZuOwACDQIAAl0VkEUjRoTZaTeIiR4E",
+ "y_9": "CAACAgEAAxkDAAEDe9xllA4F1NkFzxkbrUN-tdzZP5X7HwACtwIAAleokUWrFCx6aDoY1B4E",
+ "y_draw": "CAACAgEAAxkDAAEDe91llA4IQ-kifRI4cFbGbMZBA3rWvwACVAIAAmnbkUWKjhkSgboWox4E",
+ "y_skip": "CAACAgEAAxkDAAEDe95llA4MjLGS0nj2fCILrVq0VDOu9AAC4gEAAsUYkUVNLlmImNML9h4E",
+ "y_reverse": "CAACAgEAAxkDAAEDe99llA4QK1OuIZxHXrjpHa72GHwnQwACxAIAAn1JkEUTDAHVfy579h4E",
+ "draw_four": "CAACAgEAAxkDAAEDd9tldPH_lqQbjb_fguXSJiUEZmXMDgACCAIAAmfQkEWdQcu_mD_LxR4E",
+ "colorchooser": "CAACAgEAAxkDAAEDd9xldPICMlwKe0ZQLmNenTD1fQ3cNQACaAIAAgeNkUXMnabDbsOjOh4E",
+ "mirror": "CAACAgEAAxkBAAIJjGWXDOVcBxySviDWuqpeCBt2wzsRAALfAgACM5iRRbhn4u7C82kqHgQ",
+ "option_draw": "CAACAgEAAxkDAAEDeJpldQABh5BKyV9yoabNg_K5EBnWbAkAAtYEAAL1-6hHbSd5q2HZFrAeBA",
+ "option_pass": "CAACAgQAAxkDAAI4JmNtY_yMlr6rB3UdTikR3zFCk8kVAAL6AgACX1eZAAFuilR5QnD-VysE",
+ "option_bluff": "CAACAgQAAxkDAAI4J2NtY_2Dmt5Mi4iZhsUh32OeNVe7AALKAgACX1eZAAHBw478rNqN0CsE",
+ "option_info": "CAACAgQAAxkDAAI4KGNtY_3tO0Sxhu5NzF1UA3tdUnklAALEAgACX1eZAAGi2Qy93IIQwisE"
+ },
+ "STICKERS_GREY": {
+ "b_0": "CAACAgEAAxkDAAEDeBhldPQpr_HP5jMfg5eqmF9WwcbANwACzAEAAvMQkUW3xk9Rm7wDdB4E",
+ "b_1": "CAACAgEAAxkDAAEDeBlldPQtK30FApRgW8VPDinDZiBcMwACHAMAAhT5kEU5hLA1PG5mNx4E",
+ "b_2": "CAACAgEAAxkDAAEDeBpldPQy489pxZnGU_OJivHLZUz_rgAC8gIAAhWNkUUj2qPu53BQAR4E",
+ "b_3": "CAACAgEAAxkDAAEDeBtldPQ1QGHrATJf8y6xY1WOESH19wACywIAAoCvkEUusWPJE3SO8R4E",
+ "b_4": "CAACAgEAAxkDAAEDeBxldPQ4gNTK8wbbKPySKhH9HRQjvwACKAIAApa_kEU9N3ivQr1-1x4E",
+ "b_5": "CAACAgEAAxkDAAEDeB1ldPQ7La8udS3TXWrlx0X1-hfj-gACRwIAArP5kEVCQ9gkbL8Byh4E",
+ "b_6": "CAACAgEAAxkDAAEDeB5ldPQ-GnWfnbES5XLjjeEnCCx9QgACKQMAAqPkkUUugGSOjf9txR4E",
+ "b_7": "CAACAgEAAxkDAAEDeB9ldPRC1btFrtNIrvF2r5Cm46WbnQACWQIAAomUmUUvhGYvR8jwPh4E",
+ "b_8": "CAACAgEAAxkDAAEDeCBldPRFe3GVn8NG-kFW-6kCBfbZTwACaAIAAgg5kUUsEUnkv0FafR4E",
+ "b_9": "CAACAgEAAxkDAAEDeCFldPRIRXMxVF6-2SIuN9N2TcYSbwACSgwAAr8jkEXx2Ncg-cKr-B4E",
+ "b_draw": "CAACAgEAAxkDAAEDeCJldPRM9VR0-q4Nr1CH71nRpi3_-AACZQMAAtvQkUWdG5DeUdyYbR4E",
+ "b_skip": "CAACAgEAAxkDAAEDeCNldPRQkadczfkJ1AGbpGhP4hJoYQAClwMAAgQSkEVJkgABSqHf3RMeBA",
+ "b_reverse": "CAACAgEAAxkDAAEDeCRldPRSBY2Xe8gqahJ5uX7jhk72lgACXgIAArfzkUVdqU8Skpie5B4E",
+ "g_0": "CAACAgEAAxkDAAEDeCVldPRWthIVrMEDrpNDQkWocduO_AACcgIAAkpskEV35BNxHr8V5x4E",
+ "g_1": "CAACAgEAAxkDAAEDeCZldPRantCOaUJ5thTqgnk1aiL5QgACCwMAAs3ukUVOx82xQv9Ffx4E",
+ "g_2": "CAACAgEAAxkDAAEDeCdldPRdO7pkiMb9Jiiy5470Z8rUzAACewIAApPKkEUHSvig3w4D6R4E",
+ "g_3": "CAACAgEAAxkDAAEDeChldPRh9Wyk3_ttBrB4dKFW534KJQACNRYAAl_mkUUjJPhaXCrytR4E",
+ "g_4": "CAACAgEAAxkDAAEDeClldPRk_MvviiZl7flLtfzE_oJTLQAC2AIAAkIjkEU6INaWefsnbR4E",
+ "g_5": "CAACAgEAAxkDAAEDeCpldPRmgqPSrQI-xX4Y4tL9-ejIKQACSAMAAsXrkUU8dg1tlvXuIx4E",
+ "g_6": "CAACAgEAAxkDAAEDeCtldPRqS9IxSLuq2bC61gABw2TBEQADfgIAAtKEkEV2q3ae2QfTlR4E",
+ "g_7": "CAACAgEAAxkDAAEDeCxldPRuL0gfAcA0n2sx_f0iv5sctwACaQIAAvBfkEWujcXUoCoNkh4E",
+ "g_8": "CAACAgEAAxkDAAEDeDBldPTZGi65G5L8tGWUO3wOSixVhwACYAMAAr7jkUW_EGWLU2VY3x4E",
+ "g_9": "CAACAgEAAxkDAAEDeDFldPTatuaW2a1roWs1yQ0CknzrFAACZAIAAofZkUV4qNUOIfMGfB4E",
+ "g_draw": "CAACAgEAAxkDAAEDeDJldPTbUcBqKAzvWXOb7hYO3ebsVAAC2QIAAojIkEWLotFWFUrd9B4E",
+ "g_skip": "CAACAgEAAxkDAAEDeDNldPTdh9PvZ_VZ8XIm9Km6bX2J_QACTQIAArBokEVwbQsgazaHHB4E",
+ "g_reverse": "CAACAgEAAxkDAAEDeDRldPTd9yIAAZ4Y6szNLr_KmTCgvCgAAu8CAAKLQJFFVS-Ee507SeQeBA",
+ "r_0": "CAACAgEAAxkDAAEDeDVldPTeA_iz6315Ync-7RV5bjg8lgACMgYAAqQtkEUfzWAEmEoSsx4E",
+ "r_1": "CAACAgEAAxkDAAEDeDZldPTfPZCyQY-NBUz4YHZKVqkFdQACvgIAAhRRkUXPAAFc1XcuDSseBA",
+ "r_2": "CAACAgEAAxkDAAEDeDdldPTf3s_igw3SQLjEpVeg7cxa2AAC8wIAAn5ukEXFPt-unsEYFB4E",
+ "r_3": "CAACAgEAAxkDAAEDeDhldPTgnLoEQVmm8PXRZNjfcKT08wACHQMAAg0HkEUTAAEuHgIFMMgeBA",
+ "r_4": "CAACAgEAAxkDAAEDeDlldPTh80oMZu94S4aEgOHe_ETbzwACMgIAAloEkEU4V1zqccv4px4E",
+ "r_5": "CAACAgEAAxkBAAINHGZfWnsZDbEzrk-2D3HjMV1F65AAA6ACAAI7OJFFF9QnY0HDd4YeBA",
+ "r_6": "CAACAgEAAxkDAAEDeDtldPTjto0-gDKrLfvtOnLR3yedfwAC8QEAAh0PkUWDDCnQ0yKJ4B4E",
+ "r_7": "CAACAgEAAxkDAAEDeDxldPTj_eXDrdZOTuAgDapmmCGopgACjAIAAnyFkUWR0nnKzFE9Ox4E",
+ "r_8": "CAACAgEAAxkDAAEDeD1ldPTksKpKl4svmqhZp754lHk_4AAC1QIAAnjkkEWe22LmFa-TXx4E",
+ "r_9": "CAACAgEAAxkDAAEDeD5ldPTkK9WuHM_JGtcqX82HXids2AACBQQAAlV2kEXV6etMTirPNh4E",
+ "r_draw": "CAACAgEAAxkDAAEDeD9ldPTl95GlyWxd13otkkbwgYxnuQACIQIAArN7kEXAyhLPjeuM0B4E",
+ "r_skip": "CAACAgEAAxkDAAEDeEBldPTmDSmE_hf8iqfvTNw_MhN-DgACjQIAAgFikUUbhvkdjEvL_B4E",
+ "r_reverse": "CAACAgEAAxkDAAEDeEFldPTm_FseoIs4TkycuysDW93ClgACiwIAAvKekEWH4bB4fK_JAh4E",
+ "y_0": "CAACAgEAAxkDAAEDeEJldPUSOSBzeDwybGll4Z8UKWuTzgACzQIAAlZRkEUaN3RtvlPkhx4E",
+ "y_1": "CAACAgEAAxkDAAEDeENldPUTdMKXIDNbaFklvDnV8eyHfQAC_QIAAmS8kUWe4Qhj7djTNx4E",
+ "y_2": "CAACAgEAAxkDAAEDeERldPUTCwm7oP44jKDQXw_0v0EHFwACDAMAAkYEkEXwjgrHAngn8h4E",
+ "y_3": "CAACAgEAAxkDAAEDeEVldPUUK3_GcOUCyoAz9QxD6m21tAAC9AMAAuu9kUVv0c8dISk1Ix4E",
+ "y_4": "CAACAgEAAxkDAAEDeEZldPUUxdlEgfu7gmJvazzHtiVjLQACbwQAAp9KkUWXChzRPGdXKh4E",
+ "y_5": "CAACAgEAAxkDAAEDeEdldPUVJRjFaF2gCyeb9FI5eLHJYwACFQMAAqTfkUWYvUcRvcNxhh4E",
+ "y_6": "CAACAgEAAxkDAAEDeEhldPUWzqtfWclTzKpnM9poibfNIQACpgIAAhZ3kEW9Xv1BRth-4B4E",
+ "y_7": "CAACAgEAAxkDAAEDeElldPUWLMeeIuoZ_vL46CgPfzDTxwAC7QEAApxekEUmO5PhRBZWdx4E",
+ "y_8": "CAACAgEAAxkDAAEDeEpldPUXs-BExZa_58xEDvMRbS4_nAACfgIAAmg-kUUoRbaAW_B4HR4E",
+ "y_9": "CAACAgEAAxkDAAEDeEtldPUYcpBSMEHnXZkFkK6mAyF49AACqwIAAtsVkEVRqf1U9QqfdB4E",
+ "y_draw": "CAACAgEAAxkDAAEDeExldPUYd5oe-E69-C2kjrolu2s64wACqwIAAk1xkUXw_oyRmWZrwx4E",
+ "y_skip": "CAACAgEAAxkDAAEDeE1ldPUZ57bOPol5KNgUnLGEsWOCRQACUAIAAq70mEW_IHyXZAkgxB4E",
+ "y_reverse": "CAACAgEAAxkDAAEDeE5ldPUZlq9iapYBJlTdZv0OJ1HjiQACzwIAAiozkEUGSQFnhRdepR4E",
+ "draw_four": "CAACAgEAAxkDAAEDeE9ldPUmQloxc6_ReBmEx6mUL1GYTwACBAIAAisrmUUd5e1D0lszKB4E",
+ "colorchooser": "CAACAgEAAxkDAAEDeFBldPUxrSNyn9WqB7y9yp7QTeyTaAACDQIAAlZtkEUPHKKL4f24nR4E",
+ "mirror": "CAACAgEAAxkDAAEDeLpldRDJK0FwP0BId9Tnvf_2yBrz7AACBgIAAtSKkUWN6yeT8oqBeB4E"
+ },
+ "CARDS": {
+ "SPECIALS": [
+ "draw_four",
+ "colorchooser",
+ "mirror"
+ ],
+ "SPECIALS_INFO": {
+ "draw_four": [
+ 4,
+ "."
+ ],
+ "colorchooser": [
+ 4,
+ "^(?!.*draw).*$"
+ ],
+ "mirror": [
+ 2,
+ "draw|skip"
+ ]
+ },
+ "THEME_CARDS": [
+ "mirror"
+ ],
+ "COLORS": [
+ "b",
+ "g",
+ "r",
+ "y"
+ ],
+ "COLOR_ICONS": {
+ "b": "🟦",
+ "g": "🟩",
+ "r": "🟥",
+ "y": "🟨",
+ "x": "❓"
+ },
+ "VALUES": [
+ "0",
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "draw",
+ "skip",
+ "reverse"
+ ],
+ "VALUES_ICONS": {
+ "0": "0️⃣",
+ "1": "1️⃣",
+ "2": "2️⃣",
+ "3": "3️⃣",
+ "4": "4️⃣",
+ "5": "5️⃣",
+ "6": "6️⃣",
+ "7": "7️⃣",
+ "8": "8️⃣",
+ "9": "9️⃣",
+ "draw": "+2",
+ "skip": "🚫",
+ "reverse": "🔁",
+ "colorchooser": "🌈",
+ "draw_four": "+4",
+ "mirror": "🪞"
+ }
+ }
+}
\ No newline at end of file
diff --git a/commandlist.txt b/commandlist.txt
deleted file mode 100644
index e1aa46a..0000000
--- a/commandlist.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-new - Start a new game
-join - Join the current game
-start - Start the game
-leave - Leave the game you're in
-close - Close the game lobby
-open - Open the game lobby
-kill - Terminate the game
-kick - Kick players out of the game
-enable_translations - Enable multi-translations
-disable_translations - Disable multi-translations
-skip - Skip the current player
-notify_me - Get a message when there's a new game in this group
-help - How to use this bot?
-modes - Explanation of game modes
-settings - Language and other settings
-stats - Show statistics
-source - See source information
-news - All news about this bot
diff --git a/config-example.py b/config-example.py
new file mode 100644
index 0000000..c8ecdb0
--- /dev/null
+++ b/config-example.py
@@ -0,0 +1,12 @@
+from hydrogram import Client
+
+
+games = {}
+player_game = {}
+
+API_ID = ''
+API_HASH = ''
+
+#--- Telegram config ---
+
+bot = Client("bot", api_id=API_ID, api_hash=API_HASH, plugins=dict(root="plugins"))
diff --git a/config.json.example b/config.json.example
deleted file mode 100644
index 0639c8c..0000000
--- a/config.json.example
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "token": "token_here",
- "base_url": "https://api.telegram.org/bot",
- "admin_list": [0],
- "open_lobby": true,
- "enable_translations": false,
- "default_gamemode": "fast",
- "waiting_time": 120,
- "time_removal_after_skip": 20,
- "min_fast_turn_time": 15,
- "min_players": 2
-}
diff --git a/config.py b/config.py
deleted file mode 100644
index e5ac151..0000000
--- a/config.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import json
-
-with open("config.json") as f:
- config = json.loads(f.read())
-
-TOKEN = config.get("token")
-BASE_URL = config.get("base_url", "https://api.telegram.org/bot")
-ADMIN_LIST = config.get("admin_list", None)
-OPEN_LOBBY = config.get("open_lobby", True)
-ENABLE_TRANSLATIONS = config.get("enable_translations", False)
-DEFAULT_GAMEMODE = config.get("default_gamemode", "fast")
-WAITING_TIME = config.get("waiting_time", 120)
-TIME_REMOVAL_AFTER_SKIP = config.get("time_removal_after_skip", 20)
-MIN_FAST_TURN_TIME = config.get("min_fast_turn_time", 15)
-MIN_PLAYERS = config.get("min_players", 2)
diff --git a/database.py b/database.py
deleted file mode 100644
index d73b89e..0000000
--- a/database.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from pony.orm import Database
-
-# Database singleton
-db = Database()
diff --git a/db.py b/db.py
new file mode 100644
index 0000000..220c4bf
--- /dev/null
+++ b/db.py
@@ -0,0 +1,48 @@
+import os
+
+from tortoise import Tortoise, connections, fields
+from tortoise.backends.base.client import Capabilities
+from tortoise.models import Model
+
+
+class Chat(Model):
+ id = fields.IntField(pk=True)
+ theme = fields.CharField(max_length=255, default="classic")
+ bluff = fields.BooleanField(default=True)
+ seven = fields.BooleanField(default=False)
+ one_win = fields.BooleanField(default=False)
+ one_card = fields.BooleanField(default=False)
+ lang = fields.CharField(max_length=255, default="en-US")
+
+class User(Model):
+ id = fields.BigIntField(pk=True)
+ placar = fields.BooleanField(default=False)
+ wins = fields.IntField(default=0)
+ matches = fields.IntField(default=0)
+ cards = fields.IntField(default=0)
+ sudo = fields.BooleanField(default=False)
+ lang = fields.CharField(max_length=255, default="en-US")
+
+
+async def connect_database():
+ await Tortoise.init(
+ {
+ "connections": {
+ "bot_db": os.getenv("DATABASE_URL", "sqlite://database.sqlite")
+ },
+ "apps": {"bot": {"models": [__name__], "default_connection": "bot_db"}},
+ }
+ )
+
+ conn = connections.get("bot_db")
+ conn.capabilities = Capabilities(
+ "sqlite",
+ daemon=False,
+ requires_limit=True,
+ inline_comment=True,
+ support_for_update=False,
+ support_update_limit_order_by=False,
+ )
+
+ # Generate the schema
+ await Tortoise.generate_schemas()
diff --git a/deck.py b/deck.py
index a8852a8..fa5fb6b 100644
--- a/deck.py
+++ b/deck.py
@@ -1,83 +1,23 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import logging
-from random import shuffle
-
-import card as c
-from card import Card
-from errors import DeckEmptyError
+import random
+from card import cards
class Deck:
- """This class represents a deck of cards."""
-
- def __init__(self) -> None:
- self.cards = []
- self.graveyard = []
- self.logger = logging.getLogger(__name__)
-
- self.logger.debug(self.cards)
+ def __init__(self, theme) -> None:
+ self.cards = [
+ (color, value)
+ for _ in range(2)
+ for color in cards[theme]["CARDS"]["COLORS"]
+ for value in cards[theme]["CARDS"]["VALUES"]
+ ]
+ self.cards += [
+ ("x", car)
+ for car in cards[theme]["CARDS"]["SPECIALS"]
+ for _ in range(cards[theme]["CARDS"]["SPECIALS_INFO"][car][0])
+ ]
def shuffle(self):
- """Shuffles the deck."""
- self.logger.debug("Shuffling Deck")
- shuffle(self.cards)
-
- def draw(self):
- """Draws a card from this deck."""
- try:
- card = self.cards.pop()
- self.logger.debug("Drawing card %s", str(card))
- return card
- except IndexError as e:
- if not self.graveyard:
- raise DeckEmptyError from e
- while self.graveyard:
- self.cards.append(self.graveyard.pop())
- self.shuffle()
- return self.draw()
-
- def dismiss(self, card):
- """Returns a card to the deck."""
- if card.special:
- card.color = None
- self.graveyard.append(card)
-
- def _fill_classic_(self):
- # Fill deck with the classic card set
- self.cards.clear()
- for color in c.COLORS:
- for value in c.VALUES:
- self.cards.append(Card(color, value))
- if value != c.ZERO:
- self.cards.append(Card(color, value))
- for special in c.SPECIALS:
- for _ in range(4):
- self.cards.append(Card(None, None, special=special))
- self.shuffle()
+ random.shuffle(self.cards)
- def _fill_wild_(self):
- # Fill deck with a wild card set
- self.cards.clear()
- for color in c.COLORS:
- for value in c.WILD_VALUES:
- for _ in range(4):
- self.cards.append(Card(color, value))
- for special in c.SPECIALS:
- for _ in range(6):
- self.cards.append(Card(None, None, special=special))
- self.shuffle()
+ def draw(self, amount):
+ return [self.cards.pop(0) for _ in range(amount) if self.cards]
diff --git a/errors.py b/errors.py
deleted file mode 100644
index 748181b..0000000
--- a/errors.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-
-class NoGameInChatError(Exception):
- pass
-
-
-class AlreadyJoinedError(Exception):
- pass
-
-
-class LobbyClosedError(Exception):
- pass
-
-
-class NotEnoughPlayersError(Exception):
- pass
-
-
-class DeckEmptyError(Exception):
- pass
diff --git a/game.py b/game.py
index 349a6ca..0f5e717 100644
--- a/game.py
+++ b/game.py
@@ -1,142 +1,24 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import logging
-from datetime import datetime
-
-from telegram import Chat
-
-import card as c
-from config import ADMIN_LIST, DEFAULT_GAMEMODE, ENABLE_TRANSLATIONS, OPEN_LOBBY
+from hydrogram.types import Chat, User
from deck import Deck
class Game:
- """This class represents a game of UNO."""
-
- current_player = None
- reversed = False
- choosing_color = False
- choosing_player = False
- started = False
- draw_counter = 0
- players_won = 0
- starter = None
- mode = DEFAULT_GAMEMODE
- job = None
- owner = ADMIN_LIST
- open = OPEN_LOBBY
- translate = ENABLE_TRANSLATIONS
-
- def __init__(self, chat: Chat, thread_id: int) -> None:
+ def __init__(self, chat: Chat, theme) -> None:
self.chat = chat
- self.thread_id = thread_id
-
self.last_card = None
-
- self.deck = Deck()
-
- self.logger = logging.getLogger(__name__)
-
- @property
- def players(self):
- """Returns a list of all players in this game."""
- players = []
- if not self.current_player:
- return players
-
- current_player = self.current_player
- itplayer = current_player.next
- players.append(current_player)
- while itplayer and itplayer is not current_player:
- players.append(itplayer)
- itplayer = itplayer.next
- return players
-
- def start(self):
- if self.mode is None or self.mode != "wild":
- self.deck._fill_classic_()
- else:
- self.deck._fill_wild_()
-
- self._first_card_()
- self.started = True
-
- def set_mode(self, mode):
- self.mode = mode
-
- def reverse(self):
- """Reverses the direction of game."""
- self.reversed = not self.reversed
-
- def turn(self):
- """Marks the turn as over and change the current player."""
- self.logger.debug("Next Player")
- self.current_player = self.current_player.next
- self.current_player.drew = False
- self.current_player.turn_started = datetime.now()
- self.choosing_color = False
- self.choosing_player = False
-
- def _first_card_(self):
- # In case that the player did not select a game mode
- if not self.deck.cards:
- self.set_mode(DEFAULT_GAMEMODE)
-
- # The first card should not be a special card
- while not self.last_card or self.last_card.special:
- self.last_card = self.deck.draw()
- # If the card drawn was special, return it to the deck and loop again
- if self.last_card.special:
- self.deck.dismiss(self.last_card)
-
- self.play_card(self.last_card)
-
- def play_card(self, card):
- """Plays a card and triggers its effects.
- Should be called only from Player.play or on game start to play the
- first card.
- """
- self.deck.dismiss(self.last_card)
- self.last_card = card
-
- self.logger.info("Playing card %s", card)
- if card.value == c.SKIP:
- self.turn()
- elif card.special == c.DRAW_FOUR:
- self.draw_counter += 4
- self.logger.debug("Draw counter increased by 4")
- elif card.value == c.DRAW_TWO:
- self.draw_counter += 2
- self.logger.debug("Draw counter increased by 2")
- elif card.value == c.REVERSE:
- # Special rule for two players
- if self.current_player is self.current_player.next.next:
- self.turn()
- else:
- self.reverse()
-
- # Don't turn if the current player has to choose a color
- if card.special not in (c.CHOOSE, c.DRAW_FOUR):
- self.turn()
- else:
- self.logger.debug("Choosing Color...")
- self.choosing_color = True
-
- def choose_color(self, color):
- """Carries out the color choosing and turns the game."""
- self.last_card.color = color
- self.turn()
+ self.last_card_2 = None
+ self.next_player:User = None
+ self.deck = Deck(theme)
+ self.players = {}
+ self.is_started = False
+ self.draw = 0
+ self.chosen = None
+ self.closed = False
+ self.winner = True
+
+ def next(self):
+ if self.draw >= 0:
+ indice = list(self.players.keys()).index(self.next_player.id)
+ next_ind = (indice + 1) % len(self.players)
+ next_key = list(self.players.keys())[next_ind]
+ self.next_player = self.players[next_key]
diff --git a/game_manager.py b/game_manager.py
deleted file mode 100644
index 6099357..0000000
--- a/game_manager.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import contextlib
-import logging
-from typing import Optional
-
-from telegram import Chat
-
-from errors import (
- AlreadyJoinedError,
- LobbyClosedError,
- NoGameInChatError,
- NotEnoughPlayersError,
-)
-from game import Game
-from player import Player
-
-
-class GameManager:
- """Manages all running games by using a confusing amount of dicts."""
-
- def __init__(self) -> None:
- self.chatid_games = {}
- self.userid_players = {}
- self.userid_current = {}
- self.remind_dict = {}
-
- self.logger = logging.getLogger(__name__)
-
- def new_game(self, chat: Chat, thread_id: Optional[int] = None):
- """Create a new game in this chat."""
- chat_id = chat.id
-
- self.logger.debug("Creating new game in chat %s", str(chat_id))
- game = Game(chat, thread_id)
-
- if chat_id not in self.chatid_games:
- self.chatid_games[chat_id] = []
-
- # remove old games
- for g in list(self.chatid_games[chat_id]):
- if not g.players:
- self.chatid_games[chat_id].remove(g)
-
- self.chatid_games[chat_id].append(game)
- return game
-
- def join_game(self, user, chat):
- """Create a player from the Telegram user and add it to the game."""
- self.logger.info("Joining game with id %s", chat.id)
-
- try:
- game = self.chatid_games[chat.id][-1]
- except (KeyError, IndexError) as e:
- raise NoGameInChatError from e
-
- if not game.open:
- raise LobbyClosedError
-
- if user.id not in self.userid_players:
- self.userid_players[user.id] = []
-
- players = self.userid_players[user.id]
-
- # Don not re-add a player and remove the player from previous games in
- # this chat, if he is in one of them
- for player in players:
- if player in game.players:
- raise AlreadyJoinedError
-
- try:
- self.leave_game(user, chat)
- except NoGameInChatError:
- pass
- except NotEnoughPlayersError:
- self.end_game(chat, user)
-
- if user.id not in self.userid_players:
- self.userid_players[user.id] = []
-
- players = self.userid_players[user.id]
-
- player = Player(game, user)
- if game.started:
- player.draw_first_hand()
-
- players.append(player)
- self.userid_current[user.id] = player
-
- def leave_game(self, user, chat):
- """Remove a player from its current game."""
- player = self.player_for_user_in_chat(user, chat)
- players = self.userid_players.get(user.id, [])
-
- if not player:
- games = self.chatid_games[chat.id]
- for g in games:
- for p in g.players:
- if p.user.id == user.id:
- if p is g.current_player:
- g.turn()
-
- p.leave()
- return
-
- raise NoGameInChatError
-
- game = player.game
-
- if len(game.players) < 3:
- raise NotEnoughPlayersError
-
- if player is game.current_player:
- game.turn()
-
- player.leave()
- players.remove(player)
-
- # If this is the selected game, switch to another
- if self.userid_current.get(user.id) is player:
- if players:
- self.userid_current[user.id] = players[0]
- else:
- del self.userid_current[user.id]
- del self.userid_players[user.id]
-
- def end_game(self, chat, user):
- """End a game."""
- self.logger.info("Game in chat %s ended", chat.id)
-
- # Find the correct game instance to end
- player = self.player_for_user_in_chat(user, chat)
-
- if not player:
- raise NoGameInChatError
-
- game = player.game
-
- # Clear game
- for player_in_game in game.players:
- this_users_players = self.userid_players.get(player_in_game.user.id, [])
-
- with contextlib.suppress(ValueError):
- this_users_players.remove(player_in_game)
- if this_users_players:
- with contextlib.suppress(KeyError):
- self.userid_current[player_in_game.user.id] = this_users_players[0]
- else:
- with contextlib.suppress(KeyError):
- del self.userid_players[player_in_game.user.id]
- with contextlib.suppress(KeyError):
- del self.userid_current[player_in_game.user.id]
- self.chatid_games[chat.id].remove(game)
- if not self.chatid_games[chat.id]:
- del self.chatid_games[chat.id]
-
- def player_for_user_in_chat(self, user, chat):
- players = self.userid_players.get(user.id, [])
- return next(
- (player for player in players if player.game.chat.id == chat.id),
- None,
- )
diff --git a/genpot.sh b/genpot.sh
deleted file mode 100755
index 9c64849..0000000
--- a/genpot.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-currentVer='1.0'
-
-xgettext *.py -o ./locales/unobot.pot --foreign-user \
- --package-name="uno_bot" \
- --package-version="$currentVer" \
- --msgid-bugs-address='uno@jhoeke.de' \
- --keyword=__ \
- --keyword=_ \
- --keyword=_:1,2 \
- --keyword=__:1,2
diff --git a/images/jpg/b_0.jpg b/images/jpg/b_0.jpg
deleted file mode 100644
index 17c6cf1..0000000
Binary files a/images/jpg/b_0.jpg and /dev/null differ
diff --git a/images/jpg/b_1.jpg b/images/jpg/b_1.jpg
deleted file mode 100644
index 8a13c88..0000000
Binary files a/images/jpg/b_1.jpg and /dev/null differ
diff --git a/images/jpg/b_2.jpg b/images/jpg/b_2.jpg
deleted file mode 100644
index 1524948..0000000
Binary files a/images/jpg/b_2.jpg and /dev/null differ
diff --git a/images/jpg/b_3.jpg b/images/jpg/b_3.jpg
deleted file mode 100644
index d7e19ab..0000000
Binary files a/images/jpg/b_3.jpg and /dev/null differ
diff --git a/images/jpg/b_4.jpg b/images/jpg/b_4.jpg
deleted file mode 100644
index 4f34e06..0000000
Binary files a/images/jpg/b_4.jpg and /dev/null differ
diff --git a/images/jpg/b_5.jpg b/images/jpg/b_5.jpg
deleted file mode 100644
index e85ac46..0000000
Binary files a/images/jpg/b_5.jpg and /dev/null differ
diff --git a/images/jpg/b_6.jpg b/images/jpg/b_6.jpg
deleted file mode 100644
index a9be485..0000000
Binary files a/images/jpg/b_6.jpg and /dev/null differ
diff --git a/images/jpg/b_7.jpg b/images/jpg/b_7.jpg
deleted file mode 100644
index aa73e39..0000000
Binary files a/images/jpg/b_7.jpg and /dev/null differ
diff --git a/images/jpg/b_8.jpg b/images/jpg/b_8.jpg
deleted file mode 100644
index a6e63fb..0000000
Binary files a/images/jpg/b_8.jpg and /dev/null differ
diff --git a/images/jpg/b_9.jpg b/images/jpg/b_9.jpg
deleted file mode 100644
index e753ea2..0000000
Binary files a/images/jpg/b_9.jpg and /dev/null differ
diff --git a/images/jpg/b_draw.jpg b/images/jpg/b_draw.jpg
deleted file mode 100644
index 92e234b..0000000
Binary files a/images/jpg/b_draw.jpg and /dev/null differ
diff --git a/images/jpg/b_reverse.jpg b/images/jpg/b_reverse.jpg
deleted file mode 100644
index 8e593d6..0000000
Binary files a/images/jpg/b_reverse.jpg and /dev/null differ
diff --git a/images/jpg/b_skip.jpg b/images/jpg/b_skip.jpg
deleted file mode 100644
index 762bc36..0000000
Binary files a/images/jpg/b_skip.jpg and /dev/null differ
diff --git a/images/jpg/colorchooser.jpg b/images/jpg/colorchooser.jpg
deleted file mode 100644
index a5793ac..0000000
Binary files a/images/jpg/colorchooser.jpg and /dev/null differ
diff --git a/images/jpg/draw_four.jpg b/images/jpg/draw_four.jpg
deleted file mode 100644
index 3474002..0000000
Binary files a/images/jpg/draw_four.jpg and /dev/null differ
diff --git a/images/jpg/g_0.jpg b/images/jpg/g_0.jpg
deleted file mode 100644
index 01ece18..0000000
Binary files a/images/jpg/g_0.jpg and /dev/null differ
diff --git a/images/jpg/g_1.jpg b/images/jpg/g_1.jpg
deleted file mode 100644
index b84d80c..0000000
Binary files a/images/jpg/g_1.jpg and /dev/null differ
diff --git a/images/jpg/g_2.jpg b/images/jpg/g_2.jpg
deleted file mode 100644
index f009fff..0000000
Binary files a/images/jpg/g_2.jpg and /dev/null differ
diff --git a/images/jpg/g_3.jpg b/images/jpg/g_3.jpg
deleted file mode 100644
index a48fa89..0000000
Binary files a/images/jpg/g_3.jpg and /dev/null differ
diff --git a/images/jpg/g_4.jpg b/images/jpg/g_4.jpg
deleted file mode 100644
index 58fa959..0000000
Binary files a/images/jpg/g_4.jpg and /dev/null differ
diff --git a/images/jpg/g_5.jpg b/images/jpg/g_5.jpg
deleted file mode 100644
index f3f508f..0000000
Binary files a/images/jpg/g_5.jpg and /dev/null differ
diff --git a/images/jpg/g_6.jpg b/images/jpg/g_6.jpg
deleted file mode 100644
index 4b84eff..0000000
Binary files a/images/jpg/g_6.jpg and /dev/null differ
diff --git a/images/jpg/g_7.jpg b/images/jpg/g_7.jpg
deleted file mode 100644
index 78ca3c5..0000000
Binary files a/images/jpg/g_7.jpg and /dev/null differ
diff --git a/images/jpg/g_8.jpg b/images/jpg/g_8.jpg
deleted file mode 100644
index 16c2a82..0000000
Binary files a/images/jpg/g_8.jpg and /dev/null differ
diff --git a/images/jpg/g_9.jpg b/images/jpg/g_9.jpg
deleted file mode 100644
index aba66e0..0000000
Binary files a/images/jpg/g_9.jpg and /dev/null differ
diff --git a/images/jpg/g_draw.jpg b/images/jpg/g_draw.jpg
deleted file mode 100644
index 3de8513..0000000
Binary files a/images/jpg/g_draw.jpg and /dev/null differ
diff --git a/images/jpg/g_reverse.jpg b/images/jpg/g_reverse.jpg
deleted file mode 100644
index b6cd82f..0000000
Binary files a/images/jpg/g_reverse.jpg and /dev/null differ
diff --git a/images/jpg/g_skip.jpg b/images/jpg/g_skip.jpg
deleted file mode 100644
index be98d12..0000000
Binary files a/images/jpg/g_skip.jpg and /dev/null differ
diff --git a/images/jpg/r_0.jpg b/images/jpg/r_0.jpg
deleted file mode 100644
index efe1682..0000000
Binary files a/images/jpg/r_0.jpg and /dev/null differ
diff --git a/images/jpg/r_1.jpg b/images/jpg/r_1.jpg
deleted file mode 100644
index 99665c8..0000000
Binary files a/images/jpg/r_1.jpg and /dev/null differ
diff --git a/images/jpg/r_2.jpg b/images/jpg/r_2.jpg
deleted file mode 100644
index bf20299..0000000
Binary files a/images/jpg/r_2.jpg and /dev/null differ
diff --git a/images/jpg/r_3.jpg b/images/jpg/r_3.jpg
deleted file mode 100644
index c53a9c8..0000000
Binary files a/images/jpg/r_3.jpg and /dev/null differ
diff --git a/images/jpg/r_4.jpg b/images/jpg/r_4.jpg
deleted file mode 100644
index d38af6e..0000000
Binary files a/images/jpg/r_4.jpg and /dev/null differ
diff --git a/images/jpg/r_5.jpg b/images/jpg/r_5.jpg
deleted file mode 100644
index 39bd3dc..0000000
Binary files a/images/jpg/r_5.jpg and /dev/null differ
diff --git a/images/jpg/r_6.jpg b/images/jpg/r_6.jpg
deleted file mode 100644
index 6a5ed8a..0000000
Binary files a/images/jpg/r_6.jpg and /dev/null differ
diff --git a/images/jpg/r_7.jpg b/images/jpg/r_7.jpg
deleted file mode 100644
index 862dea3..0000000
Binary files a/images/jpg/r_7.jpg and /dev/null differ
diff --git a/images/jpg/r_8.jpg b/images/jpg/r_8.jpg
deleted file mode 100644
index de039ef..0000000
Binary files a/images/jpg/r_8.jpg and /dev/null differ
diff --git a/images/jpg/r_9.jpg b/images/jpg/r_9.jpg
deleted file mode 100644
index aed52d8..0000000
Binary files a/images/jpg/r_9.jpg and /dev/null differ
diff --git a/images/jpg/r_draw.jpg b/images/jpg/r_draw.jpg
deleted file mode 100644
index 00ebb75..0000000
Binary files a/images/jpg/r_draw.jpg and /dev/null differ
diff --git a/images/jpg/r_reverse.jpg b/images/jpg/r_reverse.jpg
deleted file mode 100644
index ac2562c..0000000
Binary files a/images/jpg/r_reverse.jpg and /dev/null differ
diff --git a/images/jpg/r_skip.jpg b/images/jpg/r_skip.jpg
deleted file mode 100644
index 68c9bb6..0000000
Binary files a/images/jpg/r_skip.jpg and /dev/null differ
diff --git a/images/jpg/y_0.jpg b/images/jpg/y_0.jpg
deleted file mode 100644
index ffa8ff9..0000000
Binary files a/images/jpg/y_0.jpg and /dev/null differ
diff --git a/images/jpg/y_1.jpg b/images/jpg/y_1.jpg
deleted file mode 100644
index c0d642b..0000000
Binary files a/images/jpg/y_1.jpg and /dev/null differ
diff --git a/images/jpg/y_2.jpg b/images/jpg/y_2.jpg
deleted file mode 100644
index 40da9b3..0000000
Binary files a/images/jpg/y_2.jpg and /dev/null differ
diff --git a/images/jpg/y_3.jpg b/images/jpg/y_3.jpg
deleted file mode 100644
index a66ba59..0000000
Binary files a/images/jpg/y_3.jpg and /dev/null differ
diff --git a/images/jpg/y_4.jpg b/images/jpg/y_4.jpg
deleted file mode 100644
index 124126f..0000000
Binary files a/images/jpg/y_4.jpg and /dev/null differ
diff --git a/images/jpg/y_5.jpg b/images/jpg/y_5.jpg
deleted file mode 100644
index ee67566..0000000
Binary files a/images/jpg/y_5.jpg and /dev/null differ
diff --git a/images/jpg/y_6.jpg b/images/jpg/y_6.jpg
deleted file mode 100644
index 10dff5a..0000000
Binary files a/images/jpg/y_6.jpg and /dev/null differ
diff --git a/images/jpg/y_7.jpg b/images/jpg/y_7.jpg
deleted file mode 100644
index 379c34a..0000000
Binary files a/images/jpg/y_7.jpg and /dev/null differ
diff --git a/images/jpg/y_8.jpg b/images/jpg/y_8.jpg
deleted file mode 100644
index f220e34..0000000
Binary files a/images/jpg/y_8.jpg and /dev/null differ
diff --git a/images/jpg/y_9.jpg b/images/jpg/y_9.jpg
deleted file mode 100644
index 82afb10..0000000
Binary files a/images/jpg/y_9.jpg and /dev/null differ
diff --git a/images/jpg/y_draw.jpg b/images/jpg/y_draw.jpg
deleted file mode 100644
index 88eb833..0000000
Binary files a/images/jpg/y_draw.jpg and /dev/null differ
diff --git a/images/jpg/y_reverse.jpg b/images/jpg/y_reverse.jpg
deleted file mode 100644
index c37fefb..0000000
Binary files a/images/jpg/y_reverse.jpg and /dev/null differ
diff --git a/images/jpg/y_skip.jpg b/images/jpg/y_skip.jpg
deleted file mode 100644
index b4fae71..0000000
Binary files a/images/jpg/y_skip.jpg and /dev/null differ
diff --git a/images/png/b_0.png b/images/png/b_0.png
deleted file mode 100644
index 6f2b3f0..0000000
Binary files a/images/png/b_0.png and /dev/null differ
diff --git a/images/png/b_1.png b/images/png/b_1.png
deleted file mode 100644
index 2ef5867..0000000
Binary files a/images/png/b_1.png and /dev/null differ
diff --git a/images/png/b_2.png b/images/png/b_2.png
deleted file mode 100644
index 3aad78a..0000000
Binary files a/images/png/b_2.png and /dev/null differ
diff --git a/images/png/b_3.png b/images/png/b_3.png
deleted file mode 100644
index e4c5221..0000000
Binary files a/images/png/b_3.png and /dev/null differ
diff --git a/images/png/b_4.png b/images/png/b_4.png
deleted file mode 100644
index ec94357..0000000
Binary files a/images/png/b_4.png and /dev/null differ
diff --git a/images/png/b_5.png b/images/png/b_5.png
deleted file mode 100644
index 46f6dc5..0000000
Binary files a/images/png/b_5.png and /dev/null differ
diff --git a/images/png/b_6.png b/images/png/b_6.png
deleted file mode 100644
index 7de3cad..0000000
Binary files a/images/png/b_6.png and /dev/null differ
diff --git a/images/png/b_7.png b/images/png/b_7.png
deleted file mode 100644
index 25c213a..0000000
Binary files a/images/png/b_7.png and /dev/null differ
diff --git a/images/png/b_8.png b/images/png/b_8.png
deleted file mode 100644
index 3f05237..0000000
Binary files a/images/png/b_8.png and /dev/null differ
diff --git a/images/png/b_9.png b/images/png/b_9.png
deleted file mode 100644
index 744249f..0000000
Binary files a/images/png/b_9.png and /dev/null differ
diff --git a/images/png/b_draw.png b/images/png/b_draw.png
deleted file mode 100644
index cc62931..0000000
Binary files a/images/png/b_draw.png and /dev/null differ
diff --git a/images/png/b_reverse.png b/images/png/b_reverse.png
deleted file mode 100644
index 20f5cae..0000000
Binary files a/images/png/b_reverse.png and /dev/null differ
diff --git a/images/png/b_skip.png b/images/png/b_skip.png
deleted file mode 100644
index 56d83aa..0000000
Binary files a/images/png/b_skip.png and /dev/null differ
diff --git a/images/png/colorchooser.png b/images/png/colorchooser.png
deleted file mode 100644
index 365fe13..0000000
Binary files a/images/png/colorchooser.png and /dev/null differ
diff --git a/images/png/draw_four.png b/images/png/draw_four.png
deleted file mode 100644
index edd4359..0000000
Binary files a/images/png/draw_four.png and /dev/null differ
diff --git a/images/png/g_0.png b/images/png/g_0.png
deleted file mode 100644
index b4ee30c..0000000
Binary files a/images/png/g_0.png and /dev/null differ
diff --git a/images/png/g_1.png b/images/png/g_1.png
deleted file mode 100644
index 2c998a9..0000000
Binary files a/images/png/g_1.png and /dev/null differ
diff --git a/images/png/g_2.png b/images/png/g_2.png
deleted file mode 100644
index 1b5faa5..0000000
Binary files a/images/png/g_2.png and /dev/null differ
diff --git a/images/png/g_3.png b/images/png/g_3.png
deleted file mode 100644
index dd2407c..0000000
Binary files a/images/png/g_3.png and /dev/null differ
diff --git a/images/png/g_4.png b/images/png/g_4.png
deleted file mode 100644
index 31517d8..0000000
Binary files a/images/png/g_4.png and /dev/null differ
diff --git a/images/png/g_5.png b/images/png/g_5.png
deleted file mode 100644
index 0fbc34b..0000000
Binary files a/images/png/g_5.png and /dev/null differ
diff --git a/images/png/g_6.png b/images/png/g_6.png
deleted file mode 100644
index dbc58ef..0000000
Binary files a/images/png/g_6.png and /dev/null differ
diff --git a/images/png/g_7.png b/images/png/g_7.png
deleted file mode 100644
index 904b93b..0000000
Binary files a/images/png/g_7.png and /dev/null differ
diff --git a/images/png/g_8.png b/images/png/g_8.png
deleted file mode 100644
index 41d452d..0000000
Binary files a/images/png/g_8.png and /dev/null differ
diff --git a/images/png/g_9.png b/images/png/g_9.png
deleted file mode 100644
index 6d14681..0000000
Binary files a/images/png/g_9.png and /dev/null differ
diff --git a/images/png/g_draw.png b/images/png/g_draw.png
deleted file mode 100644
index 1ab27e3..0000000
Binary files a/images/png/g_draw.png and /dev/null differ
diff --git a/images/png/g_reverse.png b/images/png/g_reverse.png
deleted file mode 100644
index 79e47ad..0000000
Binary files a/images/png/g_reverse.png and /dev/null differ
diff --git a/images/png/g_skip.png b/images/png/g_skip.png
deleted file mode 100644
index fc13b83..0000000
Binary files a/images/png/g_skip.png and /dev/null differ
diff --git a/images/png/option_bluff.png b/images/png/option_bluff.png
deleted file mode 100644
index 9731155..0000000
Binary files a/images/png/option_bluff.png and /dev/null differ
diff --git a/images/png/option_draw.png b/images/png/option_draw.png
deleted file mode 100644
index c7e4cfa..0000000
Binary files a/images/png/option_draw.png and /dev/null differ
diff --git a/images/png/option_draw2.png b/images/png/option_draw2.png
deleted file mode 100644
index ffbe6f5..0000000
Binary files a/images/png/option_draw2.png and /dev/null differ
diff --git a/images/png/option_info.png b/images/png/option_info.png
deleted file mode 100644
index a8e568c..0000000
Binary files a/images/png/option_info.png and /dev/null differ
diff --git a/images/png/option_pass.png b/images/png/option_pass.png
deleted file mode 100644
index 076d314..0000000
Binary files a/images/png/option_pass.png and /dev/null differ
diff --git a/images/png/option_pass2.png b/images/png/option_pass2.png
deleted file mode 100644
index 3cc9621..0000000
Binary files a/images/png/option_pass2.png and /dev/null differ
diff --git a/images/png/r_0.png b/images/png/r_0.png
deleted file mode 100644
index c1d8788..0000000
Binary files a/images/png/r_0.png and /dev/null differ
diff --git a/images/png/r_1.png b/images/png/r_1.png
deleted file mode 100644
index c644f3f..0000000
Binary files a/images/png/r_1.png and /dev/null differ
diff --git a/images/png/r_2.png b/images/png/r_2.png
deleted file mode 100644
index a363b7d..0000000
Binary files a/images/png/r_2.png and /dev/null differ
diff --git a/images/png/r_3.png b/images/png/r_3.png
deleted file mode 100644
index cebf575..0000000
Binary files a/images/png/r_3.png and /dev/null differ
diff --git a/images/png/r_4.png b/images/png/r_4.png
deleted file mode 100644
index 05958f2..0000000
Binary files a/images/png/r_4.png and /dev/null differ
diff --git a/images/png/r_5.png b/images/png/r_5.png
deleted file mode 100644
index 3607eb8..0000000
Binary files a/images/png/r_5.png and /dev/null differ
diff --git a/images/png/r_6.png b/images/png/r_6.png
deleted file mode 100644
index b0be4a2..0000000
Binary files a/images/png/r_6.png and /dev/null differ
diff --git a/images/png/r_7.png b/images/png/r_7.png
deleted file mode 100644
index 663e26c..0000000
Binary files a/images/png/r_7.png and /dev/null differ
diff --git a/images/png/r_8.png b/images/png/r_8.png
deleted file mode 100644
index 1ae438f..0000000
Binary files a/images/png/r_8.png and /dev/null differ
diff --git a/images/png/r_9.png b/images/png/r_9.png
deleted file mode 100644
index dc7799b..0000000
Binary files a/images/png/r_9.png and /dev/null differ
diff --git a/images/png/r_draw.png b/images/png/r_draw.png
deleted file mode 100644
index 64b9ccd..0000000
Binary files a/images/png/r_draw.png and /dev/null differ
diff --git a/images/png/r_reverse.png b/images/png/r_reverse.png
deleted file mode 100644
index d1cc84a..0000000
Binary files a/images/png/r_reverse.png and /dev/null differ
diff --git a/images/png/r_skip.png b/images/png/r_skip.png
deleted file mode 100644
index c0a42b3..0000000
Binary files a/images/png/r_skip.png and /dev/null differ
diff --git a/images/png/y_0.png b/images/png/y_0.png
deleted file mode 100644
index 69bd151..0000000
Binary files a/images/png/y_0.png and /dev/null differ
diff --git a/images/png/y_1.png b/images/png/y_1.png
deleted file mode 100644
index 75303aa..0000000
Binary files a/images/png/y_1.png and /dev/null differ
diff --git a/images/png/y_2.png b/images/png/y_2.png
deleted file mode 100644
index 7180a43..0000000
Binary files a/images/png/y_2.png and /dev/null differ
diff --git a/images/png/y_3.png b/images/png/y_3.png
deleted file mode 100644
index 6341271..0000000
Binary files a/images/png/y_3.png and /dev/null differ
diff --git a/images/png/y_4.png b/images/png/y_4.png
deleted file mode 100644
index 038cce3..0000000
Binary files a/images/png/y_4.png and /dev/null differ
diff --git a/images/png/y_5.png b/images/png/y_5.png
deleted file mode 100644
index 40cd6e6..0000000
Binary files a/images/png/y_5.png and /dev/null differ
diff --git a/images/png/y_6.png b/images/png/y_6.png
deleted file mode 100644
index d7ee0c1..0000000
Binary files a/images/png/y_6.png and /dev/null differ
diff --git a/images/png/y_7.png b/images/png/y_7.png
deleted file mode 100644
index f42e64e..0000000
Binary files a/images/png/y_7.png and /dev/null differ
diff --git a/images/png/y_8.png b/images/png/y_8.png
deleted file mode 100644
index db9073d..0000000
Binary files a/images/png/y_8.png and /dev/null differ
diff --git a/images/png/y_9.png b/images/png/y_9.png
deleted file mode 100644
index 108122c..0000000
Binary files a/images/png/y_9.png and /dev/null differ
diff --git a/images/png/y_draw.png b/images/png/y_draw.png
deleted file mode 100644
index 9c5b14b..0000000
Binary files a/images/png/y_draw.png and /dev/null differ
diff --git a/images/png/y_reverse.png b/images/png/y_reverse.png
deleted file mode 100644
index 5ed3816..0000000
Binary files a/images/png/y_reverse.png and /dev/null differ
diff --git a/images/png/y_skip.png b/images/png/y_skip.png
deleted file mode 100644
index cca5fd7..0000000
Binary files a/images/png/y_skip.png and /dev/null differ
diff --git a/images/png_lowsat/b_0.png b/images/png_lowsat/b_0.png
deleted file mode 100644
index 79184a7..0000000
Binary files a/images/png_lowsat/b_0.png and /dev/null differ
diff --git a/images/png_lowsat/b_1.png b/images/png_lowsat/b_1.png
deleted file mode 100644
index e27034b..0000000
Binary files a/images/png_lowsat/b_1.png and /dev/null differ
diff --git a/images/png_lowsat/b_2.png b/images/png_lowsat/b_2.png
deleted file mode 100644
index 5117cdb..0000000
Binary files a/images/png_lowsat/b_2.png and /dev/null differ
diff --git a/images/png_lowsat/b_3.png b/images/png_lowsat/b_3.png
deleted file mode 100644
index 304bef2..0000000
Binary files a/images/png_lowsat/b_3.png and /dev/null differ
diff --git a/images/png_lowsat/b_4.png b/images/png_lowsat/b_4.png
deleted file mode 100644
index b22aafe..0000000
Binary files a/images/png_lowsat/b_4.png and /dev/null differ
diff --git a/images/png_lowsat/b_5.png b/images/png_lowsat/b_5.png
deleted file mode 100644
index ad8e2d9..0000000
Binary files a/images/png_lowsat/b_5.png and /dev/null differ
diff --git a/images/png_lowsat/b_6.png b/images/png_lowsat/b_6.png
deleted file mode 100644
index f3ec00d..0000000
Binary files a/images/png_lowsat/b_6.png and /dev/null differ
diff --git a/images/png_lowsat/b_7.png b/images/png_lowsat/b_7.png
deleted file mode 100644
index bbaa943..0000000
Binary files a/images/png_lowsat/b_7.png and /dev/null differ
diff --git a/images/png_lowsat/b_8.png b/images/png_lowsat/b_8.png
deleted file mode 100644
index 6580bd9..0000000
Binary files a/images/png_lowsat/b_8.png and /dev/null differ
diff --git a/images/png_lowsat/b_9.png b/images/png_lowsat/b_9.png
deleted file mode 100644
index 0a047a5..0000000
Binary files a/images/png_lowsat/b_9.png and /dev/null differ
diff --git a/images/png_lowsat/b_draw.png b/images/png_lowsat/b_draw.png
deleted file mode 100644
index 4f97093..0000000
Binary files a/images/png_lowsat/b_draw.png and /dev/null differ
diff --git a/images/png_lowsat/b_reverse.png b/images/png_lowsat/b_reverse.png
deleted file mode 100644
index a2203f2..0000000
Binary files a/images/png_lowsat/b_reverse.png and /dev/null differ
diff --git a/images/png_lowsat/b_skip.png b/images/png_lowsat/b_skip.png
deleted file mode 100644
index 1028d3a..0000000
Binary files a/images/png_lowsat/b_skip.png and /dev/null differ
diff --git a/images/png_lowsat/colorchooser.png b/images/png_lowsat/colorchooser.png
deleted file mode 100644
index ef9c70e..0000000
Binary files a/images/png_lowsat/colorchooser.png and /dev/null differ
diff --git a/images/png_lowsat/draw_four.png b/images/png_lowsat/draw_four.png
deleted file mode 100644
index 80e518d..0000000
Binary files a/images/png_lowsat/draw_four.png and /dev/null differ
diff --git a/images/png_lowsat/g_0.png b/images/png_lowsat/g_0.png
deleted file mode 100644
index e7bd6ef..0000000
Binary files a/images/png_lowsat/g_0.png and /dev/null differ
diff --git a/images/png_lowsat/g_1.png b/images/png_lowsat/g_1.png
deleted file mode 100644
index 5a3a838..0000000
Binary files a/images/png_lowsat/g_1.png and /dev/null differ
diff --git a/images/png_lowsat/g_2.png b/images/png_lowsat/g_2.png
deleted file mode 100644
index 186643d..0000000
Binary files a/images/png_lowsat/g_2.png and /dev/null differ
diff --git a/images/png_lowsat/g_3.png b/images/png_lowsat/g_3.png
deleted file mode 100644
index de06423..0000000
Binary files a/images/png_lowsat/g_3.png and /dev/null differ
diff --git a/images/png_lowsat/g_4.png b/images/png_lowsat/g_4.png
deleted file mode 100644
index 6a063f4..0000000
Binary files a/images/png_lowsat/g_4.png and /dev/null differ
diff --git a/images/png_lowsat/g_5.png b/images/png_lowsat/g_5.png
deleted file mode 100644
index 341507e..0000000
Binary files a/images/png_lowsat/g_5.png and /dev/null differ
diff --git a/images/png_lowsat/g_6.png b/images/png_lowsat/g_6.png
deleted file mode 100644
index fdc706d..0000000
Binary files a/images/png_lowsat/g_6.png and /dev/null differ
diff --git a/images/png_lowsat/g_7.png b/images/png_lowsat/g_7.png
deleted file mode 100644
index 4eff73d..0000000
Binary files a/images/png_lowsat/g_7.png and /dev/null differ
diff --git a/images/png_lowsat/g_8.png b/images/png_lowsat/g_8.png
deleted file mode 100644
index 195b9a3..0000000
Binary files a/images/png_lowsat/g_8.png and /dev/null differ
diff --git a/images/png_lowsat/g_9.png b/images/png_lowsat/g_9.png
deleted file mode 100644
index 8624548..0000000
Binary files a/images/png_lowsat/g_9.png and /dev/null differ
diff --git a/images/png_lowsat/g_draw.png b/images/png_lowsat/g_draw.png
deleted file mode 100644
index c223ced..0000000
Binary files a/images/png_lowsat/g_draw.png and /dev/null differ
diff --git a/images/png_lowsat/g_reverse.png b/images/png_lowsat/g_reverse.png
deleted file mode 100644
index 869c5c6..0000000
Binary files a/images/png_lowsat/g_reverse.png and /dev/null differ
diff --git a/images/png_lowsat/g_skip.png b/images/png_lowsat/g_skip.png
deleted file mode 100644
index 527bf65..0000000
Binary files a/images/png_lowsat/g_skip.png and /dev/null differ
diff --git a/images/png_lowsat/r_0.png b/images/png_lowsat/r_0.png
deleted file mode 100644
index 0e4130d..0000000
Binary files a/images/png_lowsat/r_0.png and /dev/null differ
diff --git a/images/png_lowsat/r_1.png b/images/png_lowsat/r_1.png
deleted file mode 100644
index ccef019..0000000
Binary files a/images/png_lowsat/r_1.png and /dev/null differ
diff --git a/images/png_lowsat/r_2.png b/images/png_lowsat/r_2.png
deleted file mode 100644
index 264166b..0000000
Binary files a/images/png_lowsat/r_2.png and /dev/null differ
diff --git a/images/png_lowsat/r_3.png b/images/png_lowsat/r_3.png
deleted file mode 100644
index 4e28cdf..0000000
Binary files a/images/png_lowsat/r_3.png and /dev/null differ
diff --git a/images/png_lowsat/r_4.png b/images/png_lowsat/r_4.png
deleted file mode 100644
index e03d37d..0000000
Binary files a/images/png_lowsat/r_4.png and /dev/null differ
diff --git a/images/png_lowsat/r_5.png b/images/png_lowsat/r_5.png
deleted file mode 100644
index c0bd1cd..0000000
Binary files a/images/png_lowsat/r_5.png and /dev/null differ
diff --git a/images/png_lowsat/r_6.png b/images/png_lowsat/r_6.png
deleted file mode 100644
index 89c78d6..0000000
Binary files a/images/png_lowsat/r_6.png and /dev/null differ
diff --git a/images/png_lowsat/r_7.png b/images/png_lowsat/r_7.png
deleted file mode 100644
index 0dd84cd..0000000
Binary files a/images/png_lowsat/r_7.png and /dev/null differ
diff --git a/images/png_lowsat/r_8.png b/images/png_lowsat/r_8.png
deleted file mode 100644
index c21b9bf..0000000
Binary files a/images/png_lowsat/r_8.png and /dev/null differ
diff --git a/images/png_lowsat/r_9.png b/images/png_lowsat/r_9.png
deleted file mode 100644
index 9e51a85..0000000
Binary files a/images/png_lowsat/r_9.png and /dev/null differ
diff --git a/images/png_lowsat/r_draw.png b/images/png_lowsat/r_draw.png
deleted file mode 100644
index 852729f..0000000
Binary files a/images/png_lowsat/r_draw.png and /dev/null differ
diff --git a/images/png_lowsat/r_reverse.png b/images/png_lowsat/r_reverse.png
deleted file mode 100644
index 269efe0..0000000
Binary files a/images/png_lowsat/r_reverse.png and /dev/null differ
diff --git a/images/png_lowsat/r_skip.png b/images/png_lowsat/r_skip.png
deleted file mode 100644
index 6c5296a..0000000
Binary files a/images/png_lowsat/r_skip.png and /dev/null differ
diff --git a/images/png_lowsat/y_0.png b/images/png_lowsat/y_0.png
deleted file mode 100644
index 120827c..0000000
Binary files a/images/png_lowsat/y_0.png and /dev/null differ
diff --git a/images/png_lowsat/y_1.png b/images/png_lowsat/y_1.png
deleted file mode 100644
index 9b342c5..0000000
Binary files a/images/png_lowsat/y_1.png and /dev/null differ
diff --git a/images/png_lowsat/y_2.png b/images/png_lowsat/y_2.png
deleted file mode 100644
index 33ec56c..0000000
Binary files a/images/png_lowsat/y_2.png and /dev/null differ
diff --git a/images/png_lowsat/y_3.png b/images/png_lowsat/y_3.png
deleted file mode 100644
index 96d6c98..0000000
Binary files a/images/png_lowsat/y_3.png and /dev/null differ
diff --git a/images/png_lowsat/y_4.png b/images/png_lowsat/y_4.png
deleted file mode 100644
index 492e6c2..0000000
Binary files a/images/png_lowsat/y_4.png and /dev/null differ
diff --git a/images/png_lowsat/y_5.png b/images/png_lowsat/y_5.png
deleted file mode 100644
index 845a8a6..0000000
Binary files a/images/png_lowsat/y_5.png and /dev/null differ
diff --git a/images/png_lowsat/y_6.png b/images/png_lowsat/y_6.png
deleted file mode 100644
index 1b1960e..0000000
Binary files a/images/png_lowsat/y_6.png and /dev/null differ
diff --git a/images/png_lowsat/y_7.png b/images/png_lowsat/y_7.png
deleted file mode 100644
index 60149b9..0000000
Binary files a/images/png_lowsat/y_7.png and /dev/null differ
diff --git a/images/png_lowsat/y_8.png b/images/png_lowsat/y_8.png
deleted file mode 100644
index ac61ac3..0000000
Binary files a/images/png_lowsat/y_8.png and /dev/null differ
diff --git a/images/png_lowsat/y_9.png b/images/png_lowsat/y_9.png
deleted file mode 100644
index ca8b28a..0000000
Binary files a/images/png_lowsat/y_9.png and /dev/null differ
diff --git a/images/png_lowsat/y_draw.png b/images/png_lowsat/y_draw.png
deleted file mode 100644
index 93f5ff7..0000000
Binary files a/images/png_lowsat/y_draw.png and /dev/null differ
diff --git a/images/png_lowsat/y_reverse.png b/images/png_lowsat/y_reverse.png
deleted file mode 100644
index 66fb71f..0000000
Binary files a/images/png_lowsat/y_reverse.png and /dev/null differ
diff --git a/images/png_lowsat/y_skip.png b/images/png_lowsat/y_skip.png
deleted file mode 100644
index e9b0548..0000000
Binary files a/images/png_lowsat/y_skip.png and /dev/null differ
diff --git a/images/source.txt b/images/source.txt
deleted file mode 100644
index db33e86..0000000
--- a/images/source.txt
+++ /dev/null
@@ -1 +0,0 @@
-https://commons.wikimedia.org/wiki/File:UNO_cards_deck.svg
diff --git a/images/svg/b_0.svg b/images/svg/b_0.svg
deleted file mode 100644
index 4edf4d2..0000000
--- a/images/svg/b_0.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_1.svg b/images/svg/b_1.svg
deleted file mode 100644
index 10b7b34..0000000
--- a/images/svg/b_1.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_2.svg b/images/svg/b_2.svg
deleted file mode 100644
index c431bde..0000000
--- a/images/svg/b_2.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_3.svg b/images/svg/b_3.svg
deleted file mode 100644
index b05de30..0000000
--- a/images/svg/b_3.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_4.svg b/images/svg/b_4.svg
deleted file mode 100644
index 4ad3942..0000000
--- a/images/svg/b_4.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_5.svg b/images/svg/b_5.svg
deleted file mode 100644
index 5ac8867..0000000
--- a/images/svg/b_5.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_6.svg b/images/svg/b_6.svg
deleted file mode 100644
index 2b50369..0000000
--- a/images/svg/b_6.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_7.svg b/images/svg/b_7.svg
deleted file mode 100644
index e354763..0000000
--- a/images/svg/b_7.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_8.svg b/images/svg/b_8.svg
deleted file mode 100644
index f2b7435..0000000
--- a/images/svg/b_8.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_9.svg b/images/svg/b_9.svg
deleted file mode 100644
index 743cad5..0000000
--- a/images/svg/b_9.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_draw.svg b/images/svg/b_draw.svg
deleted file mode 100644
index f86de73..0000000
--- a/images/svg/b_draw.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_reverse.svg b/images/svg/b_reverse.svg
deleted file mode 100644
index 5004456..0000000
--- a/images/svg/b_reverse.svg
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
diff --git a/images/svg/b_skip.svg b/images/svg/b_skip.svg
deleted file mode 100644
index 69d1a05..0000000
--- a/images/svg/b_skip.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/colorchooser.svg b/images/svg/colorchooser.svg
deleted file mode 100644
index 728ec0c..0000000
--- a/images/svg/colorchooser.svg
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-
-
diff --git a/images/svg/draw_four.svg b/images/svg/draw_four.svg
deleted file mode 100644
index 7bfdae4..0000000
--- a/images/svg/draw_four.svg
+++ /dev/null
@@ -1,204 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_0.svg b/images/svg/g_0.svg
deleted file mode 100644
index 987b401..0000000
--- a/images/svg/g_0.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_1.svg b/images/svg/g_1.svg
deleted file mode 100644
index 70fb3c3..0000000
--- a/images/svg/g_1.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_2.svg b/images/svg/g_2.svg
deleted file mode 100644
index 5679ff8..0000000
--- a/images/svg/g_2.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_3.svg b/images/svg/g_3.svg
deleted file mode 100644
index 515db1e..0000000
--- a/images/svg/g_3.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_4.svg b/images/svg/g_4.svg
deleted file mode 100644
index c52a9ef..0000000
--- a/images/svg/g_4.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_5.svg b/images/svg/g_5.svg
deleted file mode 100644
index d2e9c62..0000000
--- a/images/svg/g_5.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_6.svg b/images/svg/g_6.svg
deleted file mode 100644
index 4117bcb..0000000
--- a/images/svg/g_6.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_7.svg b/images/svg/g_7.svg
deleted file mode 100644
index 370b15e..0000000
--- a/images/svg/g_7.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_8.svg b/images/svg/g_8.svg
deleted file mode 100644
index f34f8b3..0000000
--- a/images/svg/g_8.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_9.svg b/images/svg/g_9.svg
deleted file mode 100644
index 1c2602c..0000000
--- a/images/svg/g_9.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_draw.svg b/images/svg/g_draw.svg
deleted file mode 100644
index e245b0c..0000000
--- a/images/svg/g_draw.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_reverse.svg b/images/svg/g_reverse.svg
deleted file mode 100644
index cb706fb..0000000
--- a/images/svg/g_reverse.svg
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
diff --git a/images/svg/g_skip.svg b/images/svg/g_skip.svg
deleted file mode 100644
index 4314a8e..0000000
--- a/images/svg/g_skip.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_0.svg b/images/svg/r_0.svg
deleted file mode 100644
index 04803e8..0000000
--- a/images/svg/r_0.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_1.svg b/images/svg/r_1.svg
deleted file mode 100644
index 453a06f..0000000
--- a/images/svg/r_1.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_2.svg b/images/svg/r_2.svg
deleted file mode 100644
index 8e27640..0000000
--- a/images/svg/r_2.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_3.svg b/images/svg/r_3.svg
deleted file mode 100644
index eb1e3bc..0000000
--- a/images/svg/r_3.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_4.svg b/images/svg/r_4.svg
deleted file mode 100644
index d71ac7a..0000000
--- a/images/svg/r_4.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_5.svg b/images/svg/r_5.svg
deleted file mode 100644
index d78f261..0000000
--- a/images/svg/r_5.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_6.svg b/images/svg/r_6.svg
deleted file mode 100644
index 5cf23e5..0000000
--- a/images/svg/r_6.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_7.svg b/images/svg/r_7.svg
deleted file mode 100644
index 013e933..0000000
--- a/images/svg/r_7.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_8.svg b/images/svg/r_8.svg
deleted file mode 100644
index 00ab479..0000000
--- a/images/svg/r_8.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_9.svg b/images/svg/r_9.svg
deleted file mode 100644
index 38881b6..0000000
--- a/images/svg/r_9.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_draw.svg b/images/svg/r_draw.svg
deleted file mode 100644
index 73b43f4..0000000
--- a/images/svg/r_draw.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_reverse.svg b/images/svg/r_reverse.svg
deleted file mode 100644
index 1dd8d13..0000000
--- a/images/svg/r_reverse.svg
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
diff --git a/images/svg/r_skip.svg b/images/svg/r_skip.svg
deleted file mode 100644
index dc5b362..0000000
--- a/images/svg/r_skip.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_0.svg b/images/svg/y_0.svg
deleted file mode 100644
index 07a7217..0000000
--- a/images/svg/y_0.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_1.svg b/images/svg/y_1.svg
deleted file mode 100644
index c96416b..0000000
--- a/images/svg/y_1.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_2.svg b/images/svg/y_2.svg
deleted file mode 100644
index 5717a89..0000000
--- a/images/svg/y_2.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_3.svg b/images/svg/y_3.svg
deleted file mode 100644
index 72c0f29..0000000
--- a/images/svg/y_3.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_4.svg b/images/svg/y_4.svg
deleted file mode 100644
index 8a4316d..0000000
--- a/images/svg/y_4.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_5.svg b/images/svg/y_5.svg
deleted file mode 100644
index 55c5f11..0000000
--- a/images/svg/y_5.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_6.svg b/images/svg/y_6.svg
deleted file mode 100644
index 5fdf529..0000000
--- a/images/svg/y_6.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_7.svg b/images/svg/y_7.svg
deleted file mode 100644
index e04a0c1..0000000
--- a/images/svg/y_7.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_8.svg b/images/svg/y_8.svg
deleted file mode 100644
index a1da081..0000000
--- a/images/svg/y_8.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_9.svg b/images/svg/y_9.svg
deleted file mode 100644
index 34f8389..0000000
--- a/images/svg/y_9.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_draw.svg b/images/svg/y_draw.svg
deleted file mode 100644
index ffe743b..0000000
--- a/images/svg/y_draw.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_reverse.svg b/images/svg/y_reverse.svg
deleted file mode 100644
index d57f8ac..0000000
--- a/images/svg/y_reverse.svg
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
diff --git a/images/svg/y_skip.svg b/images/svg/y_skip.svg
deleted file mode 100644
index 96b353f..0000000
--- a/images/svg/y_skip.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/images/thumb/b_0.jpg b/images/thumb/b_0.jpg
deleted file mode 100644
index a45820e..0000000
Binary files a/images/thumb/b_0.jpg and /dev/null differ
diff --git a/images/thumb/b_1.jpg b/images/thumb/b_1.jpg
deleted file mode 100644
index 7f85f22..0000000
Binary files a/images/thumb/b_1.jpg and /dev/null differ
diff --git a/images/thumb/b_2.jpg b/images/thumb/b_2.jpg
deleted file mode 100644
index cac1288..0000000
Binary files a/images/thumb/b_2.jpg and /dev/null differ
diff --git a/images/thumb/b_3.jpg b/images/thumb/b_3.jpg
deleted file mode 100644
index 3be34c9..0000000
Binary files a/images/thumb/b_3.jpg and /dev/null differ
diff --git a/images/thumb/b_4.jpg b/images/thumb/b_4.jpg
deleted file mode 100644
index cd09ae8..0000000
Binary files a/images/thumb/b_4.jpg and /dev/null differ
diff --git a/images/thumb/b_5.jpg b/images/thumb/b_5.jpg
deleted file mode 100644
index 2629bed..0000000
Binary files a/images/thumb/b_5.jpg and /dev/null differ
diff --git a/images/thumb/b_6.jpg b/images/thumb/b_6.jpg
deleted file mode 100644
index c620fea..0000000
Binary files a/images/thumb/b_6.jpg and /dev/null differ
diff --git a/images/thumb/b_7.jpg b/images/thumb/b_7.jpg
deleted file mode 100644
index c4b1982..0000000
Binary files a/images/thumb/b_7.jpg and /dev/null differ
diff --git a/images/thumb/b_8.jpg b/images/thumb/b_8.jpg
deleted file mode 100644
index d7738a8..0000000
Binary files a/images/thumb/b_8.jpg and /dev/null differ
diff --git a/images/thumb/b_9.jpg b/images/thumb/b_9.jpg
deleted file mode 100644
index 2b04594..0000000
Binary files a/images/thumb/b_9.jpg and /dev/null differ
diff --git a/images/thumb/b_draw.jpg b/images/thumb/b_draw.jpg
deleted file mode 100644
index b0f8a41..0000000
Binary files a/images/thumb/b_draw.jpg and /dev/null differ
diff --git a/images/thumb/b_reverse.jpg b/images/thumb/b_reverse.jpg
deleted file mode 100644
index e81c28f..0000000
Binary files a/images/thumb/b_reverse.jpg and /dev/null differ
diff --git a/images/thumb/b_skip.jpg b/images/thumb/b_skip.jpg
deleted file mode 100644
index 0940e3f..0000000
Binary files a/images/thumb/b_skip.jpg and /dev/null differ
diff --git a/images/thumb/colorchooser.jpg b/images/thumb/colorchooser.jpg
deleted file mode 100644
index 67ff2ff..0000000
Binary files a/images/thumb/colorchooser.jpg and /dev/null differ
diff --git a/images/thumb/draw_four.jpg b/images/thumb/draw_four.jpg
deleted file mode 100644
index ae5aa21..0000000
Binary files a/images/thumb/draw_four.jpg and /dev/null differ
diff --git a/images/thumb/g_0.jpg b/images/thumb/g_0.jpg
deleted file mode 100644
index 7c8fd97..0000000
Binary files a/images/thumb/g_0.jpg and /dev/null differ
diff --git a/images/thumb/g_1.jpg b/images/thumb/g_1.jpg
deleted file mode 100644
index 3d8b927..0000000
Binary files a/images/thumb/g_1.jpg and /dev/null differ
diff --git a/images/thumb/g_2.jpg b/images/thumb/g_2.jpg
deleted file mode 100644
index f527986..0000000
Binary files a/images/thumb/g_2.jpg and /dev/null differ
diff --git a/images/thumb/g_3.jpg b/images/thumb/g_3.jpg
deleted file mode 100644
index 6669244..0000000
Binary files a/images/thumb/g_3.jpg and /dev/null differ
diff --git a/images/thumb/g_4.jpg b/images/thumb/g_4.jpg
deleted file mode 100644
index 66ea924..0000000
Binary files a/images/thumb/g_4.jpg and /dev/null differ
diff --git a/images/thumb/g_5.jpg b/images/thumb/g_5.jpg
deleted file mode 100644
index 10a89db..0000000
Binary files a/images/thumb/g_5.jpg and /dev/null differ
diff --git a/images/thumb/g_6.jpg b/images/thumb/g_6.jpg
deleted file mode 100644
index c4e005b..0000000
Binary files a/images/thumb/g_6.jpg and /dev/null differ
diff --git a/images/thumb/g_7.jpg b/images/thumb/g_7.jpg
deleted file mode 100644
index 79e205c..0000000
Binary files a/images/thumb/g_7.jpg and /dev/null differ
diff --git a/images/thumb/g_8.jpg b/images/thumb/g_8.jpg
deleted file mode 100644
index bd3eba1..0000000
Binary files a/images/thumb/g_8.jpg and /dev/null differ
diff --git a/images/thumb/g_9.jpg b/images/thumb/g_9.jpg
deleted file mode 100644
index 403dc25..0000000
Binary files a/images/thumb/g_9.jpg and /dev/null differ
diff --git a/images/thumb/g_draw.jpg b/images/thumb/g_draw.jpg
deleted file mode 100644
index c082bfe..0000000
Binary files a/images/thumb/g_draw.jpg and /dev/null differ
diff --git a/images/thumb/g_reverse.jpg b/images/thumb/g_reverse.jpg
deleted file mode 100644
index d655b20..0000000
Binary files a/images/thumb/g_reverse.jpg and /dev/null differ
diff --git a/images/thumb/g_skip.jpg b/images/thumb/g_skip.jpg
deleted file mode 100644
index 8ab1e1b..0000000
Binary files a/images/thumb/g_skip.jpg and /dev/null differ
diff --git a/images/thumb/r_0.jpg b/images/thumb/r_0.jpg
deleted file mode 100644
index 5476f83..0000000
Binary files a/images/thumb/r_0.jpg and /dev/null differ
diff --git a/images/thumb/r_1.jpg b/images/thumb/r_1.jpg
deleted file mode 100644
index 81d1486..0000000
Binary files a/images/thumb/r_1.jpg and /dev/null differ
diff --git a/images/thumb/r_2.jpg b/images/thumb/r_2.jpg
deleted file mode 100644
index 5cae25f..0000000
Binary files a/images/thumb/r_2.jpg and /dev/null differ
diff --git a/images/thumb/r_3.jpg b/images/thumb/r_3.jpg
deleted file mode 100644
index 8aec569..0000000
Binary files a/images/thumb/r_3.jpg and /dev/null differ
diff --git a/images/thumb/r_4.jpg b/images/thumb/r_4.jpg
deleted file mode 100644
index f22de30..0000000
Binary files a/images/thumb/r_4.jpg and /dev/null differ
diff --git a/images/thumb/r_5.jpg b/images/thumb/r_5.jpg
deleted file mode 100644
index 6a4e0da..0000000
Binary files a/images/thumb/r_5.jpg and /dev/null differ
diff --git a/images/thumb/r_6.jpg b/images/thumb/r_6.jpg
deleted file mode 100644
index 7e6f0d1..0000000
Binary files a/images/thumb/r_6.jpg and /dev/null differ
diff --git a/images/thumb/r_7.jpg b/images/thumb/r_7.jpg
deleted file mode 100644
index 23a13f4..0000000
Binary files a/images/thumb/r_7.jpg and /dev/null differ
diff --git a/images/thumb/r_8.jpg b/images/thumb/r_8.jpg
deleted file mode 100644
index a281d5e..0000000
Binary files a/images/thumb/r_8.jpg and /dev/null differ
diff --git a/images/thumb/r_9.jpg b/images/thumb/r_9.jpg
deleted file mode 100644
index 66d1995..0000000
Binary files a/images/thumb/r_9.jpg and /dev/null differ
diff --git a/images/thumb/r_draw.jpg b/images/thumb/r_draw.jpg
deleted file mode 100644
index f02ed4e..0000000
Binary files a/images/thumb/r_draw.jpg and /dev/null differ
diff --git a/images/thumb/r_reverse.jpg b/images/thumb/r_reverse.jpg
deleted file mode 100644
index 78c43a8..0000000
Binary files a/images/thumb/r_reverse.jpg and /dev/null differ
diff --git a/images/thumb/r_skip.jpg b/images/thumb/r_skip.jpg
deleted file mode 100644
index 40c2a1a..0000000
Binary files a/images/thumb/r_skip.jpg and /dev/null differ
diff --git a/images/thumb/y_0.jpg b/images/thumb/y_0.jpg
deleted file mode 100644
index b50f47c..0000000
Binary files a/images/thumb/y_0.jpg and /dev/null differ
diff --git a/images/thumb/y_1.jpg b/images/thumb/y_1.jpg
deleted file mode 100644
index edc1af8..0000000
Binary files a/images/thumb/y_1.jpg and /dev/null differ
diff --git a/images/thumb/y_2.jpg b/images/thumb/y_2.jpg
deleted file mode 100644
index 2ae91a9..0000000
Binary files a/images/thumb/y_2.jpg and /dev/null differ
diff --git a/images/thumb/y_3.jpg b/images/thumb/y_3.jpg
deleted file mode 100644
index fe73c2f..0000000
Binary files a/images/thumb/y_3.jpg and /dev/null differ
diff --git a/images/thumb/y_4.jpg b/images/thumb/y_4.jpg
deleted file mode 100644
index c1a25af..0000000
Binary files a/images/thumb/y_4.jpg and /dev/null differ
diff --git a/images/thumb/y_5.jpg b/images/thumb/y_5.jpg
deleted file mode 100644
index 41523f7..0000000
Binary files a/images/thumb/y_5.jpg and /dev/null differ
diff --git a/images/thumb/y_6.jpg b/images/thumb/y_6.jpg
deleted file mode 100644
index c850582..0000000
Binary files a/images/thumb/y_6.jpg and /dev/null differ
diff --git a/images/thumb/y_7.jpg b/images/thumb/y_7.jpg
deleted file mode 100644
index af9e818..0000000
Binary files a/images/thumb/y_7.jpg and /dev/null differ
diff --git a/images/thumb/y_8.jpg b/images/thumb/y_8.jpg
deleted file mode 100644
index b7980d9..0000000
Binary files a/images/thumb/y_8.jpg and /dev/null differ
diff --git a/images/thumb/y_9.jpg b/images/thumb/y_9.jpg
deleted file mode 100644
index faea4bb..0000000
Binary files a/images/thumb/y_9.jpg and /dev/null differ
diff --git a/images/thumb/y_draw.jpg b/images/thumb/y_draw.jpg
deleted file mode 100644
index 66b5baf..0000000
Binary files a/images/thumb/y_draw.jpg and /dev/null differ
diff --git a/images/thumb/y_reverse.jpg b/images/thumb/y_reverse.jpg
deleted file mode 100644
index de1657c..0000000
Binary files a/images/thumb/y_reverse.jpg and /dev/null differ
diff --git a/images/thumb/y_skip.jpg b/images/thumb/y_skip.jpg
deleted file mode 100644
index 9020ff4..0000000
Binary files a/images/thumb/y_skip.jpg and /dev/null differ
diff --git a/images/webp/b_0.webp b/images/webp/b_0.webp
deleted file mode 100644
index 420eb52..0000000
Binary files a/images/webp/b_0.webp and /dev/null differ
diff --git a/images/webp/b_1.webp b/images/webp/b_1.webp
deleted file mode 100644
index 84e5a58..0000000
Binary files a/images/webp/b_1.webp and /dev/null differ
diff --git a/images/webp/b_2.webp b/images/webp/b_2.webp
deleted file mode 100644
index 3e1639b..0000000
Binary files a/images/webp/b_2.webp and /dev/null differ
diff --git a/images/webp/b_3.webp b/images/webp/b_3.webp
deleted file mode 100644
index 55924c0..0000000
Binary files a/images/webp/b_3.webp and /dev/null differ
diff --git a/images/webp/b_4.webp b/images/webp/b_4.webp
deleted file mode 100644
index de9d39f..0000000
Binary files a/images/webp/b_4.webp and /dev/null differ
diff --git a/images/webp/b_5.webp b/images/webp/b_5.webp
deleted file mode 100644
index c9b7f2d..0000000
Binary files a/images/webp/b_5.webp and /dev/null differ
diff --git a/images/webp/b_6.webp b/images/webp/b_6.webp
deleted file mode 100644
index 27a6777..0000000
Binary files a/images/webp/b_6.webp and /dev/null differ
diff --git a/images/webp/b_7.webp b/images/webp/b_7.webp
deleted file mode 100644
index b8e259e..0000000
Binary files a/images/webp/b_7.webp and /dev/null differ
diff --git a/images/webp/b_8.webp b/images/webp/b_8.webp
deleted file mode 100644
index f5862da..0000000
Binary files a/images/webp/b_8.webp and /dev/null differ
diff --git a/images/webp/b_9.webp b/images/webp/b_9.webp
deleted file mode 100644
index b173edd..0000000
Binary files a/images/webp/b_9.webp and /dev/null differ
diff --git a/images/webp/b_draw.webp b/images/webp/b_draw.webp
deleted file mode 100644
index 5cd9285..0000000
Binary files a/images/webp/b_draw.webp and /dev/null differ
diff --git a/images/webp/b_reverse.webp b/images/webp/b_reverse.webp
deleted file mode 100644
index 4bc8846..0000000
Binary files a/images/webp/b_reverse.webp and /dev/null differ
diff --git a/images/webp/b_skip.webp b/images/webp/b_skip.webp
deleted file mode 100644
index 3b0a40c..0000000
Binary files a/images/webp/b_skip.webp and /dev/null differ
diff --git a/images/webp/colorchooser.webp b/images/webp/colorchooser.webp
deleted file mode 100644
index 5254ae5..0000000
Binary files a/images/webp/colorchooser.webp and /dev/null differ
diff --git a/images/webp/draw_four.webp b/images/webp/draw_four.webp
deleted file mode 100644
index c67b6f0..0000000
Binary files a/images/webp/draw_four.webp and /dev/null differ
diff --git a/images/webp/g_0.webp b/images/webp/g_0.webp
deleted file mode 100644
index 42b1d53..0000000
Binary files a/images/webp/g_0.webp and /dev/null differ
diff --git a/images/webp/g_1.webp b/images/webp/g_1.webp
deleted file mode 100644
index d62936f..0000000
Binary files a/images/webp/g_1.webp and /dev/null differ
diff --git a/images/webp/g_2.webp b/images/webp/g_2.webp
deleted file mode 100644
index 3146b6e..0000000
Binary files a/images/webp/g_2.webp and /dev/null differ
diff --git a/images/webp/g_3.webp b/images/webp/g_3.webp
deleted file mode 100644
index 09c333e..0000000
Binary files a/images/webp/g_3.webp and /dev/null differ
diff --git a/images/webp/g_4.webp b/images/webp/g_4.webp
deleted file mode 100644
index af456c0..0000000
Binary files a/images/webp/g_4.webp and /dev/null differ
diff --git a/images/webp/g_5.webp b/images/webp/g_5.webp
deleted file mode 100644
index 185150e..0000000
Binary files a/images/webp/g_5.webp and /dev/null differ
diff --git a/images/webp/g_6.webp b/images/webp/g_6.webp
deleted file mode 100644
index 6f27df6..0000000
Binary files a/images/webp/g_6.webp and /dev/null differ
diff --git a/images/webp/g_7.webp b/images/webp/g_7.webp
deleted file mode 100644
index ffe779a..0000000
Binary files a/images/webp/g_7.webp and /dev/null differ
diff --git a/images/webp/g_8.webp b/images/webp/g_8.webp
deleted file mode 100644
index d912fde..0000000
Binary files a/images/webp/g_8.webp and /dev/null differ
diff --git a/images/webp/g_9.webp b/images/webp/g_9.webp
deleted file mode 100644
index dd7e19c..0000000
Binary files a/images/webp/g_9.webp and /dev/null differ
diff --git a/images/webp/g_draw.webp b/images/webp/g_draw.webp
deleted file mode 100644
index 1de1392..0000000
Binary files a/images/webp/g_draw.webp and /dev/null differ
diff --git a/images/webp/g_reverse.webp b/images/webp/g_reverse.webp
deleted file mode 100644
index 34b83ff..0000000
Binary files a/images/webp/g_reverse.webp and /dev/null differ
diff --git a/images/webp/g_skip.webp b/images/webp/g_skip.webp
deleted file mode 100644
index f3ee3f2..0000000
Binary files a/images/webp/g_skip.webp and /dev/null differ
diff --git a/images/webp/option_bluff.webp b/images/webp/option_bluff.webp
deleted file mode 100644
index 8c531a4..0000000
Binary files a/images/webp/option_bluff.webp and /dev/null differ
diff --git a/images/webp/option_draw.webp b/images/webp/option_draw.webp
deleted file mode 100644
index 5332b23..0000000
Binary files a/images/webp/option_draw.webp and /dev/null differ
diff --git a/images/webp/option_draw_old.webp b/images/webp/option_draw_old.webp
deleted file mode 100644
index 3880f1e..0000000
Binary files a/images/webp/option_draw_old.webp and /dev/null differ
diff --git a/images/webp/option_info.webp b/images/webp/option_info.webp
deleted file mode 100644
index 2022781..0000000
Binary files a/images/webp/option_info.webp and /dev/null differ
diff --git a/images/webp/option_pass.webp b/images/webp/option_pass.webp
deleted file mode 100644
index ca6ce9d..0000000
Binary files a/images/webp/option_pass.webp and /dev/null differ
diff --git a/images/webp/option_pass_old.webp b/images/webp/option_pass_old.webp
deleted file mode 100644
index d02a611..0000000
Binary files a/images/webp/option_pass_old.webp and /dev/null differ
diff --git a/images/webp/r_0.webp b/images/webp/r_0.webp
deleted file mode 100644
index 4d434ee..0000000
Binary files a/images/webp/r_0.webp and /dev/null differ
diff --git a/images/webp/r_1.webp b/images/webp/r_1.webp
deleted file mode 100644
index 54e25b3..0000000
Binary files a/images/webp/r_1.webp and /dev/null differ
diff --git a/images/webp/r_2.webp b/images/webp/r_2.webp
deleted file mode 100644
index 31686cf..0000000
Binary files a/images/webp/r_2.webp and /dev/null differ
diff --git a/images/webp/r_3.webp b/images/webp/r_3.webp
deleted file mode 100644
index 5ac698e..0000000
Binary files a/images/webp/r_3.webp and /dev/null differ
diff --git a/images/webp/r_4.webp b/images/webp/r_4.webp
deleted file mode 100644
index fef9835..0000000
Binary files a/images/webp/r_4.webp and /dev/null differ
diff --git a/images/webp/r_5.webp b/images/webp/r_5.webp
deleted file mode 100644
index 67cd405..0000000
Binary files a/images/webp/r_5.webp and /dev/null differ
diff --git a/images/webp/r_6.webp b/images/webp/r_6.webp
deleted file mode 100644
index b61fe11..0000000
Binary files a/images/webp/r_6.webp and /dev/null differ
diff --git a/images/webp/r_7.webp b/images/webp/r_7.webp
deleted file mode 100644
index aeba4b3..0000000
Binary files a/images/webp/r_7.webp and /dev/null differ
diff --git a/images/webp/r_8.webp b/images/webp/r_8.webp
deleted file mode 100644
index f5f0d2b..0000000
Binary files a/images/webp/r_8.webp and /dev/null differ
diff --git a/images/webp/r_9.webp b/images/webp/r_9.webp
deleted file mode 100644
index c78676b..0000000
Binary files a/images/webp/r_9.webp and /dev/null differ
diff --git a/images/webp/r_draw.webp b/images/webp/r_draw.webp
deleted file mode 100644
index c3d56cc..0000000
Binary files a/images/webp/r_draw.webp and /dev/null differ
diff --git a/images/webp/r_reverse.webp b/images/webp/r_reverse.webp
deleted file mode 100644
index a18c382..0000000
Binary files a/images/webp/r_reverse.webp and /dev/null differ
diff --git a/images/webp/r_skip.webp b/images/webp/r_skip.webp
deleted file mode 100644
index 4922dc7..0000000
Binary files a/images/webp/r_skip.webp and /dev/null differ
diff --git a/images/webp/y_0.webp b/images/webp/y_0.webp
deleted file mode 100644
index b7ad2b2..0000000
Binary files a/images/webp/y_0.webp and /dev/null differ
diff --git a/images/webp/y_1.webp b/images/webp/y_1.webp
deleted file mode 100644
index f9aa282..0000000
Binary files a/images/webp/y_1.webp and /dev/null differ
diff --git a/images/webp/y_2.webp b/images/webp/y_2.webp
deleted file mode 100644
index e292c49..0000000
Binary files a/images/webp/y_2.webp and /dev/null differ
diff --git a/images/webp/y_3.webp b/images/webp/y_3.webp
deleted file mode 100644
index 4d49fac..0000000
Binary files a/images/webp/y_3.webp and /dev/null differ
diff --git a/images/webp/y_4.webp b/images/webp/y_4.webp
deleted file mode 100644
index b713f10..0000000
Binary files a/images/webp/y_4.webp and /dev/null differ
diff --git a/images/webp/y_5.webp b/images/webp/y_5.webp
deleted file mode 100644
index cd9c819..0000000
Binary files a/images/webp/y_5.webp and /dev/null differ
diff --git a/images/webp/y_6.webp b/images/webp/y_6.webp
deleted file mode 100644
index 1350187..0000000
Binary files a/images/webp/y_6.webp and /dev/null differ
diff --git a/images/webp/y_7.webp b/images/webp/y_7.webp
deleted file mode 100644
index 24683f1..0000000
Binary files a/images/webp/y_7.webp and /dev/null differ
diff --git a/images/webp/y_8.webp b/images/webp/y_8.webp
deleted file mode 100644
index 66e4e6f..0000000
Binary files a/images/webp/y_8.webp and /dev/null differ
diff --git a/images/webp/y_9.webp b/images/webp/y_9.webp
deleted file mode 100644
index 385f465..0000000
Binary files a/images/webp/y_9.webp and /dev/null differ
diff --git a/images/webp/y_draw.webp b/images/webp/y_draw.webp
deleted file mode 100644
index ebbc5ed..0000000
Binary files a/images/webp/y_draw.webp and /dev/null differ
diff --git a/images/webp/y_reverse.webp b/images/webp/y_reverse.webp
deleted file mode 100644
index c67f1de..0000000
Binary files a/images/webp/y_reverse.webp and /dev/null differ
diff --git a/images/webp/y_skip.webp b/images/webp/y_skip.webp
deleted file mode 100644
index ed98743..0000000
Binary files a/images/webp/y_skip.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_0.webp b/images/webp_lowsat/b_0.webp
deleted file mode 100644
index 3f89279..0000000
Binary files a/images/webp_lowsat/b_0.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_1.webp b/images/webp_lowsat/b_1.webp
deleted file mode 100644
index 117403a..0000000
Binary files a/images/webp_lowsat/b_1.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_2.webp b/images/webp_lowsat/b_2.webp
deleted file mode 100644
index b300c00..0000000
Binary files a/images/webp_lowsat/b_2.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_3.webp b/images/webp_lowsat/b_3.webp
deleted file mode 100644
index b2f1a03..0000000
Binary files a/images/webp_lowsat/b_3.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_4.webp b/images/webp_lowsat/b_4.webp
deleted file mode 100644
index 6cdb693..0000000
Binary files a/images/webp_lowsat/b_4.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_5.webp b/images/webp_lowsat/b_5.webp
deleted file mode 100644
index 8734f05..0000000
Binary files a/images/webp_lowsat/b_5.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_6.webp b/images/webp_lowsat/b_6.webp
deleted file mode 100644
index d56868d..0000000
Binary files a/images/webp_lowsat/b_6.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_7.webp b/images/webp_lowsat/b_7.webp
deleted file mode 100644
index 0cdb0a6..0000000
Binary files a/images/webp_lowsat/b_7.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_8.webp b/images/webp_lowsat/b_8.webp
deleted file mode 100644
index 90a78f2..0000000
Binary files a/images/webp_lowsat/b_8.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_9.webp b/images/webp_lowsat/b_9.webp
deleted file mode 100644
index 6f385cb..0000000
Binary files a/images/webp_lowsat/b_9.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_draw.webp b/images/webp_lowsat/b_draw.webp
deleted file mode 100644
index 498149a..0000000
Binary files a/images/webp_lowsat/b_draw.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_reverse.webp b/images/webp_lowsat/b_reverse.webp
deleted file mode 100644
index ba6f1f7..0000000
Binary files a/images/webp_lowsat/b_reverse.webp and /dev/null differ
diff --git a/images/webp_lowsat/b_skip.webp b/images/webp_lowsat/b_skip.webp
deleted file mode 100644
index cfe955a..0000000
Binary files a/images/webp_lowsat/b_skip.webp and /dev/null differ
diff --git a/images/webp_lowsat/colorchooser.webp b/images/webp_lowsat/colorchooser.webp
deleted file mode 100644
index ee5c7fa..0000000
Binary files a/images/webp_lowsat/colorchooser.webp and /dev/null differ
diff --git a/images/webp_lowsat/draw_four.webp b/images/webp_lowsat/draw_four.webp
deleted file mode 100644
index a93b759..0000000
Binary files a/images/webp_lowsat/draw_four.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_0.webp b/images/webp_lowsat/g_0.webp
deleted file mode 100644
index d380e1a..0000000
Binary files a/images/webp_lowsat/g_0.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_1.webp b/images/webp_lowsat/g_1.webp
deleted file mode 100644
index 0709297..0000000
Binary files a/images/webp_lowsat/g_1.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_2.webp b/images/webp_lowsat/g_2.webp
deleted file mode 100644
index d77b87c..0000000
Binary files a/images/webp_lowsat/g_2.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_3.webp b/images/webp_lowsat/g_3.webp
deleted file mode 100644
index 2289300..0000000
Binary files a/images/webp_lowsat/g_3.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_4.webp b/images/webp_lowsat/g_4.webp
deleted file mode 100644
index 3611653..0000000
Binary files a/images/webp_lowsat/g_4.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_5.webp b/images/webp_lowsat/g_5.webp
deleted file mode 100644
index cb29d26..0000000
Binary files a/images/webp_lowsat/g_5.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_6.webp b/images/webp_lowsat/g_6.webp
deleted file mode 100644
index 938f501..0000000
Binary files a/images/webp_lowsat/g_6.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_7.webp b/images/webp_lowsat/g_7.webp
deleted file mode 100644
index 0a42d2a..0000000
Binary files a/images/webp_lowsat/g_7.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_8.webp b/images/webp_lowsat/g_8.webp
deleted file mode 100644
index 4d06b4c..0000000
Binary files a/images/webp_lowsat/g_8.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_9.webp b/images/webp_lowsat/g_9.webp
deleted file mode 100644
index 22112f3..0000000
Binary files a/images/webp_lowsat/g_9.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_draw.webp b/images/webp_lowsat/g_draw.webp
deleted file mode 100644
index bcbd98b..0000000
Binary files a/images/webp_lowsat/g_draw.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_reverse.webp b/images/webp_lowsat/g_reverse.webp
deleted file mode 100644
index 59838a6..0000000
Binary files a/images/webp_lowsat/g_reverse.webp and /dev/null differ
diff --git a/images/webp_lowsat/g_skip.webp b/images/webp_lowsat/g_skip.webp
deleted file mode 100644
index 603ebbd..0000000
Binary files a/images/webp_lowsat/g_skip.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_0.webp b/images/webp_lowsat/r_0.webp
deleted file mode 100644
index 4a13ae0..0000000
Binary files a/images/webp_lowsat/r_0.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_1.webp b/images/webp_lowsat/r_1.webp
deleted file mode 100644
index 9ed6277..0000000
Binary files a/images/webp_lowsat/r_1.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_2.webp b/images/webp_lowsat/r_2.webp
deleted file mode 100644
index 6389660..0000000
Binary files a/images/webp_lowsat/r_2.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_3.webp b/images/webp_lowsat/r_3.webp
deleted file mode 100644
index 71fb6be..0000000
Binary files a/images/webp_lowsat/r_3.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_4.webp b/images/webp_lowsat/r_4.webp
deleted file mode 100644
index ef3d574..0000000
Binary files a/images/webp_lowsat/r_4.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_5.webp b/images/webp_lowsat/r_5.webp
deleted file mode 100644
index addb5f9..0000000
Binary files a/images/webp_lowsat/r_5.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_6.webp b/images/webp_lowsat/r_6.webp
deleted file mode 100644
index 09718a4..0000000
Binary files a/images/webp_lowsat/r_6.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_7.webp b/images/webp_lowsat/r_7.webp
deleted file mode 100644
index 0ad64df..0000000
Binary files a/images/webp_lowsat/r_7.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_8.webp b/images/webp_lowsat/r_8.webp
deleted file mode 100644
index cf70b5d..0000000
Binary files a/images/webp_lowsat/r_8.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_9.webp b/images/webp_lowsat/r_9.webp
deleted file mode 100644
index 8508990..0000000
Binary files a/images/webp_lowsat/r_9.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_draw.webp b/images/webp_lowsat/r_draw.webp
deleted file mode 100644
index 4ac1d72..0000000
Binary files a/images/webp_lowsat/r_draw.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_reverse.webp b/images/webp_lowsat/r_reverse.webp
deleted file mode 100644
index c5effef..0000000
Binary files a/images/webp_lowsat/r_reverse.webp and /dev/null differ
diff --git a/images/webp_lowsat/r_skip.webp b/images/webp_lowsat/r_skip.webp
deleted file mode 100644
index 780707d..0000000
Binary files a/images/webp_lowsat/r_skip.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_0.webp b/images/webp_lowsat/y_0.webp
deleted file mode 100644
index d497b59..0000000
Binary files a/images/webp_lowsat/y_0.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_1.webp b/images/webp_lowsat/y_1.webp
deleted file mode 100644
index 5a7b632..0000000
Binary files a/images/webp_lowsat/y_1.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_2.webp b/images/webp_lowsat/y_2.webp
deleted file mode 100644
index 37bacff..0000000
Binary files a/images/webp_lowsat/y_2.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_3.webp b/images/webp_lowsat/y_3.webp
deleted file mode 100644
index b8f24d3..0000000
Binary files a/images/webp_lowsat/y_3.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_4.webp b/images/webp_lowsat/y_4.webp
deleted file mode 100644
index 98ef259..0000000
Binary files a/images/webp_lowsat/y_4.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_5.webp b/images/webp_lowsat/y_5.webp
deleted file mode 100644
index cc94b9e..0000000
Binary files a/images/webp_lowsat/y_5.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_6.webp b/images/webp_lowsat/y_6.webp
deleted file mode 100644
index d8effbe..0000000
Binary files a/images/webp_lowsat/y_6.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_7.webp b/images/webp_lowsat/y_7.webp
deleted file mode 100644
index d1eed2c..0000000
Binary files a/images/webp_lowsat/y_7.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_8.webp b/images/webp_lowsat/y_8.webp
deleted file mode 100644
index 619b648..0000000
Binary files a/images/webp_lowsat/y_8.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_9.webp b/images/webp_lowsat/y_9.webp
deleted file mode 100644
index c581723..0000000
Binary files a/images/webp_lowsat/y_9.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_draw.webp b/images/webp_lowsat/y_draw.webp
deleted file mode 100644
index 0fb569a..0000000
Binary files a/images/webp_lowsat/y_draw.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_reverse.webp b/images/webp_lowsat/y_reverse.webp
deleted file mode 100644
index e6fa51c..0000000
Binary files a/images/webp_lowsat/y_reverse.webp and /dev/null differ
diff --git a/images/webp_lowsat/y_skip.webp b/images/webp_lowsat/y_skip.webp
deleted file mode 100644
index f9f6eee..0000000
Binary files a/images/webp_lowsat/y_skip.webp and /dev/null differ
diff --git a/images/xcf/bluff.xcf b/images/xcf/bluff.xcf
deleted file mode 100644
index 1aaa539..0000000
Binary files a/images/xcf/bluff.xcf and /dev/null differ
diff --git a/images/xcf/draw.xcf b/images/xcf/draw.xcf
deleted file mode 100644
index c661781..0000000
Binary files a/images/xcf/draw.xcf and /dev/null differ
diff --git a/images/xcf/info.xcf b/images/xcf/info.xcf
deleted file mode 100644
index 6c3a400..0000000
Binary files a/images/xcf/info.xcf and /dev/null differ
diff --git a/images/xcf/pass.xcf b/images/xcf/pass.xcf
deleted file mode 100644
index 7dd29dc..0000000
Binary files a/images/xcf/pass.xcf and /dev/null differ
diff --git a/internationalization.py b/internationalization.py
deleted file mode 100644
index 9bf4a9e..0000000
--- a/internationalization.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import gettext
-from functools import wraps
-
-from pony.orm import db_session
-from telegram import Update
-from telegram.ext import ContextTypes
-
-from locales import available_locales
-from shared_vars import gm
-from user_setting import UserSetting
-
-GETTEXT_DOMAIN = "unobot"
-GETTEXT_DIR = "locales"
-
-
-class _Underscore:
- """Class to emulate flufl.i18n behaviour, but with plural support."""
-
- def __init__(self) -> None:
- self.translators = {
- locale: gettext.GNUTranslations(
- open(
- gettext.find(GETTEXT_DOMAIN, GETTEXT_DIR, languages=[locale]),
- "rb",
- ),
- )
- for locale in available_locales
- if locale != "en_US" # No translation file for en_US
- }
- self.locale_stack = []
-
- def push(self, locale):
- self.locale_stack.append(locale)
-
- def pop(self):
- return self.locale_stack.pop() if self.locale_stack else None
-
- @property
- def code(self):
- return self.locale_stack[-1] if self.locale_stack else None
-
- def __call__(self, singular, plural=None, n=1, locale=None):
- if not locale:
- locale = self.locale_stack[-1]
-
- if locale not in self.translators.keys():
- return singular if n == 1 else plural
- translator = self.translators[locale]
-
- if plural is None:
- return translator.gettext(singular)
- else:
- return translator.ngettext(singular, plural, n)
-
-
-_ = _Underscore()
-
-
-def __(singular, plural=None, n=1, multi=False):
- """Translates text into all locales on the stack."""
- translations = []
-
- if not multi and set(_.locale_stack):
- translations.append(_(singular, plural, n, "en_US"))
-
- else:
- for locale in _.locale_stack:
- translation = _(singular, plural, n, locale)
-
- if translation not in translations:
- translations.append(translation)
-
- return "\n".join(translations)
-
-
-def user_locale(func):
- @wraps(func)
- async def wrapped(
- update: Update,
- context: ContextTypes.DEFAULT_TYPE,
- *pargs,
- **kwargs,
- ):
- user = _user_chat_from_update(update)[0]
-
- with db_session:
- us = UserSetting.get(id=user.id)
-
- if us and us.lang != "en":
- _.push(us.lang)
- else:
- _.push("en_US")
-
- result = await func(update, context, *pargs, **kwargs)
- _.pop()
- return result
-
- return wrapped
-
-
-def game_locales(func):
- @wraps(func)
- async def wrapped(
- update: Update,
- context: ContextTypes.DEFAULT_TYPE,
- *pargs,
- **kwargs,
- ):
- user, chat = _user_chat_from_update(update)
- player = gm.player_for_user_in_chat(user, chat)
- locales = []
-
- if player:
- for player in player.game.players:
- with db_session:
- us = UserSetting.get(id=player.user.id)
-
- loc = us.lang if us and us.lang != "en" else "en_US"
- if loc in locales:
- continue
-
- _.push(loc)
- locales.append(loc)
-
- result = await func(update, context, *pargs, **kwargs)
-
- while _.code:
- _.pop()
-
- return result
-
- return wrapped
-
-
-def _user_chat_from_update(update):
- try:
- user = update.message.from_user
- chat = update.message.chat
- except (NameError, AttributeError):
- try:
- user = update.inline_query.from_user
- chat = gm.userid_current[user.id].game.chat
- except KeyError:
- chat = None
- except (NameError, AttributeError):
- try:
- user = update.chosen_inline_result.from_user
- chat = gm.userid_current[user.id].game.chat
- except (NameError, AttributeError, KeyError):
- chat = None
-
- return user, chat
diff --git a/locales.py b/locales.py
new file mode 100644
index 0000000..c5afb0a
--- /dev/null
+++ b/locales.py
@@ -0,0 +1,93 @@
+import os
+from functools import partial, wraps
+from glob import glob
+from typing import Dict, List
+from hydrogram.types import Message
+from hydrogram.enums import ChatType
+from config import player_game
+from game import Game
+
+import yaml
+
+from db import User, Chat
+
+langs = ["en-US", "pt-BR"]
+
+default_language = "en-US"
+
+
+def cache_localizations(files: List[str]) -> Dict[str, Dict[str, Dict[str, str]]]:
+ ldict = {lang: {} for lang in langs}
+ for file in files:
+ _, pname = file.split(os.path.sep)
+ lang = pname.split(".")[0]
+ with open(file, "r") as f:
+ ldict[lang] = yaml.safe_load(f)
+ return ldict
+
+
+jsons = []
+
+for locale in langs:
+ jsons += glob(os.path.join("locales", f"{locale}.yml"))
+
+langdict = cache_localizations(jsons)
+
+
+def use_lang():
+ def decorator(func):
+ @wraps(func)
+ async def wrapper(client, message):
+ ulang = (await User.get_or_create(id=message.from_user.id))[0].lang
+ if not isinstance(message, Message):
+ if message.from_user.id not in player_game:
+ clang = ulang
+ else:
+ game: Game = player_game[message.from_user.id]
+ chatid = game.chat.id
+ clang = (await Chat.get_or_create(id=chatid))[0].lang
+ else:
+ clang = (await Chat.get_or_create(id=message.chat.id))[0].lang
+ ulfunc = partial(get_locale_string, ulang)
+ clfunc = partial(get_locale_string, clang)
+ return await func(client, message, ulfunc, clfunc)
+
+ return wrapper
+
+ return decorator
+
+
+def use_chat_lang():
+ def decorator(func):
+ @wraps(func)
+ async def wrapper(client, message):
+ mmessage = message.message if not isinstance(message, Message) else message
+ if mmessage.chat.type == ChatType.PRIVATE:
+ clang = (await User.get_or_create(id=mmessage.chat.id))[0].lang
+ else:
+ clang = (await Chat.get_or_create(id=mmessage.chat.id))[0].lang
+ clfunc = partial(get_locale_string, clang)
+ return await func(client, message, clfunc)
+
+ return wrapper
+
+ return decorator
+
+
+def use_user_lang():
+ def decorator(func):
+ @wraps(func)
+ async def wrapper(client, message):
+ ulang = (await User.get_or_create(id=message.from_user.id))[0].lang
+ ulfunc = partial(get_locale_string, ulang)
+ return await func(client, message, ulfunc)
+
+ return wrapper
+
+ return decorator
+
+
+def get_locale_string(language: str, key: str) -> str:
+ print(f"Getting {key} for {language}")
+ res: str = langdict[language].get(key) or key
+ return res
diff --git a/locales/__init__.py b/locales/__init__.py
deleted file mode 100644
index c646639..0000000
--- a/locales/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from .available import available_locales
-
-__all__ = ["available_locales"]
diff --git a/locales/available.py b/locales/available.py
deleted file mode 100644
index d777661..0000000
--- a/locales/available.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-
-"""Defines a dict of all available locales to the language name."""
-
-OFFSET = 127462 - ord("A")
-
-
-def flag(code):
- return chr(ord(code[0]) + OFFSET) + chr(ord(code[1]) + OFFSET)
-
-
-available_locales = {
- "en_US": flag("US") + " English (US)",
- "de_DE": flag("DE") + " Deutsch (DE)",
- "es_ES": flag("ES") + " Español (ES)",
- "id_ID": flag("ID") + " Bahasa Indonesia",
- "it_IT": flag("IT") + " Italiano",
- "pt_BR": flag("BR") + " Português Brasileiro",
- "pt": flag("PT") + " Português",
- "nb_NO": flag("NO") + " norsk",
- "ru_RU": flag("RU") + " Русский язык",
- "tr_TR": flag("TR") + " Türkçe",
- "zh_CN": flag("CN") + " 中文(简体)",
- "zh_HK": flag("HK") + " 廣東話",
- "zh_TW": flag("TW") + " 中文(台灣)",
- "ca_CA": flag("ES") + " Catalan",
- "ml_IN": flag("IN") + " Malayalam",
-}
diff --git a/locales/ca_CA/LC_MESSAGES/unobot.po b/locales/ca_CA/LC_MESSAGES/unobot.po
deleted file mode 100644
index fdffcc8..0000000
--- a/locales/ca_CA/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,557 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-12 02:46-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Catalan \n"
-"Language: ca_CA\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} ha guanyat!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Partida acabada!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Si us plau, selecciona un color"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "No hi ha més cartes al plat."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Era un fanal! {name} reb 4 cartes"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} no ha fet cap fanal! {name2} reb 6 cartes"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr ""
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Nova partida creada! Uniu-vos a la partida amb /join i comenceu amb /start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "No hi ha cap partida en execució en aquest xat."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "La sala està tancada"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr ""
-"En aquest moment no hi ha cap partida en marxa. Crea una partida nova amb /"
-"new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Ja t'has unit a la partida. Inicia-la amb /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "{name} s'ha unit a la partida"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "No estàs jugant a cap partida en aquest grup."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Okay. Següent jugagor: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Partida no trobada."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Torna a l'últim grup"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Si us plau canvia al grup que has seleccionat!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grup seleccionat: {group}\n"
-"Assegura't d'haver canviat al grup correcte!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Eliminant {name} de la partida"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "No hi ha cap partida en aquest xat. Crea una nova amb /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "La partida ja ha començat"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Abans de començar la partida, al menys {minplayers} jugadors han de unir-se "
-"utilitzant /join"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Primer jugador: {name}\n"
-"Utilitza /close per evitar que la gent s'afageixi a la partida.\n"
-"Habilita multi-traduccions amb /enable_translations."
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Selecciona el grup en el qual vols jugar."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-"Sala tancada. No hi ha més jugadors que puguin unir-se a aquesta partida."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Sala oberta. Els jugadors nous poden unir-se a la partida amb /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-traduccions activades. Desactiva-les amb /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "Multi-traduccions desactivades. Ativales amb /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "No estàs a cap partida en aquest xat."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Si us plau, espera {time} segon"
-msgstr[1] "Si us plau, espera {time} segons"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} ha intentat fer trampes"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Següent jugador: {name}."
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "El temps d'espera per a {name} s'ha reiniciat a {time} segons"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Selecciona un color"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} carta)"
-msgstr[1] "{name} ({number} cartes)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "No estàs jugant"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"No estàs jugant en aquest moment. Utilitza /new Per començar una partida o /"
-"join si ja hi ha una partida en curs dins d'aquest grup"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "La partida encara no ha començat"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Comença la partida amb /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Agafant {number} carta del piló"
-msgstr[1] "Agafant {number} cartes del piló"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Passar"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Es un fanal!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Jugador actual: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Última carta: {card}."
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Jugador: {player_list}"
-msgstr[1] "Jugadors: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Si us plau, edita els teus ajustos en un xat privat amb el bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Esborrar les estadístiques"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Activar les estadístiques"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Idioma"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Configuració"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Estadístiques activades!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Selecciona la teva llengua"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Estadístiques esborrades i desactivades!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Llengua seleccionada!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Aquest bot és programari lliure i està llicenciat sota l'AGPL. El codi està "
-"disponible aquí: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Totes les noticies aquí: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Les teves estadístiques no estan activades. Utilitza /settings en un xat "
-"privat amb el bot per activarles."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} partida jugada"
-msgstr[1] "{number} partides jugades"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} primer lloc ({percent}%)"
-msgstr[1] "{number} primers llocs ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} carta jugada"
-msgstr[1] "{number} cartes jugades"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Vermell"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Blau"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Vert"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Groc"
diff --git a/locales/compile.sh b/locales/compile.sh
deleted file mode 100755
index f911e17..0000000
--- a/locales/compile.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-# This script compiles the unobot.po file for all languages.
-
-if [ ${PWD##*/} = "locales" ];
-then
- function compile {
- cd './'$1'/LC_MESSAGES/'
- msgfmt unobot.po -o unobot.mo
- cd ../../
- };
-else
- echo 'Only execute this in the "locales" directory'
- exit 1;
-fi
-
-# Deutsch
-compile de_DE
-# Spanish
-compile es_ES
-# Indonesian
-compile id_ID
-# Italian
-compile it_IT
-# Portuguese (Brazil)
-compile pt_BR
-# Portuguese
-compile pt
-# Norwegian Bokmål
-compile nb_NO
-# Russian
-compile ru_RU
-# Turkish
-compile tr_TR
-# Simplified Chinese
-compile zh_CN
-# Chinese (Honk Kong)
-compile zh_HK
-# Traditional Chinese
-compile zh_TW
-# Catalan
-compile ca_CA
-#Malayalam
-compile ml_IN
diff --git a/locales/de_DE/LC_MESSAGES/unobot.po b/locales/de_DE/LC_MESSAGES/unobot.po
deleted file mode 100644
index c068ec7..0000000
--- a/locales/de_DE/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,560 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-# Jannes Höke , 2016.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: German "
-"\n"
-"Language: de_DE\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: utf-8\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} hat gewonnen!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Spiel beendet!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Bitte wähle eine Farbe"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Es sind keine Karten mehr im Deck."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Bluff gecalled! {name} bekommt 4 Karten"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} hat nicht geblufft! {name2} bekommt 6 Karten"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Benutze diesen Befehl in einer Gruppe, um über das nächste neu eröffnete "
-"Spiel informiert zu werden."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "In der Gruppe {title} wurde gerade ein neues Spiel gestartet"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Neues Spiel erstellt! Tritt dem Spiel mit /join bei und starte es mit /start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "In dieser Gruppe läuft gerade kein Spiel."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Die Lobby ist geschlossen"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Zur Zeit läuft kein Spiel. Erstelle ein neues mit /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Du bist dem Spiel bereits beigetreten. Starte es mit /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Spiel beigetreten"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Du spielst in keinem Spiel in dieser Gruppe."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Okay. Nächster Spieler: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Spiel nicht gefunden."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Zurück zur letzten Gruppe"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Bitte wechsele zu der Gruppe, die du gewählt hast!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Ausgewählte Gruppe: {group}\n"
-"Stell sicher, dass du in die richtige Gruppe wechselst!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Entferne {name} aus dem Spiel"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"In dieser Gruppe gibt es kein laufendes Spiel. Erstelle ein neues mit /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "Das Spiel hat bereits begonnen"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Erster Spieler: {name}\n"
-"Benutze /close, um zu verhindern, dass weitere Spieler beitreten.\n"
-"Aktivieren Sie Mehrfachübersetzungen mit /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Bitte wähle die Gruppe, in der du spielen willst."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-"Lobby geschlossen. Diesem Spiel können keine weiteren Spieler beitreten."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Lobby geöffnet. Neue Spieler können nun beitreten."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-Übersetzungen aktiviert. Deaktivieren mit /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Multi-Übersetzungen deaktiviert. Aktiviere sie wieder mit /"
-"enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Du spielst kein Spiel in dieser Gruppe."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Bitte warte {time} Sekunde"
-msgstr[1] "Bitte warte {time} Sekunden"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Aktuelles Spiel: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} hat versucht zu schummeln"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Nächster Spieler: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Wähle Farbe"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} Karte)"
-msgstr[1] "{name} ({number} Karten)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Du spielst gerade nicht"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Du spielst gerade nicht. Benutze /new um ein neues Spiel zu starten oder /"
-"join, um einem bestehenden Spiel beizutreten"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "Das Spiel wurde noch nicht gestartet"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Starte das Spiel mit /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Ich ziehe {number} Karte"
-msgstr[1] "Ich ziehe {number} Karten"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Passe"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Ich glaube du bluffst!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Aktueller Spieler: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Letzte Karte: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Spieler: {player_list}"
-msgstr[1] "Spieler: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Bitte ändere deine Einstellungen in einem privaten Chat mit dem Bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Alle Statistiken löschen"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Statistiken aktivieren"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Sprache"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Einstellungen"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Statistiken aktiviert!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Bitte Sprache auswählen"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Alle Statistiken gelöscht und deaktiviert!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Sprache gesetzt!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Dieser Bot ist Freie Software und lizenziert unter der AGPL. Der Quellcode "
-"ist hier verfügbar:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Alle News hier: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Du hast die Spiel-Statistiken nicht aktiviert. Aktiviere sie, mit dem /"
-"settings-Kommando in einem privaten Chat mit dem Bot."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} gespieltes Spiel"
-msgstr[1] "{number} gespielte Spiele"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} mal 1. Platz ({percent}%)"
-msgstr[1] "{number} mal 1. Platz ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} gespielte Karte"
-msgstr[1] "{number} gespielte Karten"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Rot"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Blau"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Grün"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Gelb"
diff --git a/locales/en-US.yml b/locales/en-US.yml
new file mode 100644
index 0000000..6373c01
--- /dev/null
+++ b/locales/en-US.yml
@@ -0,0 +1,69 @@
+lang_name: English
+lang_flag: 🇺🇸
+lang_changed: The language has been changed to English!
+back: Back
+theme: Theme
+info_theme: You choose a theme for the cards
+seven_zero: 7-0
+info_seven: When a 7 is played, the player can swap cards with another player. When a 0 is played, everyone passes their cards to the next player.
+sbluff: Bluff
+info_bluff: When a player plays a +4 card, the next one can challenge. If the player who played the +4 card has another card to play, they draw 4 cards. If not, the one who challenged draws 6.
+one_win: One winner
+info_one_win: When the first player runs out of cards, the game ends and they are the winner.
+one_card: Say UNO
+info_one_card: When a player has only one card, they must say UNO. If they don't, they must draw 2 cards.
+language: Language
+info_lang: You can change the bot's language.
+choose_lang: Choose a language
+start_text: "Hello! I am the UNO Bot, a bot to play UNO on Telegram!\n\nTo play, put me in a group and send /new to start a new game!\n\nor to configure use the buttons below!"
+game_mode: Game Mode
+status: Status
+game_mode_text: "Showing information of available game modes!\n\n"
+settings: "Welcome to the settings menu!\n\nChoose an option below to configure the bot."
+theme_config: "Choose a theme for the cards:"
+minimalist: Minimalist
+classic: Classic
+colorblind: Colorblind
+game_existis: There is already a game in progress!
+only_group: This command only works in groups!
+already_in_game: You are already in another game
+already_joined: You are already in the game!
+join: Join
+leave: Leave
+start_game: Start Game
+game_started: A new game has started!
+no_game: There is no game in progress!
+no_game_text: No game in progress, send /new to start a new game!
+lobby_closed: The lobby is closed!
+lobby_opened: The lobby is open!
+joined_game: You joined the game!
+player_joined: "{} joined the game!"
+no_joinned: You are not in the game!
+next: Next {}
+game_over: The game is over!
+player_left: "{} left the game!"
+left_game: You left the game!
+not_allowed: You are not allowed to do that!
+game_started: The game has already started!
+info_text: 🃏 Game Information:\nCurrent player - {current_player}\nLast card - {last_card}\n
+info_text2: "{player}: {cards} cards, "
+pass: Pass
+buy: Buy {} card(s)
+bluff: I think you're bluffing!
+cards_swapped: "{name1} swapped cards with {name2}"
+not_swapped: Due to the number of players, it was not possible to swap cards!
+swapped: The cards have been swapped!
+bought: You bought {buy} cards!
+bluffed: "{name} You can't bluff!\n{name} drew {draw} cards!"
+not_bluffed: "{name1} You didn't bluff!\n{name2} drew {draw} cards!"
+colorchoose: "{name} choose a color!"
+colorchoosed: I chose the color {color}!
+playerchoose: "{name} choose a player!"
+invalid_card: Invalid move!
+said_uno: "{name} shouted UNO!"
+say_uno: "{name} say UNO or draw 2 cards!"
+not_said_uno: "{name} You didn't shout UNO!\n{name} drew 2 cards!"
+first: " in first"
+won: "{name} won the game{comp}!"
+continuing: continuing the game with {count} players
+play: Play
diff --git a/locales/es_ES/LC_MESSAGES/unobot.po b/locales/es_ES/LC_MESSAGES/unobot.po
deleted file mode 100644
index c249ccd..0000000
--- a/locales/es_ES/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,630 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2023-02-22 18:37+0000\n"
-"Last-Translator: gallegonovato \n"
-"Language-Team: Spanish "
-"\n"
-"Language: es_ES\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.16-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"El tiempo de espera para saltar a este jugador se ha reducido a {time} "
-"segundos.\n"
-"Siguiente jugador: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"¡{name1} se quedó sin tiempo y ha sido eliminado de la partida!\n"
-"Siguiente jugador: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"¡{name} se ha quedado sin tiempo y ha sido eliminado de la partida!\n"
-"La partida terminó."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "¡{name} ganó!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "¡Fin de la partida!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Por favor, selecciona un color"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "No hay más cartas en la baraja."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "¡Era un farol! {name} recibe 4 cartas"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "¡{name1} no se había tirado un farol!, {name2} recibe 6 cartas"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Envía este comando en un grupo para recibir una notificación cuando comience "
-"una nueva partida allí."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-"Ok, serás notificado en un mensaje privado cuando la próxima partida se "
-"inicie en este chat. Asegúrate de que tengo permiso para enviarte mensajes."
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Se ha iniciado una nueva partida en {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"¡Nueva partida creada! Únete con /join. Cuando estéis todos listos, haz /"
-"start para empezar"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "No hay ninguna partida en curso en este grupo."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"La partida aún no ha comenzado. Únete al partida con /join y comienza la "
-"partida con /start"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-"Solo el creador del juego ({name}) y el administrador pueden hacer eso."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "La sala está cerrada"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "No hay ninguna partida en curso. Crea una partida con /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Ya te uniste a esta partida. Comienza la partida con /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-"No quedan suficientes cartas en el mazo para que se unan nuevos jugadores."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Te uniste a la partida"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "No estas jugando a una partida en este grupo."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Bueno. Siguiente jugador: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} abandonó la partida antes de que empezara."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "El jugador {name} no se encuentra en la partida actual."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} fue expulsado por {1}"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "Responda a la persona que desea expulsar y escriba /kick nuevamente."
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Partida no encontrada."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Volver al último grupo"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "¡Por favor, cambie al grupo que seleccionó!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grupo seleccionado: {group}\n"
-"¡Asegúrate de haber cambiado al grupo correcto!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Eliminando a {name} de la partida"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "No hay ninguna partida en curso en este chat. Crea una nueva con /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "La partida ya ha comenzado"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Antes de iniciar la partida, al menos {minplayers} jugadores deben unirse "
-"usando /join"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr "¡Haz tu elección!"
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Primer jugador: {name}\n"
-"Utiliza /close para impedir que la gente se una a la partida.\n"
-"Activa las multitraducciones con /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Elige el grupo en el que deseas jugar."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Sala cerrada. No podrán unirse más jugadores a la partida."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Sala abierta. Ahora pueden unirse nuevos jugadores usando /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr ""
-"Traducciones múltiples habilitadas. Deshabilitar con /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Multitraducciones deshabilitadas. Habilítelos de nuevo con "
-"/enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "No estás jugando una partida en este chat."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Por favor, espere {time} segundo"
-msgstr[1] "Por favor, espere {time} segundos"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Partida actual: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "El modo de juego ha cambiado a {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} intentó hacer trampa"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Siguiente Jugador: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "El tiempo de espera para {name} se ha reiniciado a {time} segundos"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr "Elegir jugador"
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Selecciona un color"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "Carta (toque para el estado del juego):"
-msgstr[1] "Cartas (toque para el estado del juego):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} carta)"
-msgstr[1] "{name} ({number} cartas)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "No estás jugando"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"No estás jugando en este momento. Usa /new para comenzar una partida o /join "
-"si hay una partida en curso en este grupo"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "La partida no ha comenzado todavía"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Comienza la partida con /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 Modo clásico"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "Clásico 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Modo Sanic"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "¡Hay que ir rápido! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 Modo salvaje"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "Hacia lo salvaje~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr "🔫 Modo 7-0"
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr "Modo carioca activado 🔫"
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr "✍️ Modo texto"
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr "Texto ✍️"
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Robando {number} carta"
-msgstr[1] "Robando {number} cartas"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Pasar"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "¡Es un farol!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Jugador actual: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Última carta: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Jugador: {player_list}"
-msgstr[1] "Jugadores: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Por favor, edita tus ajustes en un chat privado con el bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Borrar estadísticas"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Habilitar estadísticas"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Idioma"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Ajustes"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "¡Estadísticas habilitadas!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Selecciona tu idioma"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "¡Estadísticas borradas y deshabilitadas!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "¡Idioma seleccionado!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-"Sigue estos pasos:\n"
-"\n"
-"1. Agregue este bot a un grupo\n"
-"2. En el grupo, comience un juego nuevo con /nuevo o únase a un juego que ya "
-"se está ejecutando con /unirse\n"
-"3. Después de que se hayan unido al menos dos jugadores, comience el juego "
-"con /start\n"
-"4. Tipo@UnuRoboten tu ventana de chat y presionaespacio, "
-"o haga clic en elvía @UnuRobottexto junto a los mensajes. Verá "
-"sus tarjetas (algunas atenuadas), cualquier opción adicional como dibujar y "
-"un?para ver el estado actual del juego. lostarjetas atenuadas"
-"b>son esos que tuno puedo jugaren este momento. Toque una opción para "
-"ejecutar la acción seleccionada.\n"
-"Los jugadores pueden unirse al juego en cualquier momento. Para salir de un "
-"juego, usa /leave. Si un jugador tarda más de 90 segundos en jugar, puede "
-"usar /skip para omitir a ese jugador. Usa /notify_me para recibir un mensaje "
-"privado cuando se inicia un nuevo juego.\n"
-"\n"
-"Idiomay otras configuraciones: /configuraciones\n"
-"Otros comandos (solo creador de juegos):\n"
-"/cerrar - Cerrar el vestíbulo\n"
-"/open - Abrir vestíbulo\n"
-"/kill - Terminar el juego\n"
-"/kick - Selecciona un jugador para patear respondiéndole\n"
-"/enable_translations - Traduce textos relevantes a todos los idiomas "
-"hablados en un juego\n"
-"/disable_translations - Usa inglés para esos textos\n"
-"\n"
-"Experimental:Juega en varios grupos al mismo tiempo. presione "
-"elJuego actual: ...y seleccione el grupo en el que desea jugar "
-"una carta.\n"
-"Si te gusta este bot, únete alcanal "
-"de actualizacióny compra un juego de cartas UNO."
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-"Este bot de UNO tiene cinco modos de juego: Clásico, Sanic, Salvaje, Texto y "
-"7-0.\n"
-"\n"
-" 🎻 El modo Clásico usa el deck UNO convencional y no hay salto automático.\n"
-" 🚀 El modo Sanic usa el mazo UNO convencional y el bot omite "
-"automáticamente a un jugador si tarda demasiado en jugar su turno\n"
-" 🐉 El modo Wild usa un mazo con más cartas especiales, menos variedad de "
-"números y sin saltos automáticos.\n"
-" ✍️ El modo Texto usa el mazo UNO convencional pero en lugar de stickers usa "
-"el texto.\n"
-" 🔫 El modo 7-0 usa el mazo UNO convencional, pero cuando un jugador juega "
-"un 7, puede elegir un jugador con el que intercambiar cartas. Cuando un "
-"jugador juega un 0, todas las cartas se intercambiarán entre los jugadores "
-"actuales.\n"
-"\n"
-"Para cambiar el modo del juego, el CREADOR DEL JUEGO debe escribir el apodo "
-"del bot y un espacio, al igual que cuando juega una carta, y deberían "
-"aparecer todas las opciones del modo de juego."
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Este bot es Software Libre y esta licenciado bajo AGPL. El código esta "
-"disponible aquí:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"Atribuciones:\n"
-"Diseño de los iconos por Faithtoken\n"
-"Visto bueno a los iconos Delapouite\n"
-"Los originales se pueden encontrar en http://game-icons.net\n"
-"Iconos editados por ɳick"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Todas las noticias aquí: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Tus estadísticas no están habilitadas. Usa /settings en un chat privado con "
-"el bot para habilitarlas."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} partida jugada"
-msgstr[1] "{number} partidas jugadas"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} primer lugar ({percent}%)"
-msgstr[1] "{number} primeros lugares ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} carta jugada"
-msgstr[1] "{number} cartas jugadas"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Rojo"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Azul"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Verde"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Amarillo"
diff --git a/locales/id_ID/LC_MESSAGES/unobot.po b/locales/id_ID/LC_MESSAGES/unobot.po
deleted file mode 100644
index e9bb299..0000000
--- a/locales/id_ID/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,579 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-# Jannes Höke , 2016.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2023-06-24 02:40+0000\n"
-"Last-Translator: Reza Almanda \n"
-"Language-Team: Indonesian \n"
-"Language: id_ID\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: utf-8\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Weblate 4.18.1\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"Waktu tunggu terhadap {name} telah dikurangi menjadi {time} detik.\n"
-"Next player: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} kehabisan waktu dan telah dikeluarkan dari permainan!\n"
-"Pemain berikutnya: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} kehabisan waktu dan telah dikeluarkan dari permainan!\n"
-"Permainan berakhir."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} menang!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Permainan berakhir!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Silakan pilih warna"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Tidak ada kartu lagi tersedia."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Ternyata hanya gertakan! Memberikan 4 kartu kepada {name}"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} tidak hanya menggertak! Memberikan 6 kartu kepada {name2}"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Kirim perintah ini dalam grup untuk mendapatkan notifikasi ketika game baru "
-"dimulai di sana."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-"Oke, Anda akan diberitahu melalui pesan pribadi ketika permainan berikutnya "
-"dimulai dalam obrolan ini. Pastikan bahwa saya diizinkan untuk mengirimi "
-"Anda pesan."
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Permainan baru telah dimulai di {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Membuat permmainan baru! Ayo bergabung dengan perintah /join dan mulailah "
-"permainan tersebut dengan perintah /start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Tidak ada permainan yang berjalan pada grup chat ini."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"Permainan belum dimulai. Bergabunglah dengan permainan dengan /gabung dan "
-"mulai permainan dengan /mulai"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "Hanya pembuat game ({name}) dan admin yang dapat melakukannya."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Lobby ditutup"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr ""
-"Tidak ada permainan yang berlangsung. Buat permainan baru dengan perintah /"
-"new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr ""
-"Kamu sudah bergabung dengan permainan. Mulai permainan dengan perintah /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-"Tidak ada cukup kartu yang tersisa di dek untuk pemain baru untuk bergabung."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Tergabung dengan permainan"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Kamu tidak bermain di grup ini."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Baiklah. Pemain berikutnya: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} meninggalkan pertandingan sebelum pertandingan dimulai."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "Pemain {name} tidak ditemukan dalam permainan saat ini."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} ditendang oleh {1}"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "Silakan balas orang yang ingin Anda tendang dan ketik /tendang lagi."
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Permainan tidak ditemukan."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Kembali ke grup sebelumnya"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Silakan pilih grup!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grup terpilih: {group}\n"
-"Pastikan kamu sudah memilih grup yang benar!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Mengeluarkan {name} dari permainan"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"Tidak ada permainan yang berlangsung saat ini. Buat permainan baru dengan "
-"perintah /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "Permainan sudah dimulai"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Pemain pertama: {name}\n"
-"Gunakan /close untuk menghentikan pemain baru bergabung pada game ini.\n"
-"Aktifkan translasi multi bahasa dengan /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Silakan pilih pada grup mana kamu akan bermain."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Lobby ditutup. Tidak ada pemain yang bisa bergabung lagi."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Membuka lobby. Pemain baru bisa bergabung dengan perintah /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr ""
-"Mengaktifkan translasi multi bahasa. Non-aktifkan dengan /"
-"disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Menon-aktifkan translasi multi bahasa. Nyalakan kembali dengan perintah /"
-"enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Kamu sedang tidak bermain."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] ""
-msgstr[1] ""
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "Percobaan curang dilakukan oleh {name}"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Pemain berikutnya: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Pilih warna"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Kamu sedang tidak bermain"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Saat ini sedang tidak ada permainan. Gunakan perintah /new untuk memulai "
-"permainan atau /join untuk bergabung dengan permainan yang sedang "
-"berlangsung di grup ini"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "Permainan belum dimulai"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Mulailah permainan dengan perintah /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:209
-msgid "Pass"
-msgstr "Lewati"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Saya bilang, kamu hanya menggertak!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Pemain saat ini: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Kartu terakhir: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] ""
-msgstr[1] ""
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Silakan ubah pengaturan melalui chat pribadi dengan bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Menghapus semua statistik"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Mengaktifkan statistik"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Bahasa"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Pengaturan"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Mengaktifkan statistik"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Memilih lokasi"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Menghapus dan menonaktifkan statisk!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Pilih lokasi!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Bot ini adalah software gratis dan berlisensi dibawah AGPL. Kode nya "
-"tersedia disini: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Semua berita ada di sini: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Kamu belum menyalakan statistik. Gunakan /settings melalui chat pribadi "
-"kepada bot untuk menyalakannya."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] ""
-msgstr[1] ""
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] ""
-msgstr[1] ""
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] ""
-msgstr[1] ""
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Merah"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Biru"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Hijau"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Kuning"
diff --git a/locales/it_IT/LC_MESSAGES/unobot.po b/locales/it_IT/LC_MESSAGES/unobot.po
deleted file mode 100644
index 6dd1d6b..0000000
--- a/locales/it_IT/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,557 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Italian "
-"\n"
-"Language: it_IT\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} ha vinto!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "La partita è conclusa!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Per favore, scegli un colore"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Non ci sono più carte sul tavolo."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Il baro è stato scoperto! {name} deve pescare 4 carte"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} non ha barato! {name2} deve pescare 6 carte"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr ""
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"È stata creata una nuova partita! Unisciti con /join e inizia a giocare con /"
-"start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Non c'è alcuna partita aperta in questa chat."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "La stanza è chiusa. Nessun nuovo giocatore può unirsi alla partita"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Non c'è nessuna partita aperta al momento. Iniziane una nuova con /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Ti sei già unito/a alla partita. Inizia a giocare con /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Si è unito/a alla partita"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Non stai giocando alcuna partita in questo gruppo."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Okay. Prossimo giocatore: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Partita non trovata."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Vai all'ultimo gruppo"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Per favore, vai sul gruppo che hai selezionato!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Gruppo selezionato: {group}\n"
-"Assicurati di spostarti nel gruppo giusto!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Sto rimuovendo {name} dalla partita"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"Non c'è alcuna partita aperta in questa chat. Creane una nuova con /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "La partita è già iniziata"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Primo giocatore: {name}\n"
-"Usa /close per impedire a nuovi giocatori di unirsi alla partita.\n"
-"Abilita la funzione di multi-traduzione con /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Per favore, seleziona il gruppo dove vuoi giocare."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-"La stanza è chiusa. Nessun nuovo giocatore può unirsi alla partita in corso."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr ""
-"La stanza è aperta. Nuovi giocatori possono unirsi alla partita con /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-traduzione abilitata. Disabilitala con /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "Multi-traduzione disabilitata. Abilitala con /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Non stai giocando alcuna partita in questa chat."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Per favore, attendi {time} secondo"
-msgstr[1] "Per favore, attendi {time} secondi"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} ha tentato di barare"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Prossimo giocatore: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Scegli il colore"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} carta)"
-msgstr[1] "{name} ({number} carte)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Non stai giocando in questa partita"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Non stai giocando in questo momento. Usa /new per iniziare una nuova partita "
-"o /join per partecipare a quella già avviata in questo gruppo"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "La partita non è ancora iniziata"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Inizia la partita con /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Sto pescando {number} carta"
-msgstr[1] "Sto pescando {number} carte"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Passo"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Penso che tu stia barando!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Giocatore attuale: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Ultima carta: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Giocatori: {player_list}"
-msgstr[1] "Giocatori: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr ""
-"Per favore, modifica le tue impostazioni in una chat privata con il bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Elimina tutte le statistiche"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Abilita le statistiche"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Lingua"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Impostazioni"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Statistiche abilitate!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Seleziona la lingua"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Le statistiche sono state eliminate e disabilitate!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Lingua impostata!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Questo bot è un software gratuito e distribuito sotto licenza AGPL. Il "
-"codice è disponibile qui:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Tutte le novità le trovi qui: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Non hai abilitato le statistiche. Usa /settings in una chat privata col bot "
-"per abilitarle."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} partite giocate"
-msgstr[1] "{number} partite giocate"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} vittorie ({percent}%)"
-msgstr[1] "{number} vittorie ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} carta giocate"
-msgstr[1] "{number} carte giocate"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Rosso"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Blu"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Verde"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Giallo"
diff --git a/locales/ml_IN/LC_MESSAGES/unobot.po b/locales/ml_IN/LC_MESSAGES/unobot.po
deleted file mode 100644
index 54fe482..0000000
--- a/locales/ml_IN/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,559 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Malayalam \n"
-"Language: ml_IN\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} ജയിച്ചു!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "കളി അവസാനിച്ചു!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "നിറം തിരഞ്ഞെടുക്കുക."
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "ഡെക്കിൽ കൂടുതൽ കാർഡുകളൊന്നുമില്ല."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "ബ്ലഫ് വിളിച്ചു! {name} ന് 4 കാർഡുകൾ നൽകുന്നു"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} bluff ചെയ്തില്ല. {name2} ന് 6 കാർഡ് നല്കുന്നു"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr ""
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"പുതിയ ഗെയിം സൃഷ്ടിച്ചു! /join ഉപയോഗിച്ച് ഗെയിം ജോയിൻ ചെയ്തതിനു ശേഷം /start "
-"ഉപയോഗിച്ച് ഗെയിം തുടങ്ങു"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "ഈ ചാറ്റിൽ പ്രവർത്തിക്കുന്ന ഗെയിമുകളൊന്നുമില്ല."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "ലോബി അടച്ചു"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "ഒരു കളിയും ഇപ്പോൾ നടക്കുന്നില്ല /new പുതിയ കളി സൃഷ്ടിക്കുക"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "നിങ്ങൾ ഇതിനകം ഗെയിമിൽ ചേർന്നു. /start വച്ച് ഗെയിം സ്റ്റാർട്ട് ചെയ്യൂ"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "ഗെയിമിൽ ചേർന്നു."
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "നിങ്ങൾ ഈ ഗ്രൂപ്പിൽ ഗെയിം കളിക്കുന്നില്ല."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "ശരി. അടുത്ത കളിക്കാരൻ: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "ഗെയിം കണ്ടെത്താന് ആയില്ല."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "അവസാന ഗ്രൂപ്പിലേക്ക് മടങ്ങുന്നു"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "അവസാന ഗ്രൂപ്പിലേക്ക് മടങ്ങു!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"തിരഞ്ഞെടുത്ത ഗ്രൂപ്പ്: {group}n\n"
-" നിങ്ങൾ ശരിയായ ഗ്രൂപ്പിലേക്ക് മാറുന്നുവെന്ന് ഉറപ്പാക്കുക! b>"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "ഗെയിമിൽ നിന്ന് {name} നീക്കംചെയ്യുന്നു"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"ഈ ചാറ്റിൽ ഒരു ഗെയിമും പ്രവർത്തിക്കുന്നില്ല. /new പുതിയത് ഉപയോഗിച്ച് "
-"പുതിയൊരെണ്ണം തുടങ്ങൂ"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "ഗെയിം തുടങ്ങി കഴിഞ്ഞു"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr "ഗെയിം ആരംഭിക്കുന്നതിന് മുമ്പ് കുറഞ്ഞത് {minplayers} /join ചെയ്യണം"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"ആദ്യ കളിക്കാരൻ: {name}\n"
-"ആളുകളെ ഗെയിമിൽ ചേരുന്നത് തടയാൻ ഉപയോഗിക്കുക /close.\n"
-"/enable_translations ഉപയോഗിച്ച് ഒന്നിലധികം വിവർത്തനങ്ങൾ ഉപയോഗിക്കൂ"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "നിങ്ങൾ കളിക്കാൻ ആഗ്രഹിക്കുന്ന ഗ്രൂപ്പ് തിരഞ്ഞെടുക്കുക."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "ലോബി അടച്ചു. കൂടുതൽ കളിക്കാർക്ക് ഈ ഗെയിമിൽ ചേരാനാവില്ല."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "ലോബി തുറന്നു. പുതിയ കളിക്കാർക്ക് ഗെയിം കളിക്കാൻ /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr ""
-"ഭാഷ വിവർത്തനങ്ങൾ ഉപയോഗിക്കുന്നു. വിവർത്തനങ്ങൾ ഒഴിവാക്കാൻ /"
-"disable_translations ഉപയോഗിക്കുക"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"മറ്റ് ഭാഷ വിവർത്തനങ്ങൾ പ്രവർത്തനരഹിതമാക്കി. വിവർത്തനങ്ങൾ ഉപയോഗിക്കാൻ "
-"/enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "നിങ്ങൾ ഈ ചാറ്റിൽ ഗെയിം കളിക്കുന്നില്ല."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "{time} സെക്കൻഡ് വെയിറ്റ് ചെയ്യൂ"
-msgstr[1] "{time} സെക്കൻഡ് വെയിറ്റ് ചെയ്യൂ"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "കള്ളകളി കളിക്കാനുള്ള ശ്രമം {name}"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "അടുത്ത കളിക്കാരൻ : {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "{name} നു വേണ്ടി കാതിരിക്കാനുള്ള സമയം {time} ലേക്ക് റീസെറ്റ് ചെയ്തു"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "നിറം തിരഞ്ഞെടുക്കുക."
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} കാർഡ്)"
-msgstr[1] "{name} ({number} കാർഡുകൾ)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "നിങ്ങൾ കളിക്കുന്നില്ല"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"നിങ്ങൾ ഇപ്പോൾ കളിക്കുന്നില്ല. /new ഉപയോഗിച്ച് പുതിയ ഗെയിം തുടങ്ങൂ "
-"അല്ലെങ്കില് /join ഉപയോഗിച്ച് ഗെയിൽ കളിക്കൂ"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "ഗെയിം ഇതുവരെ തുടങ്ങിയില്ല"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "ഗെയിം തുടങ്ങുന്നതിന് /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "{number} കാർഡ് വലിക്കുന്നു"
-msgstr[1] "{number} കാർഡുകൾ വലിക്കുന്നു"
-
-#: results.py:209
-msgid "Pass"
-msgstr "പാസ്"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "ഞാന് bluff വിളിക്കുന്നു!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "നിലവിലെ കളിക്കാരൻ: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "അവസാന കാർഡ് (ഗെയിം നിലയ്ക്കായി ടാപ്പുചെയ്യുക): {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "കളിക്കാരൻ: {player_list}"
-msgstr[1] "കളിക്കാർ: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "നിങ്ങളുടെ ക്രമീകരണങ്ങൾ പ്രൈവറ്റ് ചാറ്റിൽ അപ്ഡേറ്റ് ചെയ്യുക."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "ഗെയിം വിവരങ്ങൾ ഡിലീറ്റ് ചെയ്യുന്നതിന്"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "ഗെയിം വിവരങ്ങൾ ലഭ്യമാക്കുന്നതിന്"
-
-#: settings.py:50
-msgid "Language"
-msgstr "ഭാഷ"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "സജീകരണങ്ങൾ"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "ഗെയിം വിവരങ്ങൾ enable ചെയ്തു!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "ഭാഷ തിരഞ്ഞെടുക്കൂ"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "ഗെയിം വിവരങ്ങൾ ഡിലീറ്റ് ചെയ്യുകയും disable ചെയ്യുകയും ചെയ്തു!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "ഭാഷ തിരഞ്ഞെടുക്കൂ!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"ഈ ബോട്ട് ഒരു സ്വതന്ത്ര സോഫ്റ്റ് വെയർ ആണ്, എജിപിഎൽ കീഴിൽ ലൈസൻസ് ഉള്ളതാണ്. കോഡ് ഇവിടെ "
-"ലഭ്യമാണ്: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "അപ്ഡേറ്റുകൾക്കായി ഗ്രൂപ്പ് ജോയിൻ ചെയ്യാം https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"ഗെയിം വിവരങ്ങൾ enable ചെയ്തിട്ടില്ല. /settings ബോടിന്റെ പ്രൈവറ്റ് ചാറ്റിൽ "
-"ഉപയോഗിച്ച് ഗെയിം വിവരങ്ങൾ പ്രവർത്തനക്ഷമമാക്കൂ."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} ഗെയിം കളിച്ചു"
-msgstr[1] "{number} ഗെയിം കളിച്ചു"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} ഒന്നാം സ്ഥാനം ({percent}%)"
-msgstr[1] "{number} ഒന്നാം സ്ഥാനങ്ങൾ ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} കാർഡ് കളിച്ചു"
-msgstr[1] "{number} കാർഡ് കളിച്ചു"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} ചുവപ്പ്"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} നീല"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} പച്ച"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} മഞ്ഞ"
diff --git a/locales/nb_NO/LC_MESSAGES/unobot.po b/locales/nb_NO/LC_MESSAGES/unobot.po
deleted file mode 100644
index f50681d..0000000
--- a/locales/nb_NO/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,621 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# This file is put in the public domain.
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 1.0\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-14 17:00+0000\n"
-"Last-Translator: Allan Nordhøy \n"
-"Language-Team: Norwegian Bokmål \n"
-"Language: nb_NO\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"Ventetid før denne spilleren hoppes over er redusert til {time} sekunder.\n"
-"Neste spiller: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} slapp opp for tid og har blitt fjernet fra spillet.\n"
-"Neste spiller: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} slapp opp for tid og har blitt fjernet fra spillet.\n"
-"Spillet er over."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} har vunnet."
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Spillet er over."
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Velg en farge"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Ingen flere kort i kortstokken."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Bløff sett. Gir 4 kort til {name}."
-
-#: actions.py:241
-#, fuzzy, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} bløffet ikke. Gir seks kort til {name2}."
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Send denne kommandoen i en gruppe du vil varsle når et nytt spill starter "
-"her."
-
-#: bot.py:113
-#, fuzzy
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-"OK. Du vil få en privat melding når neste spill starter i denne sludringen. "
-"Sørg for at jeg kan sende deg meldinger."
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Et nytt spill har blitt startet i {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Opprettet nytt spill. Ta del i spillet med «/join» og start spillet med "
-"«/start»."
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-#, fuzzy
-msgid "There is no running game in this chat."
-msgstr "Ingen kjørende spill i denne sludringen."
-
-#: bot.py:185 bot.py:336
-#, fuzzy
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"Spillet har ikke startet enda. Ta del i spillet med «/join» og start det ed "
-"«/start»."
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "Kun spillskaperen ({name}) og administratorer kan gjøre dette."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Lobbyen er lukket"
-
-#: bot.py:223 bot.py:326
-#, fuzzy
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Ingen spill kjører for øyeblikket. Start et nytt spill med «/new»."
-
-#: bot.py:231
-#, fuzzy
-msgid "You already joined the game. Start the game with /start"
-msgstr "Du har allerede tatt del i spillet. Start spillet med «/start»."
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr "Ikke nok kort igjen i kortstokken til at nye spillere kan ta del."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Tok del i spillet"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Du er ikke delaktig i noe spill i denne gruppen."
-
-#: bot.py:294 bot.py:397
-#, fuzzy, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "OK. Neste avspiller: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} forlot spillet før det startet."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "Fant ikke spilleren «{name}» i nåværende spill."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} ble kastet ut av {1}"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "Svar personen du vil kaste ut og skriv «/kick» igjen."
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Fant ikke spillet."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Tilbake til forrige gruppe"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Bytt til gruppen du valgte."
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Valgt gruppe: {group}\n"
-"Sørg for at du har byttet til riktig gruppe."
-
-#: bot.py:479
-#, fuzzy, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Ferner {name} fra spillet …"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "Ingen aktive spill i denne sludringen. Opprett et med «/new»."
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "Spillet har allerede startet"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Minst {minplayers} spillere må skrive «/join» for å ta del i spillet før du "
-"kan starte det."
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr "Gjør ditt valg."
-
-#: bot.py:533
-#, fuzzy, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Første spiller: {name}\n"
-"Bruk «/close» for å stoppe folk fra å ta del i spillet.\n"
-"Skru på multi-oversettelser med «/enable_translations»."
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Velg gruppen du vil spille i."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Lukket lobbyen. Ingen flere spillere kan ta del i spillet."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Åpnet lobbyen. Nye spillere kan skrive «/join» for å ta del i spillet."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-oversettelser påskrudd. Skru av med «/disable_translations»."
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "Multi-oversettelser avskrudd. Skru på igjen med «/enable_translations»."
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Du spiller ikke i noe spill i denne sludringen."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Vent {time} sekund"
-msgstr[1] "Vent {time} sekunder"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Nåværende spill: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "Spillmodus endret til {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "Forsøk på juks av {name}."
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Neste avspiller: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "Ventetid for {name} har blitt tilbakestilt til {time} sekunder."
-
-#: results.py:37
-msgid "Choose Player"
-msgstr "Velg avspiller"
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Velg farge"
-
-#: results.py:66
-#, fuzzy
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "Kort (trykk for spilltilstand):"
-msgstr[1] "Kort (trykk for spilltilstand):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} kort)"
-msgstr[1] "{name} ({number} kort)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Du spiller ikke."
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Spiller ikke akkurat nå. Bruk «/new» for å starte et spill, eller «/join» "
-"for å ta del i nåværende spill i denne gruppen."
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "Spillet har ikke startet enda"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Start spillet med «/start»"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 Klassisk modus"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "Klassisk 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Sanic-modus"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "Hurtighet først! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 Vilt modus"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "Inn i naturen~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr "🔫 7-0 -modus"
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr "Carioca-modus påslått 🔫"
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr "✍️ Tekst-modus"
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr "Tekst ✍️"
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Trekker {number} kort"
-msgstr[1] "Trekker {number} kort"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Pass"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Jeg ser bløffen din."
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Nåværende spiller: {name}"
-
-#: results.py:264
-#, fuzzy, python-brace-format
-msgid "Last card: {card}"
-msgstr "Siste kort: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Spiller: {player_list}"
-msgstr[1] "Spillere: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Rediger innstillingene dine i en privat sludring med botten."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Slett all statistikk"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Skru på statistikk"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Språk"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Innstillinger"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Statistikk påskrudd."
-
-#: settings.py:77
-#, fuzzy
-msgid "Select locale"
-msgstr "Velg språk"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Statistikk slettet og avskrudd."
-
-#: settings.py:100
-#, fuzzy
-msgid "Set locale!"
-msgstr "Sett språk."
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-"Følg disse stegene:\n"
-"\n"
-"1. Legg til denne botten i en gruppe\n"
-"2. I gruppen kan du starte et nytt spill med «/new», eller ta del i et "
-"allerede kjørende spill med «/join»\n"
-"3. Etter at minst to spillere har blitt med kan du starte spillet med "
-"«/start»\n"
-"4. Skriv @UnuRobot i sludringsboksen og trykk mellomrom, "
-"eller klikk på via @UnuRobot-teksten ved siden av meldinger. Du "
-"vil se kortene dine (noen utgrået), noen ekstra alternativer som tegning og "
-"et ? for å se gjeldende spilltilstand. Utgråede kort er dem du "
-"ikke kan spille for øyeblikket. Trykk på et alternativ for å utføre "
-"valgt handling.\n"
-"Spillere kan bli med i spillet når som helst. For å forlate et spill, bruker "
-"du «/leave». Hvis en spiller bruker mer enn 90 sekunder på å spille, kan du "
-"bruke «/skip» for å hoppe over den spilleren. Bruk «/notify_me» for å motta "
-"en privat melding når et nytt spill startes.\n"
-"\n"
-" Språk og andre innstillinger: /settings\n"
-"Andre kommandoer (kun for spillskaperen):\n"
-"«/close» - Lukk lobbyen\n"
-"«/open» - Åpne lobbyen\n"
-"«/kill» - Avslutt spillet\n"
-"«/kick» - Velg en spiller å sparke ved å svare vedkommende\n"
-"«/enable_translations» - Oversett relevante tekster til alle språk som "
-"snakkes i et spill\n"
-"«/disable_translations» - Bruk engelsk for disse tekstene\n"
-"\n"
-" Eksperimentelt: Spill i flere grupper samtidig. Trykk på "
-"Gjeldende spill: ...-knappen og velg gruppen du vil spille et "
-"kort i.\n"
-"Hvis du liker denne botten, kan du bli med i oppdateringskanalen og kjøpe et UNO-kortspill."
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-"Denne UNO-boten har fem spillmodus: Klassisk, Sanic, vilt, tekst og 7-0.\n"
-"\n"
-" 🎻 Klassisk modus bruker den konvensjonelle UNO-kortstokken og ingen hoppes "
-"over automatisk.\n"
-" 🚀 Sanic-modus bruker den konvensjonelle UNO-kortstokken og botten hopper "
-"automatisk over en spiller hvis vedkommende bruker for lang tid på sin tur.\n"
-" 🐉 Vilt modus bruker en kortstokk med flere spesialkort, mindre "
-"tallvariasjon, og ingen hoppes over automatisk.\n"
-" ✍️ Tekstmodus bruker den konvensjonelle UNO-kortstokken, men i stedet for "
-"klistremerker bruker den tekst.\n"
-" 🔫 7-0 -modus bruker den konvensjonelle UNO-kortstokken, men når en spiller "
-"legger ned en 7-er, kan vedkommende velge en spiller å bytte kort med. Når "
-"en spiller legger ned et 0-kort, vil alle kort byttes mellom de nåværende "
-"spillerne.\n"
-"\n"
-"For å endre spillmodus må spillskaperen skrive inn kallenavnet og et "
-"mellomrom, akkurat som når du spiller et kort, og alle "
-"spillmodusalternativer vises."
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Denne botten er fri programvare, lisensiert AGPLv3+. Kildekoden er "
-"tilgjengelig på\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-#, fuzzy
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"Bidragsytere:\n"
-"Korttrekkingsikon av Faithtoken\n"
-"Pass-ikon av Delapouite\n"
-"Originaler tilgjengelig på https://game-icons.net\n"
-"Ikoner redigert av ɳick"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Alle nyheter her: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Du har ikke skrudd på statistikk. Bruk «/settings» i et privat "
-"sludringsvindu med botten for å skru dette på."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} spill spilt"
-msgstr[1] "{number} spill spilt"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} førsteplass ({percent}%)"
-msgstr[1] "{number} førsteplasser ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} kort spilt"
-msgstr[1] "{number} kort spilt"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Rød"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Blå"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Grønn"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Gul"
diff --git a/locales/pt-BR.yml b/locales/pt-BR.yml
new file mode 100644
index 0000000..380a353
--- /dev/null
+++ b/locales/pt-BR.yml
@@ -0,0 +1,69 @@
+lang_name: Português
+lang_flag: 🇧🇷
+lang_changed: O idioma foi alterado para Português!
+back: Voltar
+theme: Tema
+info_theme: Você escolhe um tema para as cartas
+seven_zero: 7-0
+info_seven: Quando um 7 é jogado, o jogador pode trocar as cartas com outro jogador. Quando um 0 é jogado, todos passam as cartas para o próximo jogador.
+sbluff: Blefe
+info_bluff: Quando um jogador joga uma carta +4, o próximo pode desafiar. Se o jogador que jogou a carta +4 tiver outra carta para jogar, ele compra 4 cartas. Se não tiver, quem desafiou compra 6.
+one_win: Um vencedor
+info_one_win: Quando o primeiro jogador fica sem cartas, o jogo acaba e ele é o vencedor.
+one_card: Dizer UNO
+info_one_card: Quando um jogador tem apenas uma carta, ele deve dizer UNO. Se ele não disser, ele deve comprar 2 cartas.
+language: Idioma
+info_lang: Você pode alterar o idioma do bot.
+choose_lang: Escolha um idioma
+start_text: "Olá! Eu sou o UNO Bot, um bot para jogar UNO no Telegram!\n\nPara jogar me coloque em um grupo e mande /new para começar um novo jogo!\n\nou para configurar use os botões abaixo!"
+game_mode: Modo de Jogo
+status: Status
+game_mode_text: "Mostrando informações dos modos de jogo disponíveis!\n\n"
+settings: "Bem vindo ao menu de configurações!\n\nEscolha uma opçãoe abaixo para configurar o bot."
+theme_config: "Escolha um tema para as cartas:"
+minimalist: Minimalista
+classic: Clássico
+colorblind: Daltônico
+game_existis: Já existe um jogo em andamento!
+only_group: Esse comando só funciona em grupos!
+already_in_game: Você já está em outro jogo
+already_joined: Você já está no jogo!
+join: Entrar
+leave: Sair
+start_game: Começar Jogo
+game_started: Um novo jogo foi iniciado!
+no_game: Não há jogo em andamento!
+no_game_text: Nenhum jogo em andamento, mande /new para iniciar um novo jogo!
+lobby_closed: O lobby está fechado!
+lobby_opened: O lobby está aberto!
+joined_game: Você entrou no jogo!
+player_joined: "{} entrou no jogo!"
+no_joinned: Você não está no jogo!
+next: Próximo {}
+game_over: O jogo acabou!
+player_left: "{} saiu do jogo!"
+left_game: Você saiu do jogo!
+not_allowed: Você não tem permissão para fazer isso!
+game_started: O jogo já começou!
+info_text: 🃏 Informações do Jogo:\nJogador atual - {current_player}\nÚltima carta - {last_card}\n
+info_text2: "{player}: {cards} cartas, "
+pass: Passar
+buy: Comprar {} carta(s)
+bluff: Eu acho que você está blefando!
+cards_swapped: "{name1} trocou as cartas com {name2}"
+not_swapped: Devido ao numero de jogadores, não foi possível trocar as cartas!
+swapped: As cartas foram trocadas!
+bought: Você comprou {buy} cartas!
+bluffed: "{name} Você não pode blefar!\n{name} comprou {draw} cartas!"
+not_bluffed: "{name1} Você não blefou!\n{name2} comprou {draw} cartas!"
+colorchoose: "{name} escolha uma cor!"
+colorchoosed: Eu escolhi a cor {color}!
+playerchoose: "{name} escolha um jogador!"
+invalid_card: Jogada inválida!
+said_uno: "{name} gritou UNO!"
+say_uno: "{name} fale UNO ou compre 2 cartas!"
+not_said_uno: "{name} Você não gritou UNO!\n{name} comprou 2 cartas!"
+first: " em primeiro"
+won: "{name} ganhou o jogo{comp}!"
+continuing: continuando o jogo com {count} jogadores
+play: Jogar
\ No newline at end of file
diff --git a/locales/pt/LC_MESSAGES/unobot.po b/locales/pt/LC_MESSAGES/unobot.po
deleted file mode 100644
index a178133..0000000
--- a/locales/pt/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,622 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# This file is put in the public domain.
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 1.0\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2023-02-19 20:32+0000\n"
-"Last-Translator: ssantos \n"
-"Language-Team: Portuguese \n"
-"Language: pt\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.16-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"O tempo de espera para pular este jogador foi reduzido a {time} segundos.\n"
-"Próximo jogador: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} ficou sem tempo e foi removido da partida!\n"
-"Próximo jogador: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} ficou sem tempo e foi removido da partida!\n"
-"A partida acabou."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} venceu!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Fim de partida!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Por favor, escolha uma cor"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Não há mais cartas no deck."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Blefe revelado! Dando 4 cartas para {name}"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} não blefou! Dando 6 cartas para {name2}"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Envie este comando num grupo para ser notificado quando uma nova partida for "
-"iniciada."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-"Ok, você será notificado numa mensagem privada quando a próxima partida for "
-"iniciada neste chat. Certifique-se de que tenho permissão para lhe enviar "
-"mensagens."
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Uma nova partida foi iniciada no grupo {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr "Nova partida criada! Entre na partida com /join e inicie-a com /start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Não há uma partida sendo jogada nesta conversa."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"A partida ainda não iniciou. Junte-se a partida com /join e inicie-a com "
-"/start"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "Somente o criador do jogo ({name}) e administradores podem fazer isso."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "O lobby está fechado"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Nenhuma partida está a ser jogada. Crie uma partida com /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Já entrou na partida. Inicie-a com /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-"Não há cartas suficientes no baralho para que novos jogadores possam "
-"participar."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Entrou na partida"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Não joga nenhuma partida nesse grupo."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Ok. Próximo(a) jogador(a): {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} deixou a partida antes de ela começar."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "O jogador {name} não está na partida atual."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} foi removido por {1}"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-"Por favor, responda à pessoa que deseja remover e digite /kick novamente."
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Partida não encontrada."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Voltar ao último grupo"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Por favor, mude para o grupo selecionado!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grupo selecionado: {group}\n"
-"Tenha certeza de que mudou para o grupo certo!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Removendo {name} da partida"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"Não há nenhuma partida sendo jogada nesta conversa. Crie um nova partida com "
-"/new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "A partida já começou"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Pelo menos {minplayers} jogadores devem se juntar (/join) a partida antes de "
-"poder iniciá-la"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr "Faça sua escolha!"
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Primeiro jogador: {name}\n"
-"Use /close para impedir que mais pessoas entrem na partida.\n"
-"Ative as multi-traduções com /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Por favor, selecione o grupo em que deseja jogar."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-"O lobby está fechado. Não é permitida a entrada de novos jogadores nessa "
-"partida."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr ""
-"O lobby está aberto. Novos jogadores podem entrar na partida usando /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-traduções ativadas. Desative com /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Multi-traduções desativadas. Ative-as novamente com /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Não participa numa partida nesta conversa."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Por favor, aguarde {time} segundo"
-msgstr[1] "Por favor, aguarde {time} segundos"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Partida atual: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "Modo de jogo alterado para {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "Tentativa de trapaça por {name}"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Próximo jogador: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "O tempo de espera para {name} foi redefinido para {time} segundos"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr "Escolha o Jogador"
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Escolher Cor"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "Carta (toque para estado de jogo):"
-msgstr[1] "Cartas (toque para estado de jogo):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} carta)"
-msgstr[1] "{name} ({number} cartas)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Não está a jogar"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Não está a jogar. Use /new para criar uma partida ou /join para entrar na "
-"partida atual neste grupo"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "A partida ainda não começou"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Inicie a partida com /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 Modo clássico"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "Clássico 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Modo sanico"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "Temos que ir rápido! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 Modo selvagem"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "Para o selvagem~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr "🔫 modo 7-0"
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr "Modo carioca ativo 🔫"
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr "✍️ Modo texto"
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr "Texto ✍️"
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Sacando {number} carta"
-msgstr[1] "Sacando {number} cartas"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Passo"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Está a blefar!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Jogador atual: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Última carta: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Jogador(a): {player_list}"
-msgstr[1] "Jogadores(as): {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr ""
-"Por favor, ajuste as suas configurações numa conversa privada com o bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Apagar todas estatísticas"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Ativar estatísticas"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Idioma"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Configurações"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Estatísticas ativadas!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Definir linguagem"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Estatísticas apagadas e desativadas!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Linguagem selecionada!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-"Siga esses passos:\n"
-"\n"
-"1. Adicione este bot a um grupo\n"
-"2. No grupo, inicie uma nova partida com /new ou entre numa partida já em "
-"execução com /join\n"
-"3. Após a entrada de pelo menos dois jogadores, inicie a partida com /start\n"
-"4. Digite @UnuRobot na sua caixa de bate-papo e pressione "
-"espaço, ou clique no texto via @UnuRobot ao lado das "
-"mensagens. Verá as suas cartas (algumas esmaecidas), opções extras como "
-"desenhar e um ? para ver o estado atual do jogo. As cartas "
-"acinzentadas são aquelas que não pode jogar no momento. Toque "
-"numa opção para executar a ação selecionada.\n"
-"Os jogadores podem entrar na partida a qualquer momento. Para sair de uma "
-"partida, use /leave. Se um jogador demorar mais de 90 segundos para jogar, "
-"pode usar /skip para pular esse jogador. Use /notify_me para receber uma "
-"mensagem privada quando um novo jogo for iniciado.\n"
-"\n"
-"Idioma e outras configurações: /settings\n"
-"Outros comandos (somente criador do jogo):\n"
-"/close - Fechar lobby\n"
-"/open - Abrir lobby\n"
-"/kill - Termina o jogo\n"
-"/kick - Selecione um jogador para chutar por lhe responder\n"
-"/enable_translations - Traduz textos relevantes para todos os idiomas "
-"falados num jogo\n"
-"/disable_translations - Use inglês para esses textos\n"
-"\n"
-"Experimental: Jogue em vários grupos ao mesmo tempo. Pressione o "
-"botão Partida atual: ... e selecione o grupo no qual deseja "
-"jogar uma carta.\n"
-"Se gosta deste bot, entre no canal "
-"de atualização e compre um jogo de cartas UNO."
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-"Este bot do UNO tem cinco modos de jogo: Clássico, Sanico, Selvagem, Texto e "
-"7-0.\n"
-"\n"
-" 🎻 O modo Clássico utiliza o deck convencional UNO e não há pulo automático "
-"de jogadores.\n"
-" 🚀 O modo Sanico usa o deck UNO convencional e o bot pula automaticamente "
-"um jogador se ele demorar muito tempo para jogar a sua vez.\n"
-" 🐉 O modo Selvagem usa um baralho com mais cartas especiais, menos "
-"variedade de números e sem pulo automático.\n"
-" ✍️ O modo Texto usa o baralho convencional UNO, mas em vez de stickers, usa "
-"texto.\n"
-" 🔫 O modo 7-0 usa o baralho convencional UNO, mas quando um jogador joga um "
-"7, ele pode escolher um jogador para trocar as cartas. Quando um jogador "
-"joga um 0, todas as cartas serão trocadas entre os jogadores atuais.\n"
-"\n"
-"Para mudar o modo de jogo, o CRIADOR DO JOGO tem que digitar o username do "
-"bot e um espaço, assim como quando se joga uma carta e todas as opções de "
-"modo de jogo devem aparecer."
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Esse bot é um Software livre, grátis e licenciado com AGPL. O código está "
-"disponível aqui: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"Atribuições:\n"
-"Ícone de retirada de cartas feito por Faithtoken\n"
-"Ícone de passe feito pot por Delapouite\n"
-"Originais disponíveis em http://game-icons.net\n"
-"Ícones editados por ɳick"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Todas as novidades aqui: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Não ativou as estatísticas. Use /settings numa conversa privada com o bot "
-"para ativá-las."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} partida jogada"
-msgstr[1] "{number} partidas jogadas"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} vez em primeiro lugar ({percent}%)"
-msgstr[1] "{number} vezes em primeiro lugar ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} carta jogada"
-msgstr[1] "{number} cartas jogadas"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Vermelho"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Azul"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Verde"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Amarelo"
diff --git a/locales/pt_BR/LC_MESSAGES/unobot.po b/locales/pt_BR/LC_MESSAGES/unobot.po
deleted file mode 100644
index b642f3a..0000000
--- a/locales/pt_BR/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,634 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 06:21+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Portuguese (Brazil) \n"
-"Language: pt_BR\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"O tempo de espera para pular este jogador foi reduzido a {time} segundos.\n"
-"Próximo jogador: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} ficou sem tempo e foi removido da partida!\n"
-"Próximo jogador: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} ficou sem tempo e foi removido da partida!\n"
-"A partida acabou."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} venceu!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Fim de partida!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Por favor, escolha uma cor"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Não há mais cartas no deck."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Blefe revelado! Dando 4 cartas para {name}"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} não blefou! Dando 6 cartas para {name2}"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Envie este comando em um grupo para ser notificado quando uma nova partida "
-"for iniciada."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-"Ok, você será notificado em uma mensagem privada quando a próxima partida "
-"for iniciada neste chat. Certifique-se de que tenho permissão para lhe "
-"enviar mensagens."
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Uma nova partida foi iniciada no grupo {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr "Nova partida criada! Entre na partida com /join e inicie-a com /start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Não há uma partida sendo jogada nesta conversa."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"A partida ainda não iniciou. Junte-se a partida com /join e inicie-a com /"
-"start"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "Somente o criador do jogo ({name}) e administradores podem fazer isso."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "O lobby está fechado"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Nenhuma partida está sendo jogada. Crie uma nova partida com /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Você já entrou na partida. Inicie-a com /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-"Não há cartas suficientes no baralho para que novos jogadores possam "
-"participar."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Entrou na partida"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Você não está jogando nenhuma partida nesse grupo."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Ok. Próximo(a) jogador(a): {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} deixou a partida antes de ela começar."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "O jogador {name} não está na partida atual."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} foi removido por {1}"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-"Por favor, responda à pessoa que você deseja remover e digite /kick "
-"novamente."
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Partida não encontrada."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Voltar ao último grupo"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Por favor, mude para o grupo selecionado!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grupo selecionado: {group}\n"
-"Tenha certeza de que mudou para o grupo certo!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Removendo {name} da partida"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-"Não há nenhuma partida sendo jogada nesta conversa. Crie um nova partida "
-"com /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "A partida já começou"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Pelo menos {minplayers} jogadores devem se juntar (/join) a partida antes de "
-"poder iniciá-la"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr "Faça sua escolha!"
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Primeiro jogador: {name}\n"
-"Use /close para impedir que mais pessoas entrem na partida.\n"
-"Ative as multi-traduções com /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Por favor, selecione o grupo em que deseja jogar."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-"O lobby está fechado. Não é permitida a entrada de novos jogadores nessa "
-"partida."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr ""
-"O lobby está aberto. Novos jogadores podem entrar na partida usando /join."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Multi-traduções ativadas. Desative com /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Multi-traduções desativadas. Ative-as novamente com /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Você não está participando de uma partida nesta conversa."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Por favor, aguarde {time} segundo"
-msgstr[1] "Por favor, aguarde {time} segundos"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Partida atual: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "Modo de jogo alterado para {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "Tentativa de trapaça por {name}"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Próximo jogador: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "O tempo de espera para {name} foi redefinido para {time} segundos"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr "Escolha o Jogador"
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Escolher Cor"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "Carta (toque para estado de jogo):"
-msgstr[1] "Cartas (toque para estado de jogo):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} carta)"
-msgstr[1] "{name} ({number} cartas)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Você não está jogando"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Você não está jogando. Use /new para criar uma partida ou /join para entrar "
-"na partida atual neste grupo"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "A partida ainda não começou"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Inicie a partida com /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 Modo clássico"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "Clássico 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Modo sanico"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "Temos que ir rápido! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 Modo selvagem"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "Para o selvagem~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr "🔫 modo 7-0"
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr "Modo carioca ativo 🔫"
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr "✍️ Modo texto"
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr "Texto ✍️"
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Sacando {number} carta"
-msgstr[1] "Sacando {number} cartas"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Passo"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Você está blefando!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Jogador atual: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Última carta: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Jogador(a): {player_list}"
-msgstr[1] "Jogadores(as): {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr ""
-"Por favor, ajuste suas configurações em uma conversa privada com o bot."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Apagar todas estatísticas"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Habilitar estatísticas"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Idioma"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Configurações"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Estatísticas habilitadas!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Definir linguagem"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Estatísticas apagadas e desabilitadas!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Linguagem selecionada!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-"Siga esses passos:\n"
-"\n"
-"1. Adicione este bot a um grupo\n"
-"2. No grupo, inicie uma nova partida com /new ou entre em uma partida já em "
-"execução com /join\n"
-"3. Após a entrada de pelo menos dois jogadores, inicie a partida com /start\n"
-"4. Digite @UnuRobot em sua caixa de bate-papo e pressione "
-"espaço, ou clique no texto via @UnuRobot ao lado das "
-"mensagens. Você verá suas cartas (algumas esmaecidas), opções extras como "
-"desenhar e um ? para ver o estado atual do jogo. As cartas "
-"acinzentadas são aquelas que você não pode jogar no momento. "
-"Toque em uma opção para executar a ação selecionada.\n"
-"Os jogadores podem entrar na partida a qualquer momento. Para sair de uma "
-"partida, use /leave. Se um jogador demorar mais de 90 segundos para jogar, "
-"você pode usar /skip para pular esse jogador. Use /notify_me para receber "
-"uma mensagem privada quando um novo jogo for iniciado.\n"
-"\n"
-"Idioma e outras configurações: /settings\n"
-"Outros comandos (somente criador do jogo):\n"
-"/close - Fechar lobby\n"
-"/open - Abrir lobby\n"
-"/kill - Termina o jogo\n"
-"/kick - Selecione um jogador para chutar respondendo a ele\n"
-"/enable_translations - Traduz textos relevantes para todos os idiomas "
-"falados em um jogo\n"
-"/disable_translations - Use inglês para esses textos\n"
-"\n"
-"Experimental: Jogue em vários grupos ao mesmo tempo. Pressione o "
-"botão Partida atual: ... e selecione o grupo no qual deseja "
-"jogar uma carta.\n"
-"Se você gosta deste bot, entre no canal de atualização e compre um jogo de cartas UNO."
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-"Este bot do UNO tem cinco modos de jogo: Clássico, Sanico, Selvagem, Texto e "
-"7-0.\n"
-"\n"
-" 🎻 O modo Clássico utiliza o deck convencional UNO e não há pulo automático "
-"de jogadores.\n"
-" 🚀 O modo Sanico usa o deck UNO convencional e o bot pula automaticamente "
-"um jogador se ele demorar muito tempo para jogar sua vez.\n"
-" 🐉 O modo Selvagem usa um baralho com mais cartas especiais, menos "
-"variedade de números e sem pulo automático.\n"
-" ✍️ O modo Texto usa o baralho convencional UNO, mas em vez de stickers, usa "
-"texto.\n"
-" 🔫 O modo 7-0 usa o baralho convencional UNO, mas quando um jogador joga um "
-"7, ele pode escolher um jogador para trocar as cartas. Quando um jogador "
-"joga um 0, todas as cartas serão trocadas entre os jogadores atuais.\n"
-"\n"
-"Para mudar o modo de jogo, o CRIADOR DO JOGO tem que digitar o username do "
-"bot e um espaço, assim como quando se joga uma carta, e todas as opções de "
-"modo de jogo devem aparecer."
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Esse bot é um Software livre, grátis e licenciado com AGPL. O código está "
-"disponível aqui: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"Atribuições:\n"
-"Ícone de retirada de cartas feito por Faithtoken\n"
-"Ícone de passe feito pot por Delapouite"
-"a>\n"
-"Originais disponíveis em http://game-icons.net\n"
-"Ícones editados por ɳick"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Todas as novidades aqui: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Você não habilitou as estatísticas. Use /settings em uma conversa privada "
-"com o bot para ativá-las."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} partida jogada"
-msgstr[1] "{number} partidas jogadas"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} vez em primeiro lugar ({percent}%)"
-msgstr[1] "{number} vezes em primeiro lugar ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} carta jogada"
-msgstr[1] "{number} cartas jogadas"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Vermelho"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Azul"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Verde"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Amarelo"
diff --git a/locales/ru_RU/LC_MESSAGES/unobot.po b/locales/ru_RU/LC_MESSAGES/unobot.po
deleted file mode 100644
index 01414bc..0000000
--- a/locales/ru_RU/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,557 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-# Jannes Höke , 2016.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Russian "
-"\n"
-"Language: ru_RU\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: utf-8\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} победил!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Игра окончена!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Пожалуйста, выберите цвет"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "В колоде больше нет карт."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Это блеф! {name} получает 4 карты"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} не блефовал! {name2} получает 6 карт"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Отправьте эту команду в группе, чтобы получать уведомления о новых партиях."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "В {title} началась новая игра"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Создана новая игра! Присоединитесь к ней командой /join и начните, написав /"
-"start"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Нет ни одной игры в данном чате."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Лобби закрыто"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Нет активных партий в данный момент. Создайте новую, написав /new"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Вы уже присоединились к этой игре. Начните ее с помощью /start"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Присоединился к игре"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Вы не играете в данной группе."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Ок. Следующий игрок: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Игры не найдены."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Вернуться к последней группе"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Пожалуйста, переключитесь на выбранную группу!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Выбранная группа: {group}\n"
-"Убедитесь, что Вы переключились на нее!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "Удаляю {name} из игры"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "Нет ни одной игры в данном чате. Создайте новую командой /new"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "Игра уже началась"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"Первый игрок: {name}\n"
-"Напишите /close, чтобы запретить присоединяться к этой игре.\n"
-"Включите перевод текстов командой /enable_translations"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Пожалуйста, выберите группу, в которой хотите играть."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Лобби закрыто. К данной игре нельзя присоединиться."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Лобби открыто. Теперь к игре можно присоединиться."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Перевод активирован. Выключите с помощью /disable_translations"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-"Перевод отключен. Вы можете включить его с помощью /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Вы не играете ни в одну из партий в данном чате."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Пожалуйста, подождите {time} секунды"
-msgstr[1] "Пожалуйста, подождите {time} секунд"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Текущая игра: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} попытался сжульничать"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Следующий игрок: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Выберите цвет"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} карты)"
-msgstr[1] "{name} ({number} карт)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Вы не играете"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"В данный момент Вы не играете. Используйте /new, чтобы начать новую, или /"
-"join, чтобы присоединиться к текущей"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "Игра еще не началась"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Начните новую игру с помощью /start"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Забирает {number} карты"
-msgstr[1] "Забирает {number} карты"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Пас"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Я бросаю тебе вызов!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Текущий игрок: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Последняя карта: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Игрок: {player_list}"
-msgstr[1] "Игроки: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Пожалуйста, напишите боту для изменения своих настроек."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Удалить всю статистику"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "Включить статистику"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Язык"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Настройки"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "Статистика включена!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Выберите язык"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "Статистика удалена и отключена!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Язык установлен!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Этот бот является программой с открытым исходным кодом и выпущен под "
-"лицензией AGPL. Весь код доступен по адресу:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Все новости здесь: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"Вы не включали статистику. Чтобы ее активировать, напишите /settings в "
-"приватном чате с ботом."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} игры сыграно"
-msgstr[1] "{number} игр сыграно"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} первое место ({percent}%)"
-msgstr[1] "{number} первых мест ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} карты сыграно"
-msgstr[1] "{number} карты сыграно"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Красный"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Синий"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Зеленый"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Желтый"
diff --git a/locales/tr_TR/LC_MESSAGES/unobot.po b/locales/tr_TR/LC_MESSAGES/unobot.po
deleted file mode 100644
index 9088ba3..0000000
--- a/locales/tr_TR/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,558 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# This file is put in the public domain.
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 1.0\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Turkish "
-"\n"
-"Language: tr_TR\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"Bu oyuncuyu atlamak için gereken süre {time} saniyeye düşürüldü.\n"
-"Sıradaki oyuncu: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1}’ın süresi doldu ve oyundan çıkarıldı!\n"
-"Sıradaki oyuncu: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name}’ın süresi doldu ve oyundan çıkarıldı!\n"
-"Oyun sona erdi."
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} kazandı!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "Oyun Bitti!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "Lütfen bir renk seçin"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "Destede yeterli kart kalmadı."
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Blöf yapıyor! {name}’a 4 kart ver"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} blöf yapmıyordu! {name2}’a 6 kart ver"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-"Bu komutu, bir grupta yeni bir oyuna başladığında bildirim almak için o "
-"gruba gönderin."
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "Şu grupta yeni bir oyun başladı: {title}"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-"Yeni bir oyun oluşturuldu! Oyuna katılmak için /join yaz ve oyunu başlatmak "
-"için /start komutunu gönder"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "Bu sohbette başlamış bir oyun yok."
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-"Oyun henüz başlamadı. Oyuna katılmak için /join yazve oyunu başlatmak için /"
-"start komutunu gönder"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "Yalnızca oyunun kurucusu ({name}) ve yönetici bunu yapabilir."
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Girişler kapatıldı"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "Şu anda oyun mevcut değil. /new ile yeni bir oyun oluşturabilirsin"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "Zaten oyuna katıldın. Oyunu başlatmak için /start komutunu kullan"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr "Yeni oyuncuların katılması için destede yeterli kart kalmadı."
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "Oyuna katıldın"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "Bu gruptaki bir oyunda yoksunuz."
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "Pekala. Sıradaki Oyuncu: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name}, başlamadan oyundan ayrıldı."
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "Oyuncu {name} mevcut oyunda bulunamadı."
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0}, {1} tarafından atıldı"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "Lütfen atmak istediğiniz kişiyi alıntılayarak/kick komutunu yazın"
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Oyun bulunamadı."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "Son gruba geri dön"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "Lütfen seçtiğiniz gruba geçin!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"Grup seçildi: {group}\n"
-" Doğru gruba geçtiğinizden emin olun!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "{name} oyundan silindi"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "Bu sohbette şu an oyun yok. /new ile yeni bir oyun oluşturabilirsin"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "Oyun zaten başladı"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-"Oyun başlatmak için en az {minplayers} kişi oyuna /join yazarak katılmalı"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"İlk oyuncu: {name}\n"
-"/close yazarak oyuna daha fazla kişinin katılmasını kapatabilirsin.\n"
-"Çoklu dili etkinleştirmek için /enable_translations yaz"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "Lütfen oynamak istediğiniz grubu seçin."
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Girişler kapatıldı. Oyuna daha fazla oyuncu katılamaz."
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "Girişler açıldı. Yeni oyuncular /join yazarak oyuna katılabilir."
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "Çoklu dil etkinleştirildi. Kapatmak için /disable_translations yaz"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "Çoklu dil kapatıldı. Açmak için /enable_translations yaz"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "Bu sohbetteki bir oyunda oynamıyorsun."
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "Lütfen {time} saniye bekleyin"
-msgstr[1] "Lütfen {time} saniye bekleyin"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "Mevcut oyun: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "Oyun modu değiştirildi: {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name}, hile yapmaya çalıştı"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "Sıradaki oyuncu: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "{name} için bekleme süresi {time} saniye olarak sıfırlandı"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "Renk Seç"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "Kart (oyun durumu için dokunun):"
-msgstr[1] "Kartlar (oyun durumu için dokunun):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name}’ın ({number} kartı kaldı.)"
-msgstr[1] "{name}’ın ({number} kartı kaldı.)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "Oyunda değilsin"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"Şu anda bir oyunda yoksun. Yeni bir oyun kurmak için /new, mevcut oyuna "
-"katılmak için /join yaz"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "Oyun henüz başlamadı"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "Oyunu /start ile başlat"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 Klasik mod"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "Klasik 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Fişek mod"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "Daha hızlı ol! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 Vahşi mod"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "Vahşi doğuya ~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "{number} kart çekildi"
-msgstr[1] "{number} kart çekildi"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Pas"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "Blöf yapıyorsun!!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "Şu anki oyuncu: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "Son kart: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "Oyuncu: {player_list}"
-msgstr[1] "Oyuncular: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "Lütfen ayarlarınızı botun özel sohbetinde düzenleyin."
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "Tüm istatistikleri sil"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "İstatistikleri Aç"
-
-#: settings.py:50
-msgid "Language"
-msgstr "Dil"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "Ayarlar"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "İstatistikler açıldı!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "Dili seçiniz"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "İstatistikler devredışı bırakıldı ve silindi!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Dil seçildi!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"Bu bot Açık Kaynak ve AGPL lisanslıdır. Kodları burada: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"Teşekkürler:\n"
-"Çekme simgesi Faithtoken\n"
-"Pas simgesi Delapouite\n"
-"Orijinalleri http://game-icons.net\n"
-"ɳick taradından düzenlendi.\n"
-"Türkçe çevirisi: @holytotem tarafından yapılmıştır."
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "Tüm yenilikler burada: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"İstatistikleri etkinleştirmediniz. Bota özel sohbetten/settings komutunu "
-"gönderve istatistik ayarını aç."
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "{number} Oyun oynandı"
-msgstr[1] "{number} Oyun oynandı"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "{number} Defa birincilik ({percent}%)"
-msgstr[1] "{number} Defa birincilik ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "{number} Kart oynandı"
-msgstr[1] "{number} Kart oynandı"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} Kırmızı"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} Mavi"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} Yeşil"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} Sarı"
diff --git a/locales/unobot.pot b/locales/unobot.pot
deleted file mode 100644
index 6598b90..0000000
--- a/locales/unobot.pot
+++ /dev/null
@@ -1,527 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# This file is put in the public domain.
-# FIRST AUTHOR , YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 1.0\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr ""
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr ""
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr ""
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr ""
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr ""
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr ""
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr ""
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr ""
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr ""
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr ""
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr ""
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr ""
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr ""
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr ""
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr ""
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr ""
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr ""
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr ""
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr ""
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr ""
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr ""
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr ""
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr ""
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr ""
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr ""
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr ""
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr ""
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] ""
-msgstr[1] ""
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr ""
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr ""
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr ""
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:91
-msgid "You are not playing"
-msgstr ""
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr ""
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr ""
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] ""
-msgstr[1] ""
-
-#: results.py:209
-msgid "Pass"
-msgstr ""
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr ""
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr ""
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr ""
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] ""
-msgstr[1] ""
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr ""
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr ""
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr ""
-
-#: settings.py:50
-msgid "Language"
-msgstr ""
-
-#: settings.py:53
-msgid "Settings"
-msgstr ""
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr ""
-
-#: settings.py:77
-msgid "Select locale"
-msgstr ""
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr ""
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr ""
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr ""
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] ""
-msgstr[1] ""
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] ""
-msgstr[1] ""
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] ""
-msgstr[1] ""
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr ""
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr ""
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr ""
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr ""
diff --git a/locales/zh_CN/LC_MESSAGES/unobot.po b/locales/zh_CN/LC_MESSAGES/unobot.po
deleted file mode 100644
index 41ade41..0000000
--- a/locales/zh_CN/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,551 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-11 01:28+0000\n"
-"Last-Translator: Anonymous \n"
-"Language-Team: Chinese (Simplified) \n"
-"Language: zh_CN\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"该玩家的等待时间已降至 {time} 秒。\n"
-"轮到: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} 已经被连续跳过了 4 次。\n"
-"轮到: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} 已经被连续跳过了 4 次。\n"
-"游戏结束。"
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} 赢了!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "游戏结束!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "请选择颜色"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "牌堆中已经没有更多的牌了。"
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "质疑成功!给 {name} 4 张牌"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "质疑 {name1} 失败!给 {name2} 6 张牌"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr "在群组中发送该指令,以在新游戏开始时通知您。"
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "新游戏已在 {title} 开始"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr "创建新游戏成功!请使用 /join 加入游戏,然后使用 /start 开始游戏"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "这个群中并没有正在运行的游戏。"
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr "游戏尚未开始。请使用 /join 加入游戏,然后使用 /start 开始游戏"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "只有游戏创建者 ({name}) 和管理员才能执行该命令。"
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "已禁止中途加入游戏"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "这个群并没有运行中的游戏。请使用 /new 创建新游戏"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "您已经加入了游戏。请使用 /start 开始游戏"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr "牌堆中已经没有足够给新加入玩家的牌了。"
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "游戏加入成功"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "您在这个群中并没有参加游戏。"
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "好的,轮到: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} 在游戏开始前就离开游戏了。"
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "未在当前游戏中找到{name}玩家。"
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} 已被 {1} 踢出游戏"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "请回复要踢出的人,并再次输入 /kick 。"
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "游戏未找到。"
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "返回上一个群"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "请切换到您选择的群!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"选择群: {group}\n"
-"请确保您已切换到正确的群!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "已成功将 {name} 移出游戏"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "这个群并没有运行中的游戏。请使用 /new 创建新游戏"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "游戏已经开始"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr "至少需要 {minplayers} 个人 /join 加入游戏,才能开始游戏"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"第一个出牌的玩家: {name}\n"
-"可使用 /close 阻止其他人中途加入游戏。\n"
-"使用 /enable_translations 启动游戏翻译功能"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "请选择您要参加游戏的群。"
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "游戏已设置成不允许中途加入,玩家将不允许加入游戏。"
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "游戏已设置成允许中途加入,新玩家现在可以使用 /join 加入游戏。"
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "游戏翻译已启用,使用 /disable_translations 可以停用该功能"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "游戏翻译已停用,使用 /enable_translations 可以启用该功能"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "您并不在游戏中。"
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "请等待 {time} 秒"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "当前游戏: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "游戏模式已切换为 {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} 试图作弊"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "轮到: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "{name} 的等待时间已经重置为 {time} 秒"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "选择颜色"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "手牌 (点击查看游戏状况):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} 张牌)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "您并不在游戏中"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr ""
-"您并不在游戏中。请使用 /new 创建一个新游戏,或者使用 /join 加入一个现有的游戏"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "游戏还没有开始"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "请先使用 /start 开始游戏"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 经典模式"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "经典 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Sanic 模式"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "搞快点! 🚀\""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 野性模式"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "进入旷野~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "抽取 {number} 张牌"
-
-#: results.py:209
-msgid "Pass"
-msgstr "过"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "我要质疑你!"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "轮到: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "上一张牌: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "玩家: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "请私聊我修改您的设置。"
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "删除所有统计数据"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "启用数据统计"
-
-#: settings.py:50
-msgid "Language"
-msgstr "语言"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "设置"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "数据统计已启用!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "请选择语言"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "统计数据已经被删除并已停用!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "语言设置成功!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"本机器人是一个在 AGPL 协议下发行的自由软件。源代码可以在这里取得:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"来源:\n"
-"抽牌图标来自 Faithtoken\n"
-"a>。\n"
-"跳过图标來自 Delapouite。\n"
-"原始图标可在 http://game-icons.net 获取。\n"
-"图标由 ɳick 编辑"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "查看机器人的所有更新: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr "您并没有启用数据统计。请私聊我发送 /settings 进行设置。"
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "玩了 {number} 盘"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "赢了 {number} 盘 ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "总共出过 {number} 张牌"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} 红色"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} 蓝色"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} 绿色"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} 黄色"
diff --git a/locales/zh_HK/LC_MESSAGES/unobot.po b/locales/zh_HK/LC_MESSAGES/unobot.po
deleted file mode 100644
index cdd2704..0000000
--- a/locales/zh_HK/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,540 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Chinese (Traditional, Hong Kong) \n"
-"Language: zh_HK\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} 贏咗!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "遊戲結束!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "請揀一隻顏色"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "檯上面冇哂牌"
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "Call咗bluff, {name} draw 4張牌"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1}冇bluff, {name2} draw 6 張牌"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr ""
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr ""
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr "已經開始咗新一盤! 用/join加入同埋/start去開始"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "呢個對話入面冇嘢玩緊喎。"
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr ""
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr ""
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "Lobby已經閂咗"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "宜家冇遊戲運行, 用 /new開展新一盤"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "你已經加入咗啦, 用 /start開始呢一盤"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr ""
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "加入咗"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "你唔喺呢個group玩緊"
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "OK 下一個: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr ""
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr ""
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr ""
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr ""
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "Game not found."
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "去返前一個group"
-
-#: bot.py:437
-#, fuzzy
-msgid "Please switch to the group you selected!"
-msgstr "請轉去你揀咗果個group!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"揀咗呢個group: {group}\n"
-"記住轉過去正確嘅group"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "{name} 已經比人踢咗"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "呢個對話入面冇遊戲運行緊, 用/new開始新一盤"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "呢一盤已經開始咗"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr ""
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"第一個玩家: {name}\n"
-"唔想其他人加入遊戲嘅話可以選擇 /close\n"
-"用 /enable_translations 啓用翻譯功能"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "你想喺邊個group玩?"
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "Lobby已經閂咗, 其他玩家已經冇得加入"
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "開咗個lobby, 宜家可以 /join 呢一盤"
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "啓用咗其他語言, 可以用 /disable_translations 停用"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "已經停用咗其他語言, 想重新嘅話可以揀 /enable_translations"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "你冇喺呢個對話入面玩。"
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "請等{time}秒"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr ""
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr ""
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} chok cheat"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "下一個: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr ""
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "揀顏色"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] ""
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} ({number} 張牌)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "你唔係玩緊喎"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr "你唔係玩緊喎, 用 /new 開始新一盤或者 /join 加入宜家嘅遊戲"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "呢一盤仲未開始喎"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "用/start開始呢一盤"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr ""
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr ""
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr ""
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr ""
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr ""
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr ""
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "Draw緊{number}張牌"
-
-#: results.py:209
-msgid "Pass"
-msgstr "Pass"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "我call你bluff"
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "宜家嘅玩家: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "前一張牌: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "玩家: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "請pm個bot修改你嘅設定"
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "刪除所有數據"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "啓用數據記錄"
-
-#: settings.py:50
-msgid "Language"
-msgstr "語言"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "設定"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "已經啓用咗數據記錄!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "請揀個區域"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "已經熄咗同埋delete咗數據記錄!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "Set咗個區域!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"呢個bot係一個免費嘅Software, 根據AGPL授權 \n"
-"Code可以係呢度搵到\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "所有update都喺晒度: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr "你冇啓用數據記錄, pm個bot去啓用。"
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "玩咗{number}盤"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "贏咗{number}次 ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "已經玩咗{number}張牌"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} 紅色"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} 藍色"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} 綠色"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} 黃色"
diff --git a/locales/zh_TW/LC_MESSAGES/unobot.po b/locales/zh_TW/LC_MESSAGES/unobot.po
deleted file mode 100644
index aa87da2..0000000
--- a/locales/zh_TW/LC_MESSAGES/unobot.po
+++ /dev/null
@@ -1,552 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-msgid ""
-msgstr ""
-"Project-Id-Version: uno_bot 0.1\n"
-"Report-Msgid-Bugs-To: uno@jhoeke.de\n"
-"POT-Creation-Date: 2022-11-13 01:49-0300\n"
-"PO-Revision-Date: 2022-11-12 05:22+0000\n"
-"Last-Translator: Alisson Lauffer \n"
-"Language-Team: Chinese (Traditional) \n"
-"Language: zh_TW\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.15-dev\n"
-
-#: actions.py:43
-#, python-brace-format
-msgid ""
-"Waiting time to skip this player has been reduced to {time} seconds.\n"
-"Next player: {name}"
-msgstr ""
-"跳過此玩家的等待時間已縮短至 {time} 秒。\n"
-"輪到: {name}"
-
-#: actions.py:61
-#, python-brace-format
-msgid ""
-"{name1} ran out of time and has been removed from the game!\n"
-"Next player: {name2}"
-msgstr ""
-"{name1} 已逾時,且已將其從此場遊戲移除!\n"
-"輪到: {name2}"
-
-#: actions.py:78
-#, python-brace-format
-msgid ""
-"{name} ran out of time and has been removed from the game!\n"
-"The game ended."
-msgstr ""
-"{name} 已逾時,且已將其從此場遊戲移除!\n"
-"遊戲結束。"
-
-#: actions.py:125 actions.py:172
-#, python-brace-format
-msgid "{name} won!"
-msgstr "{name} 贏了!"
-
-#: actions.py:139 actions.py:186 bot.py:179 bot.py:288 bot.py:373 bot.py:473
-msgid "Game ended!"
-msgstr "遊戲結束!"
-
-#: actions.py:164
-msgid "Please choose a color"
-msgstr "請選擇顏色"
-
-#: actions.py:206 actions.py:233 actions.py:249
-msgid "There are no more cards in the deck."
-msgstr "卡堆中已經沒牌了。"
-
-#: actions.py:224
-#, python-brace-format
-msgid "Bluff called! Giving 4 cards to {name}"
-msgstr "已確定為虛張聲勢! 給 {name} 4 張牌"
-
-#: actions.py:241
-#, python-brace-format
-msgid "{name1} didn't bluff! Giving 6 cards to {name2}"
-msgstr "{name1} 並未虛張聲勢! 給 {name2} 6 張牌"
-
-#: bot.py:99
-msgid ""
-"Send this command in a group to be notified when a new game is started there."
-msgstr "請將這個指令傳到群組中,以在新遊戲開始時通知您。"
-
-#: bot.py:113
-msgid ""
-"Okay, you will be notified in a private message when the next game is "
-"started in this chat. Make sure that I'm allowed to send you messages."
-msgstr ""
-
-#: bot.py:134
-#, python-brace-format
-msgid "A new game has been started in {title}"
-msgstr "新遊戲已經在 {title} 開始!"
-
-#: bot.py:148
-msgid ""
-"Created a new game! Join the game with /join and start the game with /start"
-msgstr "已建立新遊戲! 使用 /join 加入遊戲,並使用 /start 開始遊戲"
-
-#: bot.py:168 bot.py:595 bot.py:630 bot.py:665 bot.py:700
-msgid "There is no running game in this chat."
-msgstr "此聊天室尚無進行中的遊戲。"
-
-#: bot.py:185 bot.py:336
-msgid ""
-"The game is not started yet. Join the game with /join and start the game "
-"with /start"
-msgstr "遊戲尚未開始。請使用 /join 加入遊戲,並使用 /start 開始遊戲"
-
-#: bot.py:194 bot.py:406 bot.py:611 bot.py:646 bot.py:681 bot.py:720
-#, python-brace-format
-msgid "Only the game creator ({name}) and admin can do that."
-msgstr "只有遊戲建立者 ({name}) 及管理員才能執行。"
-
-#: bot.py:216
-msgid "The lobby is closed"
-msgstr "遊戲大廳已關閉"
-
-#: bot.py:223 bot.py:326
-msgid "No game is running at the moment. Create a new game with /new"
-msgstr "目前沒有進行中的遊戲。請使用 /new 建立新遊戲"
-
-#: bot.py:231
-msgid "You already joined the game. Start the game with /start"
-msgstr "您已加入遊戲。請使用 /start 開始遊戲"
-
-#: bot.py:240
-msgid "There are not enough cards left in the deck for new players to join."
-msgstr "卡堆中已經沒有足夠給新進玩家的牌了。"
-
-#: bot.py:250
-msgid "Joined the game"
-msgstr "已加入遊戲"
-
-#: bot.py:267 bot.py:282
-msgid "You are not playing in a game in this group."
-msgstr "您不在此群組的遊戲中。"
-
-#: bot.py:294 bot.py:397
-#, python-brace-format
-msgid "Okay. Next Player: {name}"
-msgstr "好的。下一位玩家: {name}"
-
-#: bot.py:303
-#, python-brace-format
-msgid "{name} left the game before it started."
-msgstr "{name} 在遊戲開始前就離開遊戲了。"
-
-#: bot.py:355
-#, python-brace-format
-msgid "Player {name} is not found in the current game."
-msgstr "未在目前遊戲找到 {name} 玩家。"
-
-#: bot.py:368 bot.py:379
-#, python-brace-format
-msgid "{0} was kicked by {1}"
-msgstr "{0} 被 {1} 踢出"
-
-#: bot.py:389
-msgid "Please reply to the person you want to kick and type /kick again."
-msgstr "請回覆要踢出的人,並再次輸入 /kick 。"
-
-#: bot.py:426
-msgid "Game not found."
-msgstr "找不到遊戲。"
-
-#: bot.py:433
-msgid "Back to last group"
-msgstr "回到上一個群組"
-
-#: bot.py:437
-msgid "Please switch to the group you selected!"
-msgstr "請切換到您選取的群組!"
-
-#: bot.py:445
-#, python-brace-format
-msgid ""
-"Selected group: {group}\n"
-"Make sure that you switch to the correct group!"
-msgstr ""
-"已選擇的群組: {group}\n"
-"請確保您已切換到正確群組!"
-
-#: bot.py:479
-#, python-brace-format
-msgid "Removing {name} from the game"
-msgstr "將 {name} 從遊戲移除"
-
-#: bot.py:501
-msgid "There is no game running in this chat. Create a new one with /new"
-msgstr "此聊天室目前沒有進行中的遊戲,使用 /new 開始新遊戲"
-
-#: bot.py:508
-msgid "The game has already started"
-msgstr "遊戲已經開始"
-
-#: bot.py:514
-#, python-brace-format
-msgid ""
-"At least {minplayers} players must /join the game before you can start it"
-msgstr "必須至少要有 {minplayers} 個人 /join 才能開始遊戲"
-
-#: bot.py:528 bot.py:931
-msgid "Make your choice!"
-msgstr ""
-
-#: bot.py:533
-#, python-brace-format
-msgid ""
-"First player: {name}\n"
-"Use /close to stop people from joining the game.\n"
-"Enable multi-translations with /enable_translations"
-msgstr ""
-"第一位玩家: {name}\n"
-"可使用 /close 防止玩家加入此場遊戲。\n"
-"請使用 /enable_translations 開啟多翻譯模式"
-
-#: bot.py:577
-msgid "Please select the group you want to play in."
-msgstr "請選擇你要遊玩的群組。"
-
-#: bot.py:606
-msgid "Closed the lobby. No more players can join this game."
-msgstr "已關閉遊戲大廳。其他玩家無法再加入此場遊戲。"
-
-#: bot.py:641
-msgid "Opened the lobby. New players may /join the game."
-msgstr "已開啟遊戲大廳。新玩家可以使用 /join 加入此場遊戲。"
-
-#: bot.py:676
-msgid "Enabled multi-translations. Disable with /disable_translations"
-msgstr "已啟用多翻譯模式。可使用 /disable_translations 停用"
-
-#: bot.py:712
-msgid ""
-"Disabled multi-translations. Enable them again with /enable_translations"
-msgstr "已停用多翻譯模式。可使用 /enable_translations 再次啟用。"
-
-#: bot.py:740
-msgid "You are not playing in a game in this chat."
-msgstr "您不在此聊天室的遊戲中。"
-
-#: bot.py:758
-#, python-brace-format
-msgid "Please wait {time} second"
-msgid_plural "Please wait {time} seconds"
-msgstr[0] "請等待 {time} 秒"
-
-#: bot.py:837
-#, python-brace-format
-msgid "Current game: {game}"
-msgstr "目前遊戲: {game}"
-
-#: bot.py:877
-#, python-brace-format
-msgid "Gamemode changed to {mode}"
-msgstr "遊戲模式已變更成 {mode}"
-
-#: bot.py:884
-#, python-brace-format
-msgid "Cheat attempt by {name}"
-msgstr "{name} 嘗試作弊"
-
-#: bot.py:925
-#, python-brace-format
-msgid "Next player: {name}"
-msgstr "輪到: {name}"
-
-#: bot.py:951
-#, python-brace-format
-msgid "Waiting time for {name} has been reset to {time} seconds"
-msgstr "{name} 的等待時間已重設成 {time} 秒"
-
-#: results.py:37
-msgid "Choose Player"
-msgstr ""
-
-#: results.py:50
-msgid "Choose Color"
-msgstr "選擇顏色"
-
-#: results.py:66
-msgid "Card (tap for game state):"
-msgid_plural "Cards (tap for game state):"
-msgstr[0] "卡牌 (按一下取得遊戲狀態):"
-
-#: results.py:80
-#, python-brace-format
-msgid "{name} ({number} card)"
-msgid_plural "{name} ({number} cards)"
-msgstr[0] "{name} (有 {number} 張牌)"
-
-#: results.py:91
-msgid "You are not playing"
-msgstr "您不在遊戲中"
-
-#: results.py:94
-msgid ""
-"Not playing right now. Use /new to start a game or /join to join the current "
-"game in this group"
-msgstr "您現在不在遊戲中。請使用 /new 開始新遊戲,或使用 /join 加入目前此群組的遊戲"
-
-#: results.py:108
-msgid "The game wasn't started yet"
-msgstr "遊戲尚未開始"
-
-#: results.py:110
-msgid "Start the game with /start"
-msgstr "請使用 /start 開始遊戲"
-
-#: results.py:121
-msgid "🎻 Classic mode"
-msgstr "🎻 傳統模式"
-
-#: results.py:122
-msgid "Classic 🎻"
-msgstr "傳統 🎻"
-
-#: results.py:132
-msgid "🚀 Sanic mode"
-msgstr "🚀 Sanic 模式"
-
-#: results.py:133
-msgid "Gotta go fast! 🚀"
-msgstr "得快點! 🚀"
-
-#: results.py:143
-msgid "🐉 Wild mode"
-msgstr "🐉 野外 (Wild) 模式"
-
-#: results.py:144
-msgid "Into the Wild~ 🐉"
-msgstr "走進野外~ 🐉"
-
-#: results.py:153
-msgid "🔫 7-0 mode"
-msgstr ""
-
-#: results.py:154
-msgid "Carioca mode on 🔫"
-msgstr ""
-
-#: results.py:164
-msgid "✍️ Text mode"
-msgstr ""
-
-#: results.py:165
-msgid "Text ✍️"
-msgstr ""
-
-#: results.py:180
-#, python-brace-format
-msgid "Drawing {number} card"
-msgid_plural "Drawing {number} cards"
-msgstr[0] "抽 {number} 張牌"
-
-#: results.py:209
-msgid "Pass"
-msgstr "PASS! 下一位!"
-
-#: results.py:222
-msgid "I'm calling your bluff!"
-msgstr "別騙了,虛張聲勢 = ="
-
-#: results.py:262
-#, python-brace-format
-msgid "Current player: {name}"
-msgstr "目前玩家: {name}"
-
-#: results.py:264
-#, python-brace-format
-msgid "Last card: {card}"
-msgstr "上一張牌: {card}"
-
-#: results.py:266
-#, python-brace-format
-msgid "Player: {player_list}"
-msgid_plural "Players: {player_list}"
-msgstr[0] "玩家: {player_list}"
-
-#: settings.py:34
-msgid "Please edit your settings in a private chat with the bot."
-msgstr "請私訊這台機器人來編輯設定。"
-
-#: settings.py:45
-msgid "Delete all statistics"
-msgstr "刪除所有統計資料"
-
-#: settings.py:47
-msgid "Enable statistics"
-msgstr "啟用統計資料"
-
-#: settings.py:50
-msgid "Language"
-msgstr "語言"
-
-#: settings.py:53
-msgid "Settings"
-msgstr "設定"
-
-#: settings.py:67
-msgid "Enabled statistics!"
-msgstr "已啟用統計資料!"
-
-#: settings.py:77
-msgid "Select locale"
-msgstr "選擇語言"
-
-#: settings.py:87
-msgid "Deleted and disabled statistics!"
-msgstr "已停用並刪除統計資料!"
-
-#: settings.py:100
-msgid "Set locale!"
-msgstr "已設定語言!"
-
-#: simple_commands.py:31
-msgid ""
-"Follow these steps:\n"
-"\n"
-"1. Add this bot to a group\n"
-"2. In the group, start a new game with /new or join an already running game "
-"with /join\n"
-"3. After at least two players have joined, start the game with /start\n"
-"4. Type @UnuRobot into your chat box and hit space, or "
-"click the via @UnuRobot text next to messages. You will see "
-"your cards (some greyed out), any extra options like drawing, and a ? "
-"to see the current game state. The greyed out cards are those you "
-"can not play at the moment. Tap an option to execute the selected "
-"action.\n"
-"Players can join the game at any time. To leave a game, use /leave. If a "
-"player takes more than 90 seconds to play, you can use /skip to skip that "
-"player. Use /notify_me to receive a private message when a new game is "
-"started.\n"
-"\n"
-"Language and other settings: /settings\n"
-"Other commands (only game creator):\n"
-"/close - Close lobby\n"
-"/open - Open lobby\n"
-"/kill - Terminate the game\n"
-"/kick - Select a player to kick by replying to him or her\n"
-"/enable_translations - Translate relevant texts into all languages spoken in "
-"a game\n"
-"/disable_translations - Use English for those texts\n"
-"\n"
-"Experimental: Play in multiple groups at the same time. Press the "
-"Current game: ... button and select the group you want to play "
-"a card in.\n"
-"If you enjoy this bot, join the update channel and buy an UNO card game."
-msgstr ""
-
-#: simple_commands.py:79
-msgid ""
-"This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n"
-"\n"
-" 🎻 The Classic mode uses the conventional UNO deck and there is no auto "
-"skip.\n"
-" 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically "
-"skips a player if he/she takes too long to play its turn\n"
-" 🐉 The Wild mode uses a deck with more special cards, less number variety "
-"and no auto skip.\n"
-" ✍️ The Text mode uses the conventional UNO deck but instead of stickers it "
-"uses the text.\n"
-" 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, "
-"he/she can choose a player to swap cards with. When a player plays a 0, all "
-"cards will be swapped between the current players.\n"
-"\n"
-"To change the game mode, the GAME CREATOR has to type the bot nickname and a "
-"space, just like when playing a card, and all gamemode options should appear."
-msgstr ""
-
-#: simple_commands.py:102
-msgid ""
-"This bot is Free Software and licensed under the AGPL. The code is available "
-"here: \n"
-"https://github.com/AmanoTeam/UnuRobot"
-msgstr ""
-"這台機器人是自由軟體,使用 AGPL 授權。程式碼可在此處取得:\n"
-"https://github.com/AmanoTeam/UnuRobot"
-
-#: simple_commands.py:107
-msgid ""
-"Attributions:\n"
-"Draw icon by Faithtoken\n"
-"Pass icon by Delapouite\n"
-"Originals available on http://game-icons.net\n"
-"Icons edited by ɳick"
-msgstr ""
-"來源:\n"
-"抽牌 (Draw) 圖示來自 Faithtoken"
-"a>。\n"
-"跳過 (Pass) 圖示來自 Delapouite。\n"
-"原始圖示可在 http://game-icons.net 取得。\n"
-"圖示由 ɳick 編輯。"
-
-#: simple_commands.py:130
-msgid "All news here: https://t.me/UnuRobotUpdates"
-msgstr "新聞頻道: https://t.me/UnuRobotUpdates"
-
-#: simple_commands.py:145
-msgid ""
-"You did not enable statistics. Use /settings in a private chat with the bot "
-"to enable them."
-msgstr ""
-"您尚未啟用統計資料。請在這台機器人的私人對話中傳送 /settings 以"
-"啟用。"
-
-#: simple_commands.py:153
-#, python-brace-format
-msgid "{number} game played"
-msgid_plural "{number} games played"
-msgstr[0] "已遊玩 {number} 場遊戲"
-
-#: simple_commands.py:160
-#, python-brace-format
-msgid "{number} first place ({percent}%)"
-msgid_plural "{number} first places ({percent}%)"
-msgstr[0] "拿了 {number} 次第一名 ({percent}%)"
-
-#: simple_commands.py:168
-#, python-brace-format
-msgid "{number} card played"
-msgid_plural "{number} cards played"
-msgstr[0] "已遊玩 {number} 張牌"
-
-#: utils.py:54 utils.py:66
-#, python-brace-format
-msgid "{emoji} Red"
-msgstr "{emoji} 紅色"
-
-#: utils.py:56 utils.py:68
-#, python-brace-format
-msgid "{emoji} Blue"
-msgstr "{emoji} 藍色"
-
-#: utils.py:58 utils.py:70
-#, python-brace-format
-msgid "{emoji} Green"
-msgstr "{emoji} 綠色"
-
-#: utils.py:60 utils.py:72
-#, python-brace-format
-msgid "{emoji} Yellow"
-msgstr "{emoji} 黃色"
diff --git a/logo.png b/logo.png
deleted file mode 100644
index 08b32b7..0000000
Binary files a/logo.png and /dev/null differ
diff --git a/mwt.py b/mwt.py
deleted file mode 100644
index 58dd00f..0000000
--- a/mwt.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Source: http://code.activestate.com/recipes/325905-memoize-decorator-with-timeout/#c1
-
-import time
-
-
-class MWT:
- """Memoize With Timeout."""
-
- _caches = {}
- _timeouts = {}
-
- def __init__(self, timeout=2) -> None:
- self.timeout = timeout
-
- def collect(self):
- """Clear cache of results which have timed out."""
- for func in self._caches:
- cache = {
- key: self._caches[func][key]
- for key in self._caches[func]
- if (time.time() - self._caches[func][key][1]) < self._timeouts[func]
- }
-
- self._caches[func] = cache
-
- def __call__(self, f):
- self.cache = self._caches[f] = {}
- self._timeouts[f] = self.timeout
-
- def func(*args, **kwargs):
- kw = sorted(kwargs.items())
- key = (args, tuple(kw))
- try:
- v = self.cache[key]
- print("cache")
- if (time.time() - v[1]) > self.timeout:
- raise KeyError
- except KeyError:
- print("new")
- v = self.cache[key] = f(*args, **kwargs), time.time()
- return v[0]
-
- func.func_name = f.__name__
-
- return func
diff --git a/player.py b/player.py
deleted file mode 100644
index 3d94bc0..0000000
--- a/player.py
+++ /dev/null
@@ -1,184 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import logging
-from datetime import datetime
-
-import card as c
-from config import WAITING_TIME
-from errors import DeckEmptyError
-
-
-class Player:
- """This class represents a player.
- It is basically a doubly-linked ring list with the option to reverse the
- direction. On initialization, it will connect itself to a game and its
- other players by placing itself behind the current player.
- """
-
- def __init__(self, game, user) -> None:
- self.cards = []
- self.game = game
- self.user = user
- self.logger = logging.getLogger(__name__)
-
- # Check if this player is the first player in this game.
- if game.current_player:
- self.next = game.current_player
- self.prev = game.current_player.prev
- game.current_player.prev.next = self
- game.current_player.prev = self
- else:
- self._next = self
- self._prev = self
- game.current_player = self
-
- self.bluffing = False
- self.drew = False
- self.anti_cheat = 0
- self.turn_started = datetime.now()
- self.waiting_time = WAITING_TIME
-
- def draw_first_hand(self):
- try:
- for _ in range(7):
- self.cards.append(self.game.deck.draw())
- except DeckEmptyError:
- for card in self.cards:
- self.game.deck.dismiss(card)
-
- raise
-
- def leave(self):
- """Removes player from the game and closes the gap in the list."""
- if self.next is self:
- return
-
- self.next.prev = self.prev
- self.prev.next = self.next
- self.next = None
- self.prev = None
-
- for card in self.cards:
- self.game.deck.dismiss(card)
-
- self.cards = []
-
- def __repr__(self) -> str:
- return repr(self.user)
-
- def __str__(self) -> str:
- return str(self.user)
-
- @property
- def next(self):
- return self._prev if self.game.reversed else self._next
-
- @next.setter
- def next(self, player):
- if not self.game.reversed:
- self._next = player
- else:
- self._prev = player
-
- @property
- def prev(self):
- return self._next if self.game.reversed else self._prev
-
- @prev.setter
- def prev(self, player):
- if not self.game.reversed:
- self._prev = player
- else:
- self._next = player
-
- def draw(self):
- """Draws 1+ cards from the deck, depending on the draw counter."""
- _amount = self.game.draw_counter or 1
-
- try:
- for _ in range(_amount):
- self.cards.append(self.game.deck.draw())
-
- except DeckEmptyError:
- raise
-
- finally:
- self.game.draw_counter = 0
- self.drew = True
-
- def rm(self, card):
- """Plays a card and removes it from hand."""
- self.cards.remove(card)
-
- def play(self, card):
- """Plays a card and removes it from hand."""
- self.cards.remove(card)
- self.game.play_card(card)
-
- def playable_cards(self):
- """Returns a list of the cards this player can play right now."""
- playable = []
- last = self.game.last_card
-
- self.logger.debug("Last card was %s", str(last))
-
- cards = self.cards
- if self.drew:
- cards = self.cards[-1:]
-
- # You may only play a +4 if you have no cards of the correct color
- self.bluffing = False
- for card in cards:
- if self._card_playable(card):
- self.logger.debug("Matching!")
- playable.append(card)
-
- self.bluffing = self.bluffing or card.color == last.color
-
- # You may not play a chooser or +4 as your last card
- return [] if len(self.cards) == 1 and self.cards[0].special else playable
-
- def _card_playable(self, card):
- """Check a single card if it can be played."""
- is_playable = True
- last = self.game.last_card
- self.logger.debug("Checking card %s", str(card))
-
- if card.color != last.color and card.value != last.value and not card.special:
- self.logger.debug("Card's color or value doesn't match")
- is_playable = False
- elif (
- last.value == c.DRAW_TWO
- and card.value != c.DRAW_TWO
- and self.game.draw_counter
- ):
- self.logger.debug("Player has to draw and can't counter")
- is_playable = False
- elif last.special == c.DRAW_FOUR and self.game.draw_counter:
- self.logger.debug("Player has to draw and can't counter")
- is_playable = False
- elif last.special in [c.CHOOSE, c.DRAW_FOUR] and card.special in [
- c.CHOOSE,
- c.DRAW_FOUR,
- ]:
- self.logger.debug("Can't play colorchooser on another one")
- is_playable = False
- elif not last.color:
- self.logger.debug("Last card has no color")
- is_playable = False
-
- return is_playable
diff --git a/plugins/game.py b/plugins/game.py
new file mode 100644
index 0000000..dae8333
--- /dev/null
+++ b/plugins/game.py
@@ -0,0 +1,607 @@
+import importlib
+import re
+
+from hydrogram import Client, filters
+from hydrogram.enums import ChatType
+from hydrogram.types import (
+ ChosenInlineResult,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InlineQueryResultArticle,
+ InlineQueryResultCachedSticker,
+ InputTextMessageContent,
+ Message,
+ InlineQuery,
+ CallbackQuery,
+)
+from hydrogram.errors import ListenerTimeout
+
+from card import COLORS, cards
+from config import games, player_game
+from db import Chat, User
+from game import Game
+from typing import Union
+from locales import use_lang
+
+
+@Client.on_message(filters.command("new"))
+@use_lang()
+async def new_game(c: Client, m: Message, ut, ct):
+ await Chat.get_or_create(id=m.chat.id)
+ if (
+ m.chat.id in games
+ or m.chat.type == ChatType.PRIVATE
+ or player_game.get(m.from_user.id)
+ ):
+ return await m.reply_text(
+ ut("game_existis")
+ if m.chat.id in games
+ else ut("only_group")
+ if m.chat.type == ChatType.PRIVATE
+ else ut("already_in_game")
+ )
+
+ game = Game(m.chat, (await Chat.get(id=m.chat.id)).theme)
+ game.players[m.from_user.id] = m.from_user
+ games[m.chat.id] = game
+ player_game[m.from_user.id] = game
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(ct("join"), callback_data="join_game"),
+ InlineKeyboardButton(ct("leave"), callback_data="leave_game"),
+ ],
+ [InlineKeyboardButton(ct("start_game"), callback_data="start_game")],
+ ]
+ )
+ return await m.reply_text(ct("game_started"), reply_markup=keyb)
+
+
+@Client.on_message(filters.command("join"))
+@Client.on_callback_query(filters.regex("^join_game$"))
+@use_lang()
+async def join_game(c: Client, m: Union[Message, CallbackQuery], ut, ct):
+ if isinstance(m, CallbackQuery):
+ func = m.answer
+ else:
+ func = m.reply_text
+ game: Game = games.get(m.chat.id if isinstance(m, Message) else m.message.chat.id)
+ if not game or m.from_user.id in game.players or player_game.get(m.from_user.id):
+ return await func(
+ ut("no_game")
+ if not game
+ else ut("already_joined")
+ if m.from_user.id in game.players
+ else ut('already_in_game')
+ )
+ elif game.closed:
+ return await func(ct("lobby_closed"))
+
+ game.players[m.from_user.id] = m.from_user
+ player_game[m.from_user.id] = game
+ await func(ut("joined_game"))
+ if isinstance(m, CallbackQuery):
+ await c.send_message(
+ m.message.chat.id, ct("player_joined").format(m.from_user.mention)
+ )
+
+ if game.is_started:
+ game.players[m.from_user.id].cards = game.deck.draw(7)
+ game.players[m.from_user.id].total_cards = 0
+
+
+@Client.on_callback_query(filters.regex("^leave_game$"))
+@Client.on_message(filters.command("leave"))
+@use_lang()
+async def leave_game(c: Client, m: Union[Message, CallbackQuery], ut, ct):
+ if isinstance(m, CallbackQuery):
+ func = m.answer
+ else:
+ func = m.reply_text
+ game: Game = games.get(m.chat.id if isinstance(m, Message) else m.message.chat.id)
+ if not game or m.from_user.id not in game.players:
+ return await func(
+ ut("no_game") if not game else ut("no_joinned")
+ )
+
+ if game.is_started and game.next_player.id == m.from_user.id:
+ inline_keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(ct("play"), switch_inline_query_current_chat="")]]
+ )
+ game.next()
+ await c.send_message(
+ game.chat.id, ct("next").format(game.next_player.mention), reply_markup=inline_keyb
+ )
+ del game.players[m.from_user.id]
+ del player_game[m.from_user.id]
+ chat_id = m.chat.id if isinstance(m, Message) else m.message.chat.id
+
+ if len(game.players) == 0:
+ games.pop(m.chat.id if isinstance(m, Message) else m.message.chat.id)
+ if isinstance(m, CallbackQuery):
+ await c.send_message(
+ chat_id=chat_id,
+ text=ct("player_left").format(m.from_user.mention)+", "+ct("game_over"),
+ )
+ return await func(ut("game_over"))
+ if isinstance(m, CallbackQuery):
+ await c.send_message(
+ chat_id=chat_id, text=ct("player_left").format(m.from_user.mention)
+ )
+ return await func(ut("left_game"))
+
+
+@Client.on_message(filters.command("close"))
+@use_lang()
+async def close_game(c: Client, m: Message, ut, ct):
+ game = games.get(m.chat.id)
+ if not game or m.from_user != list(game.players.values())[0]:
+ return await m.reply_text(
+ ut("no_game")
+ if not game
+ else ut("not_allowed")
+ )
+
+ games.closed = True
+ return await m.reply_text(ct("lobby_closed"))
+
+
+@Client.on_message(filters.command("open"))
+@use_lang()
+async def open_game(c: Client, m: Message, ut, ct):
+ """Handles the opening of a game."""
+ game = games.get(m.chat.id)
+ if not game or m.from_user != list(game.players.values())[0]:
+ return await m.reply_text(
+ ut("no_game")
+ if not game
+ else ut("not_allowed")
+ )
+
+ games.closed = False
+ return await m.reply_text(ct("lobby_opened"))
+
+
+@Client.on_message(filters.command("kill"))
+@use_lang()
+async def kill_game(c: Client, m: Message, ut, ct):
+ game = games.get(m.chat.id)
+ if not game or m.from_user != list(game.players.values())[0]:
+ return await m.reply_text(
+ ut("no_game")
+ if not game
+ else ut("not_allowed")
+ )
+
+ games.pop(m.chat.id)
+ for player in game.players:
+ player_game.pop(player)
+ return await m.reply_text(ct("game_over"))
+
+
+@Client.on_message(filters.command("start") & ~filters.private)
+@Client.on_callback_query(filters.regex("^start_game$"))
+@use_lang()
+async def start_game(c: Client, m: Union[Message, CallbackQuery], ut, ct):
+ if isinstance(m, CallbackQuery):
+ func = m.answer
+ chat_id = m.message.chat.id
+ else:
+ func = m.reply_text
+ chat_id = m.chat.id
+ config = await Chat.get(id=chat_id)
+ theme = config.theme
+ game = games.get(chat_id)
+ if not game or m.from_user != list(game.players.values())[0]:
+ return await func(
+ ut("no_game")
+ if not game
+ else ut("not_allowed")
+ )
+
+ game.is_started = True
+ game.deck.shuffle()
+ for player in game.players.values():
+ player.cards = game.deck.draw(7)
+ player.total_cards = 0
+
+ await c.send_message(chat_id=chat_id, text=ct("game_started"))
+ pcard = next(
+ (
+ lcard
+ for lcard in game.deck.cards
+ if lcard[1] not in cards[config.theme]["CARDS"]["SPECIALS"]
+ ),
+ None,
+ )
+ game.deck.cards.remove(pcard)
+ game.deck.cards.append(pcard)
+ if pcard[1] == "draw":
+ if game.draw == -1:
+ game.draw = 0
+ game.draw += 2
+ await c.send_sticker(
+ chat_id=chat_id, sticker=cards[theme]["STICKERS"][f"{pcard[0]}_{pcard[1]}"]
+ )
+ game.last_card = pcard
+ game.next_player = list(game.players.values())[0]
+ inline_keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(ct("play"), switch_inline_query_current_chat="")]]
+ )
+ return await c.send_message(
+ chat_id,
+ ct("next").format(game.next_player.mention),
+ reply_markup=inline_keyb,
+ )
+
+
+@Client.on_inline_query(group=3)
+@use_lang()
+async def inline_query(c: Client, m: InlineQuery, ut, ct):
+ game = player_game.get(m.from_user.id)
+ if not game:
+ articles = [
+ InlineQueryResultArticle(
+ id="none",
+ title=ut("no_game"),
+ input_message_content=InputTextMessageContent(
+ ut("no_game_text")
+ ),
+ )
+ ]
+ return await m.answer(articles, cache_time=0)
+
+ config = await Chat.get(id=game.chat.id)
+ theme = config.theme
+ COLOR_ICONS = cards[theme]["CARDS"]["COLOR_ICONS"]
+ VALUES_ICONS = cards[theme]["CARDS"]["VALUES_ICONS"]
+ if game.chosen == "color" and game.next_player.id == m.from_user.id:
+ pre = ""
+ if game.last_card[1] in cards[theme]["CARDS"]["THEME_CARDS"]:
+ pre = f"{game.last_card[1]}-"
+ articles = [
+ InlineQueryResultArticle(
+ id=pre + color,
+ title=COLOR_ICONS[color],
+ input_message_content=InputTextMessageContent(
+ ct("colorchoosed").format(color=COLOR_ICONS[color])
+ ),
+ )
+ for color in COLORS
+ ]
+ await m.answer(articles, cache_time=0)
+ return
+ elif game.chosen == "player" and game.next_player.id == m.from_user.id:
+ players = list(game.players.keys())
+ players.remove(m.from_user.id)
+ articles = []
+ pre = ""
+ if game.last_card[1] in cards[theme]["CARDS"]["THEME_CARDS"]:
+ pre = f"{game.last_card[1]}-"
+ for player in players:
+ if len(players) == 1 or player != m.from_user.id:
+ articles.append(
+ InlineQueryResultArticle(
+ id=pre + str(player),
+ title=game.players[player].first_name,
+ input_message_content=InputTextMessageContent(
+ game.players[player].mention
+ ),
+ )
+ )
+ await m.answer(articles, cache_time=0)
+ return
+
+ info_text = ut("info_text").format(current_player=game.next_player.mention, last_card=COLOR_ICONS[game.last_card[0]]+VALUES_ICONS[game.last_card[1]])
+ for fplayer in game.players:
+ info_text += ut("info_text2").format(player=game.players[fplayer].mention, cards=len(game.players[fplayer].cards))
+
+ if not game or m.from_user.id != game.next_player.id:
+ articles = []
+ for num, pcard in enumerate(game.players[m.from_user.id].cards):
+ sticker_type = pcard[1] if pcard[0] == "x" else f"{pcard[0]}_{pcard[1]}"
+ articles += [
+ InlineQueryResultCachedSticker(
+ id=f"info-{num}",
+ sticker_file_id=cards[theme]["STICKERS_GREY"][sticker_type],
+ input_message_content=InputTextMessageContent(info_text),
+ )
+ ]
+
+ return await m.answer(articles, cache_time=0, is_gallery=True)
+
+ gcards = game.players[m.from_user.id].cards
+ lcard = game.last_card if game.draw < 2 else ("p", "draw")
+ xcard = f"{lcard[0]}_{lcard[1]}"
+ sticker_id = "option_pass" if game.draw == -1 else "option_draw"
+ sticker_text = (
+ ut("pass")
+ if game.draw == -1
+ else ut("buy").format(1)
+ if game.draw == 0
+ else ut("buy").format(game.draw)
+ )
+ articles = [
+ InlineQueryResultCachedSticker(
+ id=sticker_id,
+ sticker_file_id=cards[theme]["STICKERS"][sticker_id],
+ input_message_content=InputTextMessageContent(sticker_text),
+ )
+ ]
+
+ if game.last_card[1] == "draw_four" and game.draw == 4:
+ if (await Chat.get(id=game.chat.id)).bluff:
+ articles.append(
+ InlineQueryResultCachedSticker(
+ id="option_bluff",
+ sticker_file_id=cards[theme]["STICKERS"]["option_bluff"],
+ input_message_content=InputTextMessageContent(
+ ut("bluff")
+ ),
+ )
+ )
+
+ for num, pcard in enumerate(gcards):
+ sticker_type = pcard[1] if pcard[0] == "x" else f"{pcard[0]}_{pcard[1]}"
+ if (
+ (
+ pcard[1] in cards[theme]["CARDS"]["SPECIALS_INFO"]
+ and re.search(
+ cards[theme]["CARDS"]["SPECIALS_INFO"][pcard[1]][1], string=xcard
+ )
+ )
+ or pcard[0] == lcard[0]
+ or pcard[1] == lcard[1]
+ ):
+ articles.append(
+ InlineQueryResultCachedSticker(
+ id=f"{pcard[0]}-{pcard[1]}-{num}",
+ sticker_file_id=cards[theme]["STICKERS"][sticker_type],
+ )
+ )
+ else:
+ articles.append(
+ InlineQueryResultCachedSticker(
+ id=f"info-{num}",
+ sticker_file_id=cards[theme]["STICKERS_GREY"][sticker_type],
+ input_message_content=InputTextMessageContent(info_text),
+ )
+ )
+
+ await m.answer(articles, cache_time=0, is_gallery=True)
+
+
+@Client.on_chosen_inline_result(group=1)
+@use_lang()
+async def choosen(c: Client, ir: ChosenInlineResult, ut, ct):
+ game: Game = player_game.get(ir.from_user.id)
+ if not game and game.next_player.id != ir.from_user.id:
+ return
+
+ config = await Chat.get(id=game.chat.id)
+ pcard = ir.result_id.split("-")[:2]
+ ncard = ir.result_id.split("-")[2] if len(ir.result_id.split("-")) > 2 else None
+ lcard = game.last_card if game.draw <= 1 else ("y", "draw")
+ print(game.deck.cards)
+ inline_keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(ct("play"), switch_inline_query_current_chat="")]]
+ )
+ if pcard[0] == "info":
+ return
+ elif game.chosen == "color":
+ game.last_card = (ir.result_id, game.last_card[1])
+ game.chosen = None
+ elif game.chosen == "player" and game.last_card_2["card"][1] == "7":
+ game.players[ir.from_user.id].cards, game.players[int(pcard[0])].cards = (
+ game.players[int(pcard[0])].cards,
+ game.players[ir.from_user.id].cards,
+ )
+ game.chosen = None
+ await c.send_message(
+ game.chat.id,
+ ct("cards_swapped").format(name1=game.next_player.mention, name2=game.players[int(pcard[0])].mention),
+ )
+ game.next()
+ pcard.append("player")
+ await verify_cards(game, c, ir, game.players[int(pcard[0])], ut, ct)
+ elif pcard[0] == "option_draw":
+ buy = game.draw if game.draw > 0 else 1
+ game.players[ir.from_user.id].cards.extend(game.deck.draw(buy))
+ await c.send_message(game.chat.id, ct("bought").format(buy=buy))
+ game.draw = 0 if buy >= 2 else -1 if len(game.players) != 1 else 0
+ elif pcard[0] == "option_pass":
+ game.draw = 0
+ elif pcard[0] == "option_bluff":
+ lplayer = game.players[game.last_card_2["player"]]
+ bcard = game.last_card_2["card"]
+ if any(bcard[0] in tupla or bcard[1] in tupla for tupla in lplayer.cards):
+ lplayer.cards.extend(game.deck.draw(game.draw))
+ await c.send_message(
+ game.chat.id,
+ ct("bluffed").format(name=lplayer.mention, draw=game.draw),
+ )
+ game.draw = 0
+ await c.send_message(
+ game.chat.id,
+ ct("next").format(game.next_player.mention),
+ reply_markup=inline_keyb,
+ )
+ return
+ else:
+ game.players[ir.from_user.id].cards.extend(game.deck.draw(game.draw + 2))
+ await c.send_message(
+ game.chat.id,
+ ct("not_bluffed").format(name1=lplayer.mention, name2=ir.from_user.mention, draw=game.draw + 2),
+ )
+ game.draw = 0
+ game.next()
+ await c.send_message(
+ game.chat.id,
+ f"Próximo: {game.next_player.mention}",
+ reply_markup=inline_keyb,
+ )
+ return
+ elif pcard[0] == "x" and pcard[1] in ["colorchooser", "draw_four"]:
+ game.players[ir.from_user.id].total_cards += 1
+ if pcard[1] == "draw_four":
+ if game.draw == -1:
+ game.draw = 0
+ game.draw += 4
+ game.last_card_2 = {"card": game.last_card, "player": ir.from_user.id}
+ game.last_card = game.players[ir.from_user.id].cards.pop(int(ncard))
+ game.deck.cards.append(game.last_card)
+ game.chosen = "color"
+ return await c.send_message(
+ game.chat.id,
+ ct("colorchoose").format(name=game.next_player.mention),
+ reply_markup=inline_keyb,
+ )
+ elif (
+ pcard[0] in cards[config.theme]["CARDS"]["THEME_CARDS"]
+ or (pcard[1] and pcard[1] in cards[config.theme]["CARDS"]["THEME_CARDS"])
+ ):
+ game.deck.cards.append(game.last_card)
+ module = importlib.import_module(f"spetials.{config.theme}")
+ function = getattr(
+ module,
+ pcard[1]
+ if pcard[1] in cards[config.theme]["CARDS"]["THEME_CARDS"]
+ else pcard[0],
+ )
+ ret = await function(c, ir, game)
+ if ret:
+ return
+ elif pcard[0] != "x" and (pcard[1] == lcard[1] or pcard[0] == lcard[0]):
+ game.players[ir.from_user.id].total_cards += 1
+ game.draw += 2 if pcard[1] == "draw" else 0
+ game.last_card_2 = {"card": game.last_card, "player": ir.from_user.id}
+ game.last_card = game.players[ir.from_user.id].cards.pop(int(ncard))
+ game.deck.cards.append(game.last_card)
+ if pcard[1] == "reverse":
+ game.players = {
+ k: game.players[k] for k in reversed(list(game.players.keys()))
+ }
+ game.next() if len(game.players) == 2 else None
+ elif pcard[1] == "skip":
+ game.next()
+ elif ((await Chat.get(id=game.chat.id)).seven) and (
+ pcard[1] == "7" or pcard[1] == "0"
+ ):
+ if pcard[1] == "7":
+ if len(game.players) == 1 or len(game.players) == 2:
+ await c.send_message(
+ game.chat.id,
+ ct("not_swapped")
+ )
+ else:
+ game.chosen = "player"
+ game.last_card_2 = {
+ "card": game.last_card,
+ "player": ir.from_user.id,
+ }
+ return await c.send_message(
+ game.chat.id,
+ ct("playerchoose").format(name=game.next_player.mention),
+ reply_markup=inline_keyb,
+ )
+ else:
+ # Aqui irá trocar as cartas dos jogadores na ordem do jogo
+ gcards = {}
+ a = 0
+ for i in game.players:
+ gcards[a] = game.players[i].cards
+ a += 1
+
+ a = 1
+ for i in game.players:
+ if a in gcards:
+ game.players[i].cards = gcards[a]
+ else:
+ game.players[i].cards = gcards[0]
+ a += 1
+ await verify_cards(game, c, ir, game.players[i], ut, ct)
+
+ await c.send_message(game.chat.id, ct("swapped"))
+ if game.draw == -1:
+ game.draw = 0
+ else:
+ return await c.send_message(game.chat.id, ct("invalid_card"))
+
+ if games.get(game.chat.id):
+ await verify_cards(game, c, ir, ir.from_user, ut, ct)
+ game.next()
+ return await c.send_message(
+ game.chat.id, ct("next").format(game.next_player.mention), reply_markup=inline_keyb
+ )
+
+async def verify_cards(game, c, ir, user, ut, t):
+ inline_keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(t("play"), switch_inline_query_current_chat="")]]
+ )
+ if len(game.players[user.id].cards) == 1:
+ if not (await Chat.get(id=game.chat.id)).one_card:
+ await c.send_message(game.chat.id, t("said_uno").format(name=user.mention))
+ else:
+ await c.send_message(
+ game.chat.id,
+ ut("say_uno").format(name=user.mention),
+ )
+ uno = False
+ while True:
+ try:
+ cmessage = await game.chat.listen(
+ filters.text | filters.user(user.id), timeout=5
+ )
+ if (cmessage and cmessage.text) and "uno" in cmessage.text.lower():
+ uno = True
+ break
+ except ListenerTimeout:
+ break
+ if uno:
+ await c.send_message(
+ game.chat.id, t("said_uno").format(name=user.mention)
+ )
+ else:
+ game.players[user.id].cards.extend(game.deck.draw(2))
+ await c.send_message(
+ game.chat.id,
+ t("not_said_uno").format(name=user.mention),
+ )
+
+ elif len(game.players[user.id].cards) == 0:
+ comp_text = t("first") if game.winner else ""
+ await c.send_message(game.chat.id, t("won").format(name=user.mention, comp=comp_text))
+ if game.winner:
+ game.winner = False
+ db_user = await User.get_or_none(id=user.id)
+ if db_user and db_user.placar:
+ db_user.wins += 1
+ await db_user.save()
+ if (await Chat.get(id=game.chat.id)).one_win and len(game.players) > 2:
+ db_user = await User.get_or_none(id=user.id)
+ if db_user and db_user.placar:
+ db_user.matches += 1
+ db_user.cards += game.players[user.id].total_cards
+ await db_user.save()
+ game.next()
+ game.players.pop(user.id)
+ player_game.pop(user.id)
+ await c.send_message(
+ game.chat.id, t("continuing").format(count=len(game.players))
+ )
+ await c.send_message(
+ game.chat.id,
+ t("next").format(game.next_player.mention),
+ reply_markup=inline_keyb,
+ )
+ else:
+ games.pop(game.chat.id)
+ for player in game.players:
+ db_user = await User.get_or_none(id=player)
+ if db_user and db_user.placar:
+ db_user.matches += 1
+ db_user.cards += game.players[player].total_cards
+ await db_user.save()
+ player_game.pop(player)
+ await c.send_message(game.chat.id, t("game_over"))
+ return
diff --git a/plugins/settings.py b/plugins/settings.py
new file mode 100644
index 0000000..09ad5e9
--- /dev/null
+++ b/plugins/settings.py
@@ -0,0 +1,209 @@
+from hydrogram import Client, filters
+from hydrogram.types import Message, CallbackQuery
+from hydrogram.enums import ChatType, ChatMemberStatus
+from hydrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
+from typing import Union
+from functools import partial
+from card import cards
+from db import Chat, User
+from config import games
+from locales import langs, get_locale_string, use_chat_lang, use_user_lang
+from hydrogram.helpers import ikb
+
+
+@Client.on_callback_query(filters.regex("^settings$"))
+@Client.on_message(filters.command("settings"))
+@use_chat_lang()
+async def settings(c: Client, m: Union[Message, CallbackQuery], t):
+ if (
+ isinstance(m, Message)
+ and m.chat.type == ChatType.PRIVATE
+ or isinstance(m, CallbackQuery)
+ and m.message.chat.type == ChatType.PRIVATE
+ ):
+ print(m)
+ if isinstance(m, Message):
+ func = m.reply_text
+ else:
+ func = m.edit_message_text
+
+ x = await User.get(id=m.from_user.id)
+ keyb = [
+ [(t("language"), "info_lang"), (t("lang_flag"), "lang")],
+ [(t("status"), "status"), ("✅" if x.placar else "✖️", "ch_status")],
+ ]
+
+ if await filters.filter_sudoers(c, m):
+ keyb.append([("sudos", "sudos")])
+
+ keyb.append([(t("back"), "start")])
+
+ await func(t("settings"), reply_markup=ikb(keyb))
+ else:
+ chat_id = m.chat.id if isinstance(m, Message) else m.message.chat.id
+ admin = await c.get_chat_member(chat_id, m.from_user.id)
+ print(admin)
+ if admin.status == ChatMemberStatus.MEMBER:
+ await m.reply("You need to be an admin to change the settings!")
+ return
+ if games.get(chat_id) and games[chat_id].is_started:
+ await m.reply("You can't change the settings while a game is running!")
+ return
+ x = (await Chat.get_or_create(id=chat_id))[0]
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(t("theme"), callback_data="info_theme"),
+ InlineKeyboardButton(t(x.theme), callback_data="theme"),
+ ],
+ [
+ InlineKeyboardButton(t("seven_zero"), callback_data="info_seven"),
+ InlineKeyboardButton(
+ "✅" if x.seven else "✖️", callback_data="mode_seven"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("sbluff"), callback_data="info_bluff"),
+ InlineKeyboardButton(
+ "✅" if x.bluff else "✖️", callback_data="mode_bluff"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("one_win"), callback_data="info_one_win"),
+ InlineKeyboardButton(
+ "✅" if x.one_win else "✖️", callback_data="mode_one_win"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("one_card"), callback_data="info_one_card"),
+ InlineKeyboardButton(
+ "✅" if x.one_card else "✖️", callback_data="mode_one_card"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("language"), callback_data="info_lang"),
+ InlineKeyboardButton(t("lang_flag"), callback_data="lang"),
+ ],
+ ]
+ )
+ if isinstance(m, Message):
+ await m.reply_text(t("settings"), reply_markup=keyb)
+ else:
+ await m.edit_message_text(t("settings"), reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("^theme"))
+@use_chat_lang()
+async def theme(c: Client, cq: CallbackQuery, t):
+ if " " in cq.data:
+ await Chat.get(id=cq.message.chat.id).update(theme=cq.data.split(" ")[1])
+ keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(t("back"), callback_data="theme")]]
+ )
+ await cq.message.edit_text("Theme changed!", reply_markup=keyb)
+ else:
+ themes = cards.keys()
+ tkeyb = [
+ InlineKeyboardButton(text=t(theme), callback_data=f"theme {theme}")
+ for theme in themes
+ ]
+ keyb = InlineKeyboardMarkup(
+ [tkeyb, [InlineKeyboardButton(text=t("back"), callback_data="settings")]]
+ )
+ await cq.message.edit_text(t("theme_config"), reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("mode_"))
+@use_chat_lang()
+async def mode(c: Client, cq: CallbackQuery, t):
+ admin = await c.get_chat_member(cq.message.chat.id, cq.from_user.id)
+ if admin.status is ChatMemberStatus.MEMBER:
+ await cq.answer("You need to be an admin to change the settings!")
+ return
+ x = await Chat.get(id=cq.message.chat.id)
+ if cq.data == "mode_seven":
+ await Chat.get(id=cq.message.chat.id).update(seven=not x.seven)
+ elif cq.data == "mode_bluff":
+ await Chat.get(id=cq.message.chat.id).update(bluff=not x.bluff)
+ elif cq.data == "mode_one_win":
+ await Chat.get(id=cq.message.chat.id).update(one_win=not x.one_win)
+ elif cq.data == "mode_one_card":
+ await Chat.get(id=cq.message.chat.id).update(one_card=not x.one_card)
+ await cq.answer("Done!")
+ x = await Chat.get(id=cq.message.chat.id)
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(t("theme"), callback_data="info_theme"),
+ InlineKeyboardButton(t(x.theme), callback_data="theme"),
+ ],
+ [
+ InlineKeyboardButton(t("seven_zero"), callback_data="info_seven"),
+ InlineKeyboardButton(
+ "✅" if x.seven else "✖️", callback_data="mode_seven"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("sbluff"), callback_data="info_bluff"),
+ InlineKeyboardButton(
+ "✅" if x.bluff else "✖️", callback_data="mode_bluff"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("one_win"), callback_data="info_one_win"),
+ InlineKeyboardButton(
+ "✅" if x.one_win else "✖️", callback_data="mode_one_win"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("one_card"), callback_data="info_one_card"),
+ InlineKeyboardButton(
+ "✅" if x.one_card else "✖️", callback_data="mode_one_card"
+ ),
+ ],
+ [
+ InlineKeyboardButton(t("language"), callback_data="info_lang"),
+ InlineKeyboardButton(t("lang_flag"), callback_data="lang"),
+ ],
+ ]
+ )
+ await cq.message.edit_text(t("settings"), reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("^lang"))
+@use_chat_lang()
+async def lang(c: Client, cq: CallbackQuery, t):
+ if cq.message.chat.type != ChatType.PRIVATE:
+ admin = await c.get_chat_member(cq.message.chat.id, cq.from_user.id)
+ if admin.status is ChatMemberStatus.MEMBER:
+ await cq.answer("You need to be an admin to change the theme!")
+ return
+ if "_" in cq.data:
+ nt = partial(get_locale_string, cq.data.split("_")[1])
+ if cq.message.chat.type == ChatType.PRIVATE:
+ await User.get(id=cq.message.chat.id).update(lang=cq.data.split("_")[1])
+ else:
+ await Chat.get(id=cq.message.chat.id).update(lang=cq.data.split("_")[1])
+ keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(nt("back"), callback_data="settings")]]
+ )
+ await cq.message.edit_text(nt("lang_changed"), reply_markup=keyb)
+ else:
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ get_locale_string(lang, "lang_name"),
+ callback_data=f"lang_{lang}",
+ )
+ ]
+ for lang in langs
+ ]
+ )
+ await cq.message.edit_text(t("choose_lang"), reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("^info_"))
+@use_user_lang()
+async def info(c: Client, cq: CallbackQuery, t):
+ await cq.answer(t(cq.data), show_alert=True)
diff --git a/plugins/start.py b/plugins/start.py
new file mode 100644
index 0000000..4dfb28c
--- /dev/null
+++ b/plugins/start.py
@@ -0,0 +1,68 @@
+from hydrogram import Client, filters
+from hydrogram.types import Message, CallbackQuery
+from hydrogram.helpers import ikb
+from typing import Union
+from db import User
+from locales import use_user_lang
+
+
+@Client.on_message(filters.command("start") & filters.private)
+@Client.on_callback_query(filters.regex("^start$"))
+@use_user_lang()
+async def start(c: Client, m: Union[Message, CallbackQuery], t):
+ if isinstance(m, CallbackQuery):
+ func = m.edit_message_text
+ else:
+ func = m.reply_text
+ await User.get_or_create(id=m.from_user.id)
+ print(m.from_user.id)
+ keyb = [[("help", "help"), ("configurações", "settings")]]
+ await func(t("start_text"), reply_markup=ikb(keyb))
+
+
+@Client.on_callback_query(filters.regex("^help$"))
+@use_user_lang()
+async def help(c: Client, cq: CallbackQuery, t):
+ keyb = [
+ [(t("game_mode"), "help_game")],
+ [(t("back"), "start")],
+ ]
+ await cq.edit_message_text(
+ "Ecolha uma opção de ajuda abaixo:", reply_markup=ikb(keyb)
+ )
+
+
+@Client.on_callback_query(filters.regex("^help_game$"))
+@use_user_lang()
+async def help_game(c: Client, cq: CallbackQuery, t):
+ text = t("game_mode_text")
+ text += "" + t("seven_zero") + ": " + t("info_seven") + "\n\n"
+ text += "" + t("sbluff") + ": " + t("info_bluff") + "\n\n"
+ text += "" + t("one_win") + ": " + t("info_one_win") + "\n\n"
+ text += "" + t("one_card") + ": " + t("info_one_card") + "\n\n"
+ keyb = [[(t("back"), "help")]]
+
+ await cq.edit_message_text(text, reply_markup=ikb(keyb))
+
+
+@Client.on_message(filters.command("status"))
+@Client.on_callback_query(filters.regex("^status$"))
+async def status(c: Client, m: Union[Message, CallbackQuery]):
+ user = await User.get_or_create(id=m.from_user.id)
+ porcentagem = (user[0].wins / user[0].matches) * 100 if user[0].matches > 0 else 0
+ if (await User.get(id=m.from_user.id)).placar:
+ text = f"{user[0].matches} partidas jogadas\n{user[0].wins} vezes em primeiro lugas ({porcentagem}%)\n{user[0].cards} cartas jogadas"
+ else:
+ text = "Ligue para saber suas estatísticas como quantas partidas jogadas, quantas vezes em primeiro lugar e quantas cartas jogadas"
+ if isinstance(m, Message):
+ await m.reply_text(text)
+ else:
+ await m.answer(text, show_alert=True)
+
+@Client.on_callback_query(filters.regex("^ch_status$"))
+async def ch_status(c: Client, cq: CallbackQuery):
+ user = await User.get_or_create(id=cq.from_user.id)
+ user = user[0]
+ user.placar = not user.placar
+ await user.save()
+ await cq.answer("Status alterado com sucesso")
diff --git a/plugins/sudos.py b/plugins/sudos.py
new file mode 100644
index 0000000..b3f72cd
--- /dev/null
+++ b/plugins/sudos.py
@@ -0,0 +1,467 @@
+from asyncio import sleep
+from json import dump
+from typing import Union
+
+from hydrogram import Client, filters
+from hydrogram.errors import ListenerTimeout, MediaEmpty
+from hydrogram.types import (
+ CallbackQuery,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InlineQuery,
+ InlineQueryResultCachedSticker,
+ Message,
+)
+
+from card import cards
+from config import sudoers
+from db import User
+
+
+async def filter_sudoers_logic(flt, c, u):
+ if not u.from_user:
+ return None
+ usr = u.from_user
+ db_usr = await User.get_or_none(id=usr.id)
+ if not db_usr:
+ return False
+ if db_usr.sudo or usr.id in sudoers:
+ return True
+ else:
+ return False
+
+
+filter_sudoers = filters.create(filter_sudoers_logic, "FilterSudoers")
+filters.filter_sudoers = filter_sudoers
+
+
+@Client.on_message(filters.command("sudos") & filters.private & filter_sudoers)
+@Client.on_callback_query(filters.regex("^sudos$") & filter_sudoers)
+async def start(c: Client, m: Union[Message, CallbackQuery]):
+ if isinstance(m, CallbackQuery):
+ func = m.edit_message_text
+ else:
+ func = m.reply_text
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton("Sudos", callback_data="settings_sudos"),
+ InlineKeyboardButton("themes", callback_data="settings_sudo_themc"),
+ ],
+ [
+ InlineKeyboardButton("Voltar", callback_data="settings"),
+ ]
+ ]
+ )
+ await func(
+ "Bem vindo ao menu de configurações do UnuRobot, aqui você pode configurar o bot da forma que quiser, para isso basta clicar em um dos botões abaixo!",
+ reply_markup=keyb,
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudos$") & filter_sudoers)
+async def settings_sudos(c: Client, cq: CallbackQuery):
+ usrs = await c.get_users(sudoers)
+ db_usrs = await User.filter(sudo=True)
+ usrs += await c.get_users([usr.id for usr in db_usrs])
+ text = "Lista de sudos:\n\n"
+ for usr in usrs:
+ text += f"👤 {usr.mention}\n"
+
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton("Adicionar", callback_data="settings_sudos_add"),
+ InlineKeyboardButton("Remover", callback_data="settings_sudos_remove"),
+ ],
+ [InlineKeyboardButton("Voltar", callback_data="sudos")],
+ ]
+ )
+
+ await cq.edit_message_text(text, reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("^settings_sudos_add$") & filter_sudoers)
+async def settings_sudos_add(c: Client, cq: CallbackQuery):
+ await cq.edit_message_text("Envie o ID do usuário que deseja adicionar aos sudos")
+ cmessage = None
+ # Wait for the user to send a message with the new emoji
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.text)
+ print(cmessage)
+ except ListenerTimeout:
+ return
+
+ text = cmessage.text
+ user = await c.get_users(text)
+
+ if not user:
+ await cmessage.reply_text("Usuário não encontrado")
+ return
+
+ user_db = await User.get_or_create(id=user.id)
+
+ if user_db[0].sudo:
+ await cmessage.reply_text("Usuário já é sudo")
+ return
+
+ user_db[0].sudo = True
+ await user_db[0].save()
+
+ await cmessage.reply_text(
+ "Usuário adicionado aos sudos",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Voltar", callback_data="settings_sudos")]]
+ ),
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudos_remove") & filter_sudoers)
+async def settings_sudos_remove(c: Client, cq: CallbackQuery):
+ if cq.data == "settings_sudos_remove":
+ db_users = await User.filter(sudo=True)
+ users = await c.get_users([usr.id for usr in db_users])
+ text = "Selecione o usuário que deseja remover dos sudos:\n\n"
+ keyb = []
+ for user in users:
+ keyb.append(
+ [
+ InlineKeyboardButton(
+ user.first_name,
+ callback_data=f"settings_sudos_remove_{user.id}",
+ )
+ ]
+ )
+
+ keyb.append([InlineKeyboardButton("Voltar", callback_data="settings_sudos")])
+ await cq.edit_message_text(text, reply_markup=InlineKeyboardMarkup(keyb))
+ return
+
+ db_users = await User.filter(sudo=True)
+ sudoers = [usr.id for usr in db_users]
+
+ user_id = int(cq.data.split("_")[3])
+ if user_id not in sudoers:
+ await cq.answer("Usuário não é sudo")
+ return
+
+ await User.get(id=user_id).update(sudo=False)
+
+ await cq.edit_message_text(
+ "Usuário removido dos sudos",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Voltar", callback_data="settings_sudos")]]
+ ),
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudo_themc$") & filter_sudoers)
+async def settings_sudo_themc(c: Client, cq: CallbackQuery):
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text=theme, callback_data=f"settings_sudo_themc {theme}"
+ )
+ for theme in cards.keys()
+ ],
+ [
+ InlineKeyboardButton(
+ "Adicionar novo", callback_data="settings_sudo_themc_new"
+ ),
+ InlineKeyboardButton("Voltar", callback_data="sudos"),
+ ],
+ ]
+ )
+ await cq.edit_message_text("Selecione um tema:", reply_markup=keyb)
+
+
+@Client.on_callback_query(filters.regex("^settings_sudo_themc_new$") & filter_sudoers)
+async def settings_themes_new(c: Client, cq: CallbackQuery):
+ await cq.edit_message_text("Envie o nome do tema")
+ cmessage = None
+ # Wait for the user to send a message with the new emoji
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.text)
+ print(cmessage)
+ except ListenerTimeout:
+ return
+
+ name = cmessage.text
+
+ ncards = cards["classic"]
+
+ for card in ncards["STICKERS"]:
+ await c.send_message(
+ cq.message.chat.id, "Mande um sticker para substituir o sticker:"
+ )
+ await c.send_sticker(cq.message.chat.id, ncards["STICKERS"][card])
+
+ cmessage = None
+ # Wait for the user to send a message with the new emoji
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ ncards["STICKERS"][card] = cmessage.sticker.file_id
+ except ListenerTimeout:
+ return
+ for card in ncards["STICKERS_GREY"]:
+ await c.send_message(
+ cq.message.chat.id, "Mande um sticker para substituir o sticker:"
+ )
+ await c.send_sticker(cq.message.chat.id, ncards["STICKERS_GREY"][card])
+
+ cmessage = None
+ # Wait for the user to send a message with the new emoji
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ ncards["STICKERS_GREY"][card] = cmessage.sticker.file_id
+ except ListenerTimeout:
+ return
+
+ with open(f"cards/{name}.json", "w") as f:
+ dump(ncards, f)
+
+ await c.send_message(
+ cq.message.chat.id,
+ "Tema adicionado com sucesso!",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Voltar", callback_data="settings_sudo_themc")]]
+ ),
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudo_themc ") & filter_sudoers)
+async def settings_themes(c: Client, cq: CallbackQuery):
+ theme = cq.data.split(" ")[1]
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ "Adicionar", callback_data="settings_sudo_themc_add " + theme
+ ),
+ InlineKeyboardButton(
+ "Atualizar", callback_data="settings_sudo_themc_update " + theme
+ ),
+ InlineKeyboardButton(
+ "Verificar", callback_data="settings_sudo_themc_check " + theme
+ ),
+ ],
+ [InlineKeyboardButton("Voltar", callback_data="settings_sudo_themc")],
+ ]
+ )
+ await cq.edit_message_text(
+ f"O que deseja fazer com o tema {theme}?", reply_markup=keyb
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudo_themc_add ") & filter_sudoers)
+async def settings_themes_add(c: Client, cq: CallbackQuery):
+ theme = cq.data.split(" ")[1]
+ await cq.edit_message_text("Envie o código da nova carta")
+
+ cmessage = None
+
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.text)
+ except ListenerTimeout:
+ return
+
+ code = cmessage.text
+
+ await c.send_message(cq.message.chat.id, f"Mande um sticker colorido para o {code}")
+
+ cmessage = None
+
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ except ListenerTimeout:
+ return
+
+ stickerc = cmessage.sticker.file_id
+
+ await c.send_message(cq.message.chat.id, f"Mande um sticker cinza para o {code}")
+
+ cmessage = None
+
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ except ListenerTimeout:
+ return
+
+ stickerg = cmessage.sticker.file_id
+
+ cards[theme]["STICKERS"][code] = stickerc
+ cards[theme]["STICKERS_GREY"][code] = stickerg
+
+ with open(f"cards/{theme}.json", "w") as f:
+ dump(cards[theme], f)
+
+ await c.send_message(
+ cq.message.chat.id,
+ "Carta adicionada com sucesso!",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Voltar", callback_data="settings_sudo_themc")]]
+ ),
+ )
+
+
+@Client.on_callback_query(
+ filters.regex("^settings_sudo_themc_update ") & filter_sudoers
+)
+async def settings_themes_update(c: Client, cq: CallbackQuery):
+ sp = cq.data.split(" ")[1:]
+ print(sp)
+ theme = sp[0]
+ if len(sp) == 1:
+ keyb = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ "Light",
+ callback_data=f"settings_sudo_themc_update {theme} Light",
+ ),
+ InlineKeyboardButton(
+ "Dark", callback_data=f"settings_sudo_themc_update {theme} Dark"
+ ),
+ ],
+ ]
+ )
+ await cq.edit_message_text(
+ "Escolha o tema que deseja atualizar", reply_markup=keyb
+ )
+ if len(sp) == 2:
+ keyb = []
+ for color in cards[theme]["CARDS"]["COLORS"]:
+ keyb.append(
+ InlineKeyboardButton(
+ color,
+ callback_data=f"settings_sudo_themc_update {theme} {sp[1]} {color}",
+ )
+ )
+ keyb.append(
+ InlineKeyboardButton(
+ "SPECIALS",
+ callback_data=f"settings_sudo_themc_update {theme} {sp[1]} SPECIALS",
+ )
+ )
+ await cq.edit_message_text(
+ "Escolha a cor da carta que deseja atualizar",
+ reply_markup=InlineKeyboardMarkup([keyb]),
+ )
+ elif len(sp) == 3:
+ keyb = []
+ if sp[2] == "SPECIALS":
+ for card in cards[theme]["CARDS"]["SPECIALS"]:
+ keyb.append(
+ [
+ InlineKeyboardButton(
+ card,
+ callback_data=f"settings_sudo_themc_update {theme} {sp[1]} x {card}",
+ )
+ ]
+ )
+ else:
+ for card in cards[theme]["CARDS"]["VALUES"]:
+ keyb.append(
+ [
+ InlineKeyboardButton(
+ card,
+ callback_data=f"settings_sudo_themc_update {theme} {sp[1]} {sp[2]} {card}",
+ )
+ ]
+ )
+ await cq.edit_message_text(
+ "Escolha o valor da carta que deseja atualizar",
+ reply_markup=InlineKeyboardMarkup(keyb),
+ )
+ elif len(sp) == 4:
+ await cq.edit_message_text("Envie um sticker para substituir a carta:")
+ cardid = sp[2] + "_" + sp[3] if sp[2] != "x" else sp[3]
+ cardtm = "STICKERS_GREY" if sp[1] == "Dark" else "STICKERS"
+ await c.send_sticker(cq.message.chat.id, cards[theme][cardtm][cardid])
+
+ cmessage = None
+
+ while cmessage is None:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ except ListenerTimeout:
+ return
+
+ cards[theme][cardtm][cardid] = cmessage.sticker.file_id
+
+ with open(f"cards/{theme}.json", "w") as f:
+ dump(cards[theme], f)
+
+ await c.send_message(
+ cq.message.chat.id,
+ "Carta atualizada com sucesso!",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Voltar", callback_data="settings_sudo_themc")]]
+ ),
+ )
+
+
+@Client.on_callback_query(filters.regex("^settings_sudo_themc_check ") & filter_sudoers)
+async def settings_themes_check(c: Client, cq: CallbackQuery):
+ theme = cq.data.split(" ")[1]
+ card_types = ["STICKERS", "STICKERS_GREY"]
+ messages = ["Verificando cartas coloridas...", "Verificando cartas cinzas..."]
+
+ for card_type, message in zip(card_types, messages):
+ await c.send_message(cq.message.chat.id, message)
+ for card in cards[theme][card_type]:
+ try:
+ m2 = await c.send_sticker(
+ cq.message.chat.id, cards[theme][card_type][card]
+ )
+ await m2.delete()
+ await sleep(0.3)
+ except MediaEmpty:
+ await c.send_message(
+ cq.message.chat.id,
+ f"Carta {card} não encontrada, mande a carta para substitui-lá",
+ )
+
+ while True:
+ try:
+ cmessage = await cq.message.chat.listen(filters.sticker)
+ break
+ except ListenerTimeout:
+ return
+
+ cards[theme][card_type][card] = cmessage.sticker.file_id
+ await c.send_message(
+ cq.message.chat.id, f"Carta {card} atualizada com sucesso!"
+ )
+
+ with open(f"cards/{theme}.json", "w") as f:
+ dump(cards[theme], f)
+
+ await c.send_message(cq.message.chat.id, "Cartas verificadas com sucesso!")
+
+
+@Client.on_inline_query(filters.regex("^change ") & filter_sudoers)
+async def change(c: Client, iq: InlineQuery):
+ theme = iq.query.split(" ")[1]
+ articles = []
+ for card in cards[theme]["STICKERS"]:
+ articles.append(
+ InlineQueryResultCachedSticker(
+ id="sudo" + card, sticker_file_id=cards[theme]["STICKERS"][card]
+ )
+ )
+ for card in cards[theme]["STICKERS_GREY"]:
+ articles.append(
+ InlineQueryResultCachedSticker(
+ id="sudog" + card, sticker_file_id=cards[theme]["STICKERS_GREY"][card]
+ )
+ )
+ return await iq.answer(articles, cache_time=0)
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index a73e847..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-python-telegram-bot>=20.0a5,<21.0
-pony
diff --git a/results.py b/results.py
deleted file mode 100644
index 2edace3..0000000
--- a/results.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-"""Defines helper functions to build the inline result list."""
-
-from uuid import uuid4
-
-from telegram import InlineQueryResultArticle, InputTextMessageContent
-from telegram import InlineQueryResultCachedSticker as Sticker
-
-import card as c
-from internationalization import _, __
-from utils import display_color, display_color_group, display_name
-
-
-def add_choose_player(name, results, game):
- """Add choose color options."""
- for a, i in enumerate(game.players):
- if name != i.user.id or len(game.players) == 1:
- results.append(
- InlineQueryResultArticle(
- id=f"player_{a}",
- title=_("Choose Player"),
- description=f"{i.user.first_name} - {len(i.cards)}",
- input_message_content=InputTextMessageContent(i.user.first_name),
- ),
- )
-
-
-def add_choose_color(results, game):
- """Add choose color options."""
- for color in c.COLORS:
- results.append(
- InlineQueryResultArticle(
- id=color,
- title=_("Choose Color"),
- description=display_color(color),
- input_message_content=InputTextMessageContent(
- display_color_group(color, game),
- ),
- ),
- )
-
-
-def add_other_cards(player, results, game):
- """Add hand cards when choosing colors."""
- results.append(
- InlineQueryResultArticle(
- "hand",
- title=_(
- "Card (tap for game state):",
- "Cards (tap for game state):",
- len(player.cards),
- ),
- description=", ".join([repr(card) for card in player.cards]),
- input_message_content=game_info(game),
- ),
- )
-
-
-def player_list(game):
- """Generate list of player strings."""
- return [
- _(
- "{name} ({number} card)",
- "{name} ({number} cards)",
- len(player.cards),
- ).format(name=player.user.first_name, number=len(player.cards))
- for player in game.players
- ]
-
-
-def add_no_game(results):
- """Add text result if user is not playing."""
- results.append(
- InlineQueryResultArticle(
- "nogame",
- title=_("You are not playing"),
- input_message_content=InputTextMessageContent(
- _(
- "Not playing right now. Use /new to "
- "start a game or /join to join the "
- "current game in this group",
- ),
- ),
- ),
- )
-
-
-def add_not_started(results):
- """Add text result if the game has not yet started."""
- results.append(
- InlineQueryResultArticle(
- "nogame",
- title=_("The game wasn't started yet"),
- input_message_content=InputTextMessageContent(
- _("Start the game with /start"),
- ),
- ),
- )
-
-
-def add_mode_classic(results):
- """Change mode to classic."""
- results.append(
- InlineQueryResultArticle(
- "mode_classic",
- title=_("🎻 Classic mode"),
- input_message_content=InputTextMessageContent(_("Classic 🎻")),
- ),
- )
-
-
-def add_mode_fast(results):
- """Change mode to classic."""
- results.append(
- InlineQueryResultArticle(
- "mode_fast",
- title=_("🚀 Sanic mode"),
- input_message_content=InputTextMessageContent(_("Gotta go fast! 🚀")),
- ),
- )
-
-
-def add_mode_wild(results):
- """Change mode to classic."""
- results.append(
- InlineQueryResultArticle(
- "mode_wild",
- title=_("🐉 Wild mode"),
- input_message_content=InputTextMessageContent(_("Into the Wild~ 🐉")),
- ),
- )
-
-
-def add_mode_sete(results):
- results.append(
- InlineQueryResultArticle(
- "mode_7-0",
- title=_("🔫 7-0 mode"),
- input_message_content=InputTextMessageContent(_("Carioca mode on 🔫")),
- ),
- )
-
-
-def add_mode_text(results):
- """Change mode to text."""
- results.append(
- InlineQueryResultArticle(
- "mode_text",
- title=_("✍️ Text mode"),
- input_message_content=InputTextMessageContent(_("Text ✍️")),
- ),
- )
-
-
-def add_draw(player, results):
- """Add option to draw."""
- n = player.game.draw_counter or 1
-
- results.append(
- Sticker(
- "draw",
- sticker_file_id=c.STICKERS["option_draw"],
- input_message_content=InputTextMessageContent(
- __(
- "Drawing {number} card",
- "Drawing {number} cards",
- n,
- multi=player.game.translate,
- ).format(number=n),
- ),
- ),
- )
-
-
-def add_gameinfo(game, results):
- """Add option to show game info."""
- results.append(
- Sticker(
- "gameinfo",
- sticker_file_id=c.STICKERS["option_info"],
- input_message_content=game_info(game),
- ),
- )
-
-
-def add_pass(results, game):
- """Add option to pass."""
- results.append(
- Sticker(
- "pass",
- sticker_file_id=c.STICKERS["option_pass"],
- input_message_content=InputTextMessageContent(
- __("Pass", multi=game.translate),
- ),
- ),
- )
-
-
-def add_call_bluff(results, game):
- """Add option to call a bluff."""
- results.append(
- Sticker(
- "call_bluff",
- sticker_file_id=c.STICKERS["option_bluff"],
- input_message_content=InputTextMessageContent(
- __("I'm calling your bluff!", multi=game.translate),
- ),
- ),
- )
-
-
-def add_card(game, card, results, can_play):
- """Add an option that represents a card."""
- if can_play:
- if game.mode != "text":
- results.append(Sticker(str(card), sticker_file_id=c.STICKERS[str(card)]))
- if game.mode == "text":
- results.append(
- Sticker(
- str(card),
- sticker_file_id=c.STICKERS[str(card)],
- input_message_content=InputTextMessageContent(
- "Card Played: {card}".format(
- card=repr(card)
- .replace("Draw Four", "+4")
- .replace("Draw", "+2")
- .replace("Colorchooser", "Color Chooser"),
- ),
- ),
- ),
- )
- else:
- results.append(
- Sticker(
- str(uuid4()),
- sticker_file_id=c.STICKERS_GREY[str(card)],
- input_message_content=game_info(game),
- ),
- )
-
-
-def game_info(game):
- players = player_list(game)
- return InputTextMessageContent(
- _("Current player: {name}").format(name=display_name(game.current_player.user))
- + "\n"
- + _("Last card: {card}").format(card=repr(game.last_card))
- + "\n"
- + _("Player: {player_list}", "Players: {player_list}", len(players)).format(
- player_list=" -> ".join(players),
- ),
- )
diff --git a/settings.py b/settings.py
deleted file mode 100644
index 9e076ea..0000000
--- a/settings.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from telegram import ReplyKeyboardMarkup, Update
-from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters
-
-from internationalization import _, user_locale
-from locales import available_locales
-from shared_vars import application
-from user_setting import UserSetting
-from utils import send_async
-
-
-@user_locale
-async def show_settings(update: Update, context: ContextTypes.DEFAULT_TYPE):
- chat = update.message.chat
-
- if update.message.chat.type != "private":
- await send_async(
- chat,
- text=_("Please edit your settings in a private chat with the bot."),
- message_thread_id=update.message.message_thread_id,
- )
- return
-
- us = UserSetting.get(id=update.message.from_user.id) or UserSetting(
- id=update.message.from_user.id,
- )
-
- stats = (
- "❌" + " " + _("Delete all statistics")
- if us.stats
- else "📊" + " " + _("Enable statistics")
- )
-
- kb = [[stats], ["🌍" + " " + _("Language")]]
- await send_async(
- chat,
- text="🔧" + " " + _("Settings"),
- reply_markup=ReplyKeyboardMarkup(keyboard=kb, one_time_keyboard=True),
- )
-
-
-@user_locale
-async def kb_select(update: Update, context: ContextTypes.DEFAULT_TYPE):
- chat = update.message.chat
- user = update.message.from_user
- option = context.matches[0].group(1)
-
- if option == "📊":
- us = UserSetting.get(id=user.id)
- us.stats = True
- await send_async(chat, text=_("Enabled statistics!"))
-
- elif option == "🌍":
- kb = [
- [f"{locale} - {descr}"]
- for locale, descr in sorted(available_locales.items())
- ]
-
- await send_async(
- chat,
- text=_("Select locale"),
- reply_markup=ReplyKeyboardMarkup(keyboard=kb, one_time_keyboard=True),
- )
-
- elif option == "❌":
- us = UserSetting.get(id=user.id)
- us.stats = False
- us.first_places = 0
- us.games_played = 0
- us.cards_played = 0
- await send_async(chat, text=_("Deleted and disabled statistics!"))
-
-
-@user_locale
-async def locale_select(update: Update, context: ContextTypes.DEFAULT_TYPE):
- chat = update.message.chat
- user = update.message.from_user
- option = context.matches[0].group(1)
-
- if option in available_locales:
- us = UserSetting.get(id=user.id)
- us.lang = option
- _.push(option)
- await send_async(chat, text=_("Set locale!"))
- _.pop()
-
-
-def register():
- application.add_handler(CommandHandler("settings", show_settings))
- application.add_handler(MessageHandler(filters.Regex(r"^([📊🌍❌]) .+$"), kb_select))
- application.add_handler(
- MessageHandler(filters.Regex(r"^(\w\w(_\w\w)?) - .*"), locale_select),
- )
diff --git a/shared_vars.py b/shared_vars.py
deleted file mode 100644
index 7184b6d..0000000
--- a/shared_vars.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import os
-
-from telegram.ext import Application
-
-from config import BASE_URL, TOKEN
-from database import db
-from game_manager import GameManager
-
-# Explicitly import UserSetting to avoid circular imports,
-# since UserSetting must be loaded before generating database mapping
-from user_setting import UserSetting # noqa: F401
-
-db.bind("sqlite", os.getenv("UNO_DB", "uno.sqlite3"), create_db=True)
-db.generate_mapping(create_tables=True)
-
-gm = GameManager()
-application = Application.builder().token(TOKEN).base_url(BASE_URL).build()
diff --git a/simple_commands.py b/simple_commands.py
deleted file mode 100644
index 9e219c4..0000000
--- a/simple_commands.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from telegram import Update
-from telegram.constants import ParseMode
-from telegram.ext import CommandHandler, ContextTypes
-
-from internationalization import _, user_locale
-from shared_vars import application
-from user_setting import UserSetting
-from utils import send_async
-
-
-@user_locale
-async def help_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /help command."""
- help_text = _(
- "Follow these steps:\n\n"
- "1. Add this bot to a group\n"
- "2. In the group, start a new game with /new or join an already"
- " running game with /join\n"
- "3. After at least two players have joined, start the game with"
- " /start\n"
- "4. Type @UnuRobot into your chat box and hit "
- "space, or click the via @UnuRobot text "
- "next to messages. You will see your cards (some greyed out), "
- "any extra options like drawing, and a ? to see the "
- "current game state. The greyed out cards are those you "
- "can not play at the moment. Tap an option to execute "
- "the selected action.\n"
- "Players can join the game at any time. To leave a game, "
- "use /leave. If a player takes more than 90 seconds to play, "
- "you can use /skip to skip that player. Use /notify_me to "
- "receive a private message when a new game is started.\n\n"
- "Language and other settings: /settings\n"
- "Other commands (only game creator):\n"
- "/close - Close lobby\n"
- "/open - Open lobby\n"
- "/kill - Terminate the game\n"
- "/kick - Select a player to kick "
- "by replying to him or her\n"
- "/enable_translations - Translate relevant texts into all "
- "languages spoken in a game\n"
- "/disable_translations - Use English for those texts\n\n"
- "Experimental: Play in multiple groups at the same time. "
- "Press the Current game: ... button and select the "
- "group you want to play a card in.\n"
- "If you enjoy this bot, join the "
- 'update channel'
- " and buy an UNO card game.",
- )
-
- await send_async(
- update.message.chat,
- text=help_text,
- parse_mode=ParseMode.HTML,
- message_thread_id=update.message.message_thread_id,
- disable_web_page_preview=True,
- )
-
-
-@user_locale
-async def modes(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /help command."""
- modes_explanation = _(
- "This UNO bot has five game modes: Classic, Sanic, Wild, Text and 7-0.\n\n"
- " 🎻 The Classic mode uses the conventional UNO deck and there is no auto skip.\n"
- " 🚀 The Sanic mode uses the conventional UNO deck and the bot automatically skips a player if he/she takes too long to play its turn\n"
- " 🐉 The Wild mode uses a deck with more special cards, less number variety and no auto skip.\n"
- " ✍️ The Text mode uses the conventional UNO deck but instead of stickers it uses the text.\n"
- " 🔫 The 7-0 mode uses the conventional UNO deck but when a player plays a 7, he/she can choose a player to swap cards with."
- " When a player plays a 0, all cards will be swapped between the current players.\n\n"
- "To change the game mode, the GAME CREATOR has to type the bot nickname and a space, "
- "just like when playing a card, and all gamemode options should appear.",
- )
- await send_async(
- update.message.chat,
- text=modes_explanation,
- parse_mode=ParseMode.HTML,
- message_thread_id=update.message.message_thread_id,
- disable_web_page_preview=True,
- )
-
-
-@user_locale
-async def source(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /help command."""
- source_text = _(
- "This bot is Free Software and licensed under the AGPL. "
- "The code is available here: \n"
- "https://github.com/AmanoTeam/UnuRobot",
- )
- attributions = _(
- "Attributions:\n"
- "Draw icon by "
- 'Faithtoken\n'
- "Pass icon by "
- 'Delapouite\n'
- "Originals available on http://game-icons.net\n"
- "Icons edited by ɳick",
- )
-
- await send_async(
- update.message.chat,
- text=source_text + "\n" + attributions,
- parse_mode=ParseMode.HTML,
- message_thread_id=update.message.message_thread_id,
- disable_web_page_preview=True,
- )
-
-
-@user_locale
-async def news(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Handler for the /news command."""
- await send_async(
- update.message.chat,
- text=_("All news here: https://t.me/UnuRobotUpdates"),
- message_thread_id=update.message.message_thread_id,
- disable_web_page_preview=True,
- )
-
-
-@user_locale
-async def stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
- user = update.message.from_user
- chat = update.message.chat
- us = UserSetting.get(id=user.id)
- if not us or not us.stats:
- await send_async(
- chat,
- text=_(
- "You did not enable statistics. Use /settings in "
- "a private chat with the bot to enable them.",
- ),
- message_thread_id=update.message.message_thread_id,
- )
- else:
- n = us.games_played
- stats_text = [
- _("{number} game played", "{number} games played", n).format(number=n),
- ]
-
- n = us.first_places
- m = round((us.first_places / us.games_played) * 100) if us.games_played else 0
- stats_text.append(
- _(
- "{number} first place ({percent}%)",
- "{number} first places ({percent}%)",
- n,
- ).format(number=n, percent=m),
- )
-
- n = us.cards_played
- stats_text.append(
- _("{number} card played", "{number} cards played", n).format(number=n),
- )
-
- await send_async(
- chat,
- text="\n".join(stats_text),
- message_thread_id=update.message.message_thread_id,
- )
-
-
-def register():
- application.add_handler(CommandHandler("help", help_handler))
- application.add_handler(CommandHandler("source", source))
- application.add_handler(CommandHandler("news", news))
- application.add_handler(CommandHandler("stats", stats))
- application.add_handler(CommandHandler("modes", modes))
diff --git a/spetials/minimalist.py b/spetials/minimalist.py
new file mode 100644
index 0000000..a06af66
--- /dev/null
+++ b/spetials/minimalist.py
@@ -0,0 +1,32 @@
+from hydrogram import Client
+from hydrogram.types import ChosenInlineResult
+from hydrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
+from game import Game
+
+inline_keyb = InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Jogar", switch_inline_query_current_chat="")]]
+)
+
+
+async def mirror(c: Client, ir: ChosenInlineResult, game: Game):
+ if game.draw < 2:
+ await c.send_message(game.chat.id, "Você não pode descartar essa carta agora!")
+ return True
+ else:
+ print(game.last_card_2, game.last_card)
+ game.players[ir.from_user.id].total_cards += 1
+ ncard = ir.result_id.split("-")[2]
+ player = game.last_card_2["player"]
+ player = game.players[int(player)]
+ player.cards.extend(game.deck.draw(game.draw))
+ await c.send_message(
+ game.chat.id, f"{player.mention} comprou {game.draw} cartas!"
+ )
+ game.players[ir.from_user.id].cards.pop(int(ncard))
+ await c.send_message(
+ game.chat.id,
+ f"Próximo: {game.next_player.mention}",
+ reply_markup=inline_keyb,
+ )
+ game.draw = 0
+ return True
diff --git a/test/__init__.py b/test/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/test/test_game_manager.py b/test/test_game_manager.py
deleted file mode 100644
index d28349b..0000000
--- a/test/test_game_manager.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import unittest
-
-from telegram import Chat, User
-
-from errors import (
- AlreadyJoinedError,
- LobbyClosedError,
- NoGameInChatError,
- NotEnoughPlayersError,
-)
-from game_manager import GameManager
-
-
-class Test(unittest.TestCase):
- game = None
-
- def setUp(self):
- self.gm = GameManager()
-
- self.chat0 = Chat(0, "group")
- self.chat1 = Chat(1, "group")
- self.chat2 = Chat(2, "group")
-
- self.user0 = User(0, "user0", False)
- self.user1 = User(1, "user1", False)
- self.user2 = User(2, "user2", False)
-
- def test_new_game(self):
- g0 = self.gm.new_game(self.chat0)
- g1 = self.gm.new_game(self.chat1)
-
- self.assertListEqual(self.gm.chatid_games[0], [g0])
- self.assertListEqual(self.gm.chatid_games[1], [g1])
-
- def test_join_game(self):
- self.assertRaises(
- NoGameInChatError,
- self.gm.join_game,
- *(self.user0, self.chat0),
- )
-
- g0 = self.gm.new_game(self.chat0)
-
- self.gm.join_game(self.user0, self.chat0)
- assert len(g0.players) == 1
-
- self.gm.join_game(self.user1, self.chat0)
- assert len(g0.players) == 2
-
- g0.open = False
- self.assertRaises(
- LobbyClosedError,
- self.gm.join_game,
- *(self.user2, self.chat0),
- )
-
- g0.open = True
- self.assertRaises(
- AlreadyJoinedError,
- self.gm.join_game,
- *(self.user1, self.chat0),
- )
-
- def test_leave_game(self):
- self.start_and_join()
- self.assertRaises(
- NotEnoughPlayersError,
- self.gm.leave_game,
- *(self.user1, self.chat0),
- )
-
- self.gm.join_game(self.user2, self.chat0)
- self.gm.leave_game(self.user0, self.chat0)
-
- self.assertRaises(
- NoGameInChatError,
- self.gm.leave_game,
- *(self.user0, self.chat0),
- )
-
- def test_end_game(self):
- self.start_and_join()
- assert len(self.gm.userid_players[0]) == 1
-
- self.gm.new_game(self.chat0)
- self.gm.join_game(self.user2, self.chat0)
-
- self.gm.end_game(self.chat0, self.user0)
- assert len(self.gm.chatid_games[0]) == 1
-
- self.gm.end_game(self.chat0, self.user2)
- assert 0 not in self.gm.chatid_games
- assert 0 not in self.gm.userid_players
- assert 1 not in self.gm.userid_players
- assert 2 not in self.gm.userid_players
-
- def start_and_join(self):
- self.gm.new_game(self.chat0)
- self.gm.join_game(self.user0, self.chat0)
- self.gm.join_game(self.user1, self.chat0)
diff --git a/test/test_player.py b/test/test_player.py
deleted file mode 100644
index f32d21b..0000000
--- a/test/test_player.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import unittest
-
-import card as c
-from game import Game
-from player import Player
-
-
-class Test(unittest.TestCase):
- game = None
-
- def setUp(self):
- self.game = Game(None, None)
-
- def test_insert(self):
- p0 = Player(self.game, "Player 0")
- p1 = Player(self.game, "Player 1")
- p2 = Player(self.game, "Player 2")
-
- assert p0 == p2.next
- assert p1 == p0.next
- assert p2 == p1.next
-
- assert p0.prev == p2
- assert p1.prev == p0
- assert p2.prev == p1
-
- def test_reverse(self):
- p0 = Player(self.game, "Player 0")
- p1 = Player(self.game, "Player 1")
- p2 = Player(self.game, "Player 2")
- self.game.reverse()
- p3 = Player(self.game, "Player 3")
-
- assert p0 == p3.next
- assert p1 == p2.next
- assert p2 == p0.next
- assert p3 == p1.next
-
- assert p0 == p2.prev
- assert p1 == p3.prev
- assert p2 == p1.prev
- assert p3 == p0.prev
-
- def test_leave(self):
- p0 = Player(self.game, "Player 0")
- p1 = Player(self.game, "Player 1")
- p2 = Player(self.game, "Player 2")
-
- p1.leave()
-
- assert p0 == p2.next
- assert p2 == p0.next
-
- def test_draw(self):
- p = Player(self.game, "Player 0")
- self.game.start()
-
- deck_before = len(self.game.deck.cards)
- top_card = self.game.deck.cards[-1]
-
- p.draw()
-
- assert top_card == p.cards[-1]
- assert deck_before == len(self.game.deck.cards) + 1
-
- def test_draw_two(self):
- p = Player(self.game, "Player 0")
- self.game.start()
-
- deck_before = len(self.game.deck.cards)
- self.game.draw_counter = 2
-
- p.draw()
-
- assert deck_before == len(self.game.deck.cards) + 2
-
- def test_playable_cards_simple(self):
- p = Player(self.game, "Player 0")
-
- self.game.last_card = c.Card(c.RED, "5")
-
- p.cards = [
- c.Card(c.RED, "0"),
- c.Card(c.RED, "5"),
- c.Card(c.BLUE, "0"),
- c.Card(c.GREEN, "5"),
- c.Card(c.GREEN, "8"),
- ]
-
- expected = [c.Card(c.RED, "0"), c.Card(c.RED, "5"), c.Card(c.GREEN, "5")]
-
- self.assertListEqual(p.playable_cards(), expected)
-
- def test_playable_cards_on_draw_two(self):
- p = Player(self.game, "Player 0")
-
- self.game.last_card = c.Card(c.RED, c.DRAW_TWO)
- self.game.draw_counter = 2
-
- p.cards = [
- c.Card(c.RED, c.DRAW_TWO),
- c.Card(c.RED, "5"),
- c.Card(c.BLUE, "0"),
- c.Card(c.GREEN, "5"),
- c.Card(c.GREEN, c.DRAW_TWO),
- ]
-
- expected = [c.Card(c.RED, c.DRAW_TWO), c.Card(c.GREEN, c.DRAW_TWO)]
-
- self.assertListEqual(p.playable_cards(), expected)
-
- def test_playable_cards_on_draw_four(self):
- p = Player(self.game, "Player 0")
-
- self.game.last_card = c.Card(c.RED, None, c.DRAW_FOUR)
- self.game.draw_counter = 4
-
- p.cards = [
- c.Card(c.RED, c.DRAW_TWO),
- c.Card(c.RED, "5"),
- c.Card(c.BLUE, "0"),
- c.Card(c.GREEN, "5"),
- c.Card(c.GREEN, c.DRAW_TWO),
- c.Card(None, None, c.DRAW_FOUR),
- c.Card(None, None, c.CHOOSE),
- ]
-
- expected = []
-
- self.assertListEqual(p.playable_cards(), expected)
-
- def test_bluffing(self):
- p = Player(self.game, "Player 0")
- Player(self.game, "Player 01")
-
- self.game.last_card = c.Card(c.RED, "1")
-
- p.cards = [
- c.Card(c.RED, c.DRAW_TWO),
- c.Card(c.RED, "5"),
- c.Card(c.BLUE, "0"),
- c.Card(c.GREEN, "5"),
- c.Card(c.RED, "5"),
- c.Card(c.GREEN, c.DRAW_TWO),
- c.Card(None, None, c.DRAW_FOUR),
- c.Card(None, None, c.CHOOSE),
- ]
-
- p.playable_cards()
- assert p.bluffing
-
- p.cards = [
- c.Card(c.BLUE, "1"),
- c.Card(c.GREEN, "1"),
- c.Card(c.GREEN, c.DRAW_TWO),
- c.Card(None, None, c.DRAW_FOUR),
- c.Card(None, None, c.CHOOSE),
- ]
-
- p.playable_cards()
-
- p.play(c.Card(None, None, c.DRAW_FOUR))
- self.game.choose_color(c.GREEN)
-
- assert not self.game.current_player.prev.bluffing
diff --git a/user_setting.py b/user_setting.py
deleted file mode 100644
index b8cf059..0000000
--- a/user_setting.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-from pony.orm import Optional, PrimaryKey
-
-from database import db
-
-
-class UserSetting(db.Entity):
- id = PrimaryKey(int, auto=False, size=64) # Telegram User ID
- lang = Optional(str, default="") # The language setting for this user
- stats = Optional(bool, default=False) # Opt-in to keep game statistics
- first_places = Optional(int, default=0) # Nr. of games won in first place
- games_played = Optional(int, default=0) # Nr. of games completed
- cards_played = Optional(int, default=0) # Nr. of cards played total
- use_keyboards = Optional(bool, default=False) # Use keyboards (unused)
diff --git a/utils.py b/utils.py
deleted file mode 100644
index e99e426..0000000
--- a/utils.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Telegram bot to play UNO in group chats
-# Copyright (c) 2016 Jannes Höke
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero 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 Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import logging
-from typing import Union
-
-from telegram import Chat, Update, User
-from telegram.ext import ContextTypes
-
-from game import Game
-from internationalization import _, __
-from mwt import MWT
-from shared_vars import gm
-
-logger = logging.getLogger(__name__)
-
-TIMEOUT = 2.5
-
-
-def list_subtract(list1, list2):
- """Helper function to subtract two lists and return the sorted result."""
- list1 = list1.copy()
-
- for x in list2:
- list1.remove(x)
-
- return sorted(list1)
-
-
-def display_name(user):
- """Get the current players name including their username, if possible."""
- user_name = user.first_name
- if user.username:
- user_name += f" (@{user.username})"
- return user_name
-
-
-def display_color(color):
- """Convert a color code to actual color name."""
- if color == "r":
- return _("{emoji} Red").format(emoji="❤️")
- if color == "b":
- return _("{emoji} Blue").format(emoji="💙")
- if color == "g":
- return _("{emoji} Green").format(emoji="💚")
- if color == "y":
- return _("{emoji} Yellow").format(emoji="💛")
- return None
-
-
-def display_color_group(color, game):
- """Convert a color code to actual color name."""
- if color == "r":
- return __("{emoji} Red", game.translate).format(emoji="❤️")
- if color == "b":
- return __("{emoji} Blue", game.translate).format(emoji="💙")
- if color == "g":
- return __("{emoji} Green", game.translate).format(emoji="💚")
- if color == "y":
- return __("{emoji} Yellow", game.translate).format(emoji="💛")
- return None
-
-
-async def error(update: Update, context: ContextTypes.DEFAULT_TYPE):
- """Simple error handler."""
- if isinstance(context, Exception):
- logger.exception(context)
- else:
- logger.exception(context.error)
-
-
-async def send_async(context: Union[Game, Chat, User], *args, **kwargs):
- """Send a message asynchronously."""
- if isinstance(context, Game) and not kwargs.get("message_thread_id"):
- kwargs["message_thread_id"] = context.thread_id
-
- chat = context.chat if isinstance(context, Game) else context
- try:
- await chat.send_message(*args, **kwargs)
- except Exception as e:
- await error(None, e)
-
-
-async def answer_async(context: ContextTypes.DEFAULT_TYPE, *args, **kwargs):
- """Answer an inline query asynchronously."""
- try:
- await context.bot.answer_inline_query(*args, **kwargs)
- except Exception as e:
- await error(None, e)
-
-
-def game_is_running(game):
- return game in gm.chatid_games.get(game.chat.id, [])
-
-
-def user_is_creator(user, game):
- return user.id in game.owner
-
-
-async def user_is_admin(user, context, chat):
- return user.id in await get_admin_ids(context, chat.id)
-
-
-async def user_is_creator_or_admin(user, game, context, chat):
- return user_is_creator(user, game) or await user_is_admin(user, context, chat)
-
-
-@MWT(timeout=60 * 60)
-async def get_admin_ids(context, chat_id):
- """Returns a list of admin IDs for a given chat. Results are cached for 1 hour."""
- return [
- admin.user.id for admin in await context.bot.get_chat_administrators(chat_id)
- ]
diff --git a/version.py b/version.py
new file mode 100644
index 0000000..9f715b1
--- /dev/null
+++ b/version.py
@@ -0,0 +1,13 @@
+version = "1.0.0-beta"
+
+ascii_art = f""" ___ ___ ___
+ /\\__\\ /\\__\\ /\\__\\
+ /:/ _/_ /:| _|_ /:/ _/_
+ /:/_/\\__\\ /::|/\\__\\ /:/_/\\__\\
+ \\:\\/:/ / \\/|::/ / \\:\\/:/ /
+ \\::/ / |:/ / \\::/ / _ _ |_ _ |_
+ \\/__/ \\/__/ \\/__/ | (_)|_)(_)|_
+
+ Version: {version} - Powered by Hydrogram
+
+"""