diff --git a/.github/issue_template.md b/.github/issue_template.md
deleted file mode 100644
index a2f9aff..0000000
--- a/.github/issue_template.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: bug
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Launch bot
-3. Type command '...'
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Desktop (please complete the following information):**
- - OS: [e.g. Debian]
- - Python Version [e.g. 3.7.4]
-
-**Additional context**
-Add any other context about the problem here.
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 45b11a6..02ae0be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,146 +1,12 @@
-#Python
-__pycache__/
-*.pyc
-.env
-configs/config.cfg
-configs/prefixes.cfg
-configs/fallbacks.cfg
-.DS_Store
-private.py
-
-#jetbrains
-.idea/
-
-# other
-logs/tuxbot.log
-utils/images/tmp/*
-
-# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-pip-wheel-metadata/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-.python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
venv/
-ENV/
-env.bak/
-venv.bak/
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
+settings.py
\ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..368d7c1
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..f031c4e
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..4941e09
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..dd59735
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/tuxbot-bot-rewrite.iml b/.idea/tuxbot-bot-rewrite.iml
new file mode 100644
index 0000000..74d515a
--- /dev/null
+++ b/.idea/tuxbot-bot-rewrite.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..78cface
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..5210e9e
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,199 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1589922546510
+
+
+ 1589991138014
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100755
index d60efe4..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,437 +0,0 @@
-Attribution-NonCommercial-ShareAlike 4.0 International
-
-=======================================================================
-
-Creative Commons Corporation ("Creative Commons") is not a law firm and
-does not provide legal services or legal advice. Distribution of
-Creative Commons public licenses does not create a lawyer-client or
-other relationship. Creative Commons makes its licenses and related
-information available on an "as-is" basis. Creative Commons gives no
-warranties regarding its licenses, any material licensed under their
-terms and conditions, or any related information. Creative Commons
-disclaims all liability for damages resulting from their use to the
-fullest extent possible.
-
-Using Creative Commons Public Licenses
-
-Creative Commons public licenses provide a standard set of terms and
-conditions that creators and other rights holders may use to share
-original works of authorship and other material subject to copyright
-and certain other rights specified in the public license below. The
-following considerations are for informational purposes only, are not
-exhaustive, and do not form part of our licenses.
-
- Considerations for licensors: Our public licenses are
- intended for use by those authorized to give the public
- permission to use material in ways otherwise restricted by
- copyright and certain other rights. Our licenses are
- irrevocable. Licensors should read and understand the terms
- and conditions of the license they choose before applying it.
- Licensors should also secure all rights necessary before
- applying our licenses so that the public can reuse the
- material as expected. Licensors should clearly mark any
- material not subject to the license. This includes other CC-
- licensed material, or material used under an exception or
- limitation to copyright. More considerations for licensors:
- wiki.creativecommons.org/Considerations_for_licensors
-
- Considerations for the public: By using one of our public
- licenses, a licensor grants the public permission to use the
- licensed material under specified terms and conditions. If
- the licensor's permission is not necessary for any reason--for
- example, because of any applicable exception or limitation to
- copyright--then that use is not regulated by the license. Our
- licenses grant only permissions under copyright and certain
- other rights that a licensor has authority to grant. Use of
- the licensed material may still be restricted for other
- reasons, including because others have copyright or other
- rights in the material. A licensor may make special requests,
- such as asking that all changes be marked or described.
- Although not required by our licenses, you are encouraged to
- respect those requests where reasonable. More_considerations
- for the public:
- wiki.creativecommons.org/Considerations_for_licensees
-
-=======================================================================
-
-Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
-Public License
-
-By exercising the Licensed Rights (defined below), You accept and agree
-to be bound by the terms and conditions of this Creative Commons
-Attribution-NonCommercial-ShareAlike 4.0 International Public License
-("Public License"). To the extent this Public License may be
-interpreted as a contract, You are granted the Licensed Rights in
-consideration of Your acceptance of these terms and conditions, and the
-Licensor grants You such rights in consideration of benefits the
-Licensor receives from making the Licensed Material available under
-these terms and conditions.
-
-
-Section 1 -- Definitions.
-
- a. Adapted Material means material subject to Copyright and Similar
- Rights that is derived from or based upon the Licensed Material
- and in which the Licensed Material is translated, altered,
- arranged, transformed, or otherwise modified in a manner requiring
- permission under the Copyright and Similar Rights held by the
- Licensor. For purposes of this Public License, where the Licensed
- Material is a musical work, performance, or sound recording,
- Adapted Material is always produced where the Licensed Material is
- synched in timed relation with a moving image.
-
- b. Adapter's License means the license You apply to Your Copyright
- and Similar Rights in Your contributions to Adapted Material in
- accordance with the terms and conditions of this Public License.
-
- c. BY-NC-SA Compatible License means a license listed at
- creativecommons.org/compatiblelicenses, approved by Creative
- Commons as essentially the equivalent of this Public License.
-
- d. Copyright and Similar Rights means copyright and/or similar rights
- closely related to copyright including, without limitation,
- performance, broadcast, sound recording, and Sui Generis Database
- Rights, without regard to how the rights are labeled or
- categorized. For purposes of this Public License, the rights
- specified in Section 2(b)(1)-(2) are not Copyright and Similar
- Rights.
-
- e. Effective Technological Measures means those measures that, in the
- absence of proper authority, may not be circumvented under laws
- fulfilling obligations under Article 11 of the WIPO Copyright
- Treaty adopted on December 20, 1996, and/or similar international
- agreements.
-
- f. Exceptions and Limitations means fair use, fair dealing, and/or
- any other exception or limitation to Copyright and Similar Rights
- that applies to Your use of the Licensed Material.
-
- g. License Elements means the license attributes listed in the name
- of a Creative Commons Public License. The License Elements of this
- Public License are Attribution, NonCommercial, and ShareAlike.
-
- h. Licensed Material means the artistic or literary work, database,
- or other material to which the Licensor applied this Public
- License.
-
- i. Licensed Rights means the rights granted to You subject to the
- terms and conditions of this Public License, which are limited to
- all Copyright and Similar Rights that apply to Your use of the
- Licensed Material and that the Licensor has authority to license.
-
- j. Licensor means the individual(s) or entity(ies) granting rights
- under this Public License.
-
- k. NonCommercial means not primarily intended for or directed towards
- commercial advantage or monetary compensation. For purposes of
- this Public License, the exchange of the Licensed Material for
- other material subject to Copyright and Similar Rights by digital
- file-sharing or similar means is NonCommercial provided there is
- no payment of monetary compensation in connection with the
- exchange.
-
- l. Share means to provide material to the public by any means or
- process that requires permission under the Licensed Rights, such
- as reproduction, public display, public performance, distribution,
- dissemination, communication, or importation, and to make material
- available to the public including in ways that members of the
- public may access the material from a place and at a time
- individually chosen by them.
-
- m. Sui Generis Database Rights means rights other than copyright
- resulting from Directive 96/9/EC of the European Parliament and of
- the Council of 11 March 1996 on the legal protection of databases,
- as amended and/or succeeded, as well as other essentially
- equivalent rights anywhere in the world.
-
- n. You means the individual or entity exercising the Licensed Rights
- under this Public License. Your has a corresponding meaning.
-
-
-Section 2 -- Scope.
-
- a. License grant.
-
- 1. Subject to the terms and conditions of this Public License,
- the Licensor hereby grants You a worldwide, royalty-free,
- non-sublicensable, non-exclusive, irrevocable license to
- exercise the Licensed Rights in the Licensed Material to:
-
- a. reproduce and Share the Licensed Material, in whole or
- in part, for NonCommercial purposes only; and
-
- b. produce, reproduce, and Share Adapted Material for
- NonCommercial purposes only.
-
- 2. Exceptions and Limitations. For the avoidance of doubt, where
- Exceptions and Limitations apply to Your use, this Public
- License does not apply, and You do not need to comply with
- its terms and conditions.
-
- 3. Term. The term of this Public License is specified in Section
- 6(a).
-
- 4. Media and formats; technical modifications allowed. The
- Licensor authorizes You to exercise the Licensed Rights in
- all media and formats whether now known or hereafter created,
- and to make technical modifications necessary to do so. The
- Licensor waives and/or agrees not to assert any right or
- authority to forbid You from making technical modifications
- necessary to exercise the Licensed Rights, including
- technical modifications necessary to circumvent Effective
- Technological Measures. For purposes of this Public License,
- simply making modifications authorized by this Section 2(a)
- (4) never produces Adapted Material.
-
- 5. Downstream recipients.
-
- a. Offer from the Licensor -- Licensed Material. Every
- recipient of the Licensed Material automatically
- receives an offer from the Licensor to exercise the
- Licensed Rights under the terms and conditions of this
- Public License.
-
- b. Additional offer from the Licensor -- Adapted Material.
- Every recipient of Adapted Material from You
- automatically receives an offer from the Licensor to
- exercise the Licensed Rights in the Adapted Material
- under the conditions of the Adapter's License You apply.
-
- c. No downstream restrictions. You may not offer or impose
- any additional or different terms or conditions on, or
- apply any Effective Technological Measures to, the
- Licensed Material if doing so restricts exercise of the
- Licensed Rights by any recipient of the Licensed
- Material.
-
- 6. No endorsement. Nothing in this Public License constitutes or
- may be construed as permission to assert or imply that You
- are, or that Your use of the Licensed Material is, connected
- with, or sponsored, endorsed, or granted official status by,
- the Licensor or others designated to receive attribution as
- provided in Section 3(a)(1)(A)(i).
-
- b. Other rights.
-
- 1. Moral rights, such as the right of integrity, are not
- licensed under this Public License, nor are publicity,
- privacy, and/or other similar personality rights; however, to
- the extent possible, the Licensor waives and/or agrees not to
- assert any such rights held by the Licensor to the limited
- extent necessary to allow You to exercise the Licensed
- Rights, but not otherwise.
-
- 2. Patent and trademark rights are not licensed under this
- Public License.
-
- 3. To the extent possible, the Licensor waives any right to
- collect royalties from You for the exercise of the Licensed
- Rights, whether directly or through a collecting society
- under any voluntary or waivable statutory or compulsory
- licensing scheme. In all other cases the Licensor expressly
- reserves any right to collect such royalties, including when
- the Licensed Material is used other than for NonCommercial
- purposes.
-
-
-Section 3 -- License Conditions.
-
-Your exercise of the Licensed Rights is expressly made subject to the
-following conditions.
-
- a. Attribution.
-
- 1. If You Share the Licensed Material (including in modified
- form), You must:
-
- a. retain the following if it is supplied by the Licensor
- with the Licensed Material:
-
- i. identification of the creator(s) of the Licensed
- Material and any others designated to receive
- attribution, in any reasonable manner requested by
- the Licensor (including by pseudonym if
- designated);
-
- ii. a copyright notice;
-
- iii. a notice that refers to this Public License;
-
- iv. a notice that refers to the disclaimer of
- warranties;
-
- v. a URI or hyperlink to the Licensed Material to the
- extent reasonably practicable;
-
- b. indicate if You modified the Licensed Material and
- retain an indication of any previous modifications; and
-
- c. indicate the Licensed Material is licensed under this
- Public License, and include the text of, or the URI or
- hyperlink to, this Public License.
-
- 2. You may satisfy the conditions in Section 3(a)(1) in any
- reasonable manner based on the medium, means, and context in
- which You Share the Licensed Material. For example, it may be
- reasonable to satisfy the conditions by providing a URI or
- hyperlink to a resource that includes the required
- information.
- 3. If requested by the Licensor, You must remove any of the
- information required by Section 3(a)(1)(A) to the extent
- reasonably practicable.
-
- b. ShareAlike.
-
- In addition to the conditions in Section 3(a), if You Share
- Adapted Material You produce, the following conditions also apply.
-
- 1. The Adapter's License You apply must be a Creative Commons
- license with the same License Elements, this version or
- later, or a BY-NC-SA Compatible License.
-
- 2. You must include the text of, or the URI or hyperlink to, the
- Adapter's License You apply. You may satisfy this condition
- in any reasonable manner based on the medium, means, and
- context in which You Share Adapted Material.
-
- 3. You may not offer or impose any additional or different terms
- or conditions on, or apply any Effective Technological
- Measures to, Adapted Material that restrict exercise of the
- rights granted under the Adapter's License You apply.
-
-
-Section 4 -- Sui Generis Database Rights.
-
-Where the Licensed Rights include Sui Generis Database Rights that
-apply to Your use of the Licensed Material:
-
- a. for the avoidance of doubt, Section 2(a)(1) grants You the right
- to extract, reuse, reproduce, and Share all or a substantial
- portion of the contents of the database for NonCommercial purposes
- only;
-
- b. if You include all or a substantial portion of the database
- contents in a database in which You have Sui Generis Database
- Rights, then the database in which You have Sui Generis Database
- Rights (but not its individual contents) is Adapted Material,
- including for purposes of Section 3(b); and
-
- c. You must comply with the conditions in Section 3(a) if You Share
- all or a substantial portion of the contents of the database.
-
-For the avoidance of doubt, this Section 4 supplements and does not
-replace Your obligations under this Public License where the Licensed
-Rights include other Copyright and Similar Rights.
-
-
-Section 5 -- Disclaimer of Warranties and Limitation of Liability.
-
- a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
- EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
- AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
- ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
- IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
- WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
- PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
- ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
- KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
- ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
-
- b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
- TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
- NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
- INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
- COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
- USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
- DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
- IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
-
- c. The disclaimer of warranties and limitation of liability provided
- above shall be interpreted in a manner that, to the extent
- possible, most closely approximates an absolute disclaimer and
- waiver of all liability.
-
-
-Section 6 -- Term and Termination.
-
- a. This Public License applies for the term of the Copyright and
- Similar Rights licensed here. However, if You fail to comply with
- this Public License, then Your rights under this Public License
- terminate automatically.
-
- b. Where Your right to use the Licensed Material has terminated under
- Section 6(a), it reinstates:
-
- 1. automatically as of the date the violation is cured, provided
- it is cured within 30 days of Your discovery of the
- violation; or
-
- 2. upon express reinstatement by the Licensor.
-
- For the avoidance of doubt, this Section 6(b) does not affect any
- right the Licensor may have to seek remedies for Your violations
- of this Public License.
-
- c. For the avoidance of doubt, the Licensor may also offer the
- Licensed Material under separate terms or conditions or stop
- distributing the Licensed Material at any time; however, doing so
- will not terminate this Public License.
-
- d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
- License.
-
-
-Section 7 -- Other Terms and Conditions.
-
- a. The Licensor shall not be bound by any additional or different
- terms or conditions communicated by You unless expressly agreed.
-
- b. Any arrangements, understandings, or agreements regarding the
- Licensed Material not stated herein are separate from and
- independent of the terms and conditions of this Public License.
-
-
-Section 8 -- Interpretation.
-
- a. For the avoidance of doubt, this Public License does not, and
- shall not be interpreted to, reduce, limit, restrict, or impose
- conditions on any use of the Licensed Material that could lawfully
- be made without permission under this Public License.
-
- b. To the extent possible, if any provision of this Public License is
- deemed unenforceable, it shall be automatically reformed to the
- minimum extent necessary to make it enforceable. If the provision
- cannot be reformed, it shall be severed from this Public License
- without affecting the enforceability of the remaining terms and
- conditions.
-
- c. No term or condition of this Public License will be waived and no
- failure to comply consented to unless expressly agreed to by the
- Licensor.
-
- d. Nothing in this Public License constitutes or may be interpreted
- as a limitation upon, or waiver of, any privileges and immunities
- that apply to the Licensor or You, including from the legal
- processes of any jurisdiction or authority.
-
-=======================================================================
-
-Creative Commons is not a party to its public
-licenses. Notwithstanding, Creative Commons may elect to apply one of
-its public licenses to material it publishes and in those instances
-will be considered the “Licensor.” The text of the Creative Commons
-public licenses is dedicated to the public domain under the CC0 Public
-Domain Dedication. Except for the limited purpose of indicating that
-material is shared under a Creative Commons public license or as
-otherwise permitted by the Creative Commons policies published at
-creativecommons.org/policies, Creative Commons does not authorize the
-use of the trademark "Creative Commons" or any other trademark or logo
-of Creative Commons without its prior written consent including,
-without limitation, in connection with any unauthorized modifications
-to any of its public licenses or any other arrangements,
-understandings, or agreements concerning use of licensed material. For
-the avoidance of doubt, this paragraph does not form part of the
-public licenses.
-
-Creative Commons may be contacted at creativecommons.org.
diff --git a/README.md b/README.md
deleted file mode 100644
index b543613..0000000
--- a/README.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# News
-
- - [ ] i18n for messages
- - [x] Custom prefixes
- - [ ] Better help command
- - [ ] Alias system for commands (e.g. `.alias .ci show .cs`)
- - [x] Migrate MySQL to postgresql
- - [x] Prepare bot for python 3.8 and discord.py 1.3.0
- - [ ] Create launcher
- - [ ] Create documentation
-
-## Launcher requirements :
-
- - [ ] Can install the bot
- - [ ] Can launch the bot
- - [ ] Can propose updates
-
-## New commands :
-
- - [x] `.sondage --anonyme <...>` (create à sondage with the possibility of answering anonymously)
- - [ ] `.sondage --edit ` (edit a sondage if we are the author or an admin)
-
-## Documentation:
- - [ ] How to use ?
- - [ ] How to add more commands ?
-
-## Ultimate :
-
- - [ ] Send email or Telegram's message when something is wrong on the bot
- - [ ] Create skynet (group of multiple commands about sky (planes, meteo, AI,...))
-
- ---
-
- # Cogs.admin commands
-
- - [x] upload `removed`, cause : `never used`
- - [x] ban
- - [x] kick
- - [x] clear
- - [x] say
- - [x] sayto `removed`, now : `say to`
- - [x] sayto_dm `removed`, now : `say to`
- - [x] editsay `removed`, now : `say edit`
- - [x] addreaction `renamed`, now `react add`
- - [x] delete
- - [x] deletefrom `removed`, now `delete (from|to|in)`
- - [x] embed `removed`, cause : `never used`
- - [x] warn `new command`
-
- ---
-
- # Cogs.basics commands
- - [x] ping
- - [x] info
- - [ ] help
- - [x] credits `new command`
-
- ---
-
- # Cogs.ci commands `canceled until the frontend development`
- - [ ] ci (help?)
- - [ ] ci show
- - [ ] ci register
- - [ ] ci delete
- - [ ] ci update
- - [ ] ci setconfig
- - [ ] ci setos
- - [ ] ci setcountry
- - [ ] ci online_edit `renamed`, cause : `website down`
- - [ ] ci list
-
- ---
-
- # Cogs.utility commands
- - [ ] clock `removed` ?
- - [ ] clock * `removed` ?
- - [ ] ytdiscover `removed` ?
- - [x] iplocalise
- - [x] getheaders
- - [x] git
- - [x] quote
-
- ---
-
- # Cogs.sondage commands `(renamed as cogs.poll)` `canceled until the frontend development`
- - [ ] sondage (help?)
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..97376fc
--- /dev/null
+++ b/app.py
@@ -0,0 +1,151 @@
+import contextlib
+import datetime
+import logging
+from collections import Counter
+from typing import List
+
+import aiohttp
+import discord
+from discord.ext import commands
+from tortoise import Tortoise
+
+from configs.bot import settings
+from utils.functions.extra import ContextPlus, get_prefix, \
+ get_owners, get_blacklist
+
+log = logging.getLogger(__name__)
+
+l_extensions: List[str] = [
+ "jishaku",
+ "cogs.Logs",
+ "cogs.Images",
+]
+
+
+class TuxBot(commands.AutoShardedBot):
+ logs_channels: dict
+ session: aiohttp.ClientSession
+ command_stats: Counter = Counter()
+ socket_stats: Counter = Counter()
+
+ def __init__(self):
+ self.uptime = datetime.datetime.utcnow()
+ self.config = settings
+ super().__init__(
+ command_prefix=get_prefix,
+ case_insensitive=True
+ )
+
+ self.logs_channels = {
+ "dm": self.config.logs["dm"],
+ "mentions": self.config.logs["mentions"],
+ "guilds": self.config.logs["guilds"],
+ "errors": self.config.logs["errors"],
+ }
+
+ print("\n"*2)
+
+ for extension in l_extensions:
+ try:
+ self.load_extension(extension)
+ print(f"{extension} loaded !")
+ except Exception as e:
+ print(f"{type(e).__name__}: {e}")
+
+ print("\n"*2)
+
+ async def is_owner(self, user: discord.User):
+ return user.id in get_owners()
+
+ async def on_ready(self):
+ print(f"Connected !\n"
+ f"\n"
+ f"==> info: bot username {self.user}\n"
+ f" info: bot id {self.user.id}\n"
+ f" info: bot prefix {self.command_prefix}\n"
+ f"==> info: guild count {len(self.guilds)}\n"
+ f" info: member count {len(list(self.get_all_members()))}\n"
+ f" info: channel count {len(list(self.get_all_channels()))}")
+
+ print(f"\n{'='*118}\n\n")
+
+ @staticmethod
+ async def on_resumed():
+ print("resumed...")
+
+ async def get_context(self, message: discord.Message, *, cls=None):
+ return await super().get_context(message, cls=ContextPlus)
+
+ async def on_message(self, message: discord.Message):
+ if message.author.bot:
+ return
+
+ if message.author.id in get_blacklist()['users'] \
+ or message.channel.id in get_blacklist()['channels'] \
+ or (message.channel.guild
+ and message.channel.guild.id in get_blacklist()['guilds']):
+ return
+
+ try:
+ await self.process_commands(message)
+ except Exception as e:
+ print(f"{type(e).__name__}: {e}")
+
+ async def bot_logout(self):
+ await super().logout()
+ await self.session.close()
+
+ async def bot_start(self):
+ self.session = aiohttp.ClientSession(loop=self.loop)
+ await self.login(self.config.token, bot=True)
+ await self.connect()
+
+ def run(self):
+ loop = self.loop
+
+ loop.run_until_complete(Tortoise.init(
+ db_url=self.config.postgresql,
+ modules={
+ "models": [
+ "models.__init__"
+ ]
+ }
+ ))
+ loop.run_until_complete(Tortoise.generate_schemas())
+
+ try:
+ loop.run_until_complete(self.bot_start())
+ except KeyboardInterrupt:
+ loop.run_until_complete(self.bot_logout())
+
+
+@contextlib.contextmanager
+def setup_logging():
+ logging.getLogger('discord').setLevel(logging.INFO)
+ logging.getLogger('discord.http').setLevel(logging.WARNING)
+
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+
+ try:
+ handler = logging.FileHandler(filename='logs/tuxbot.log',
+ encoding='utf-8', mode='w')
+ fmt = logging.Formatter('[{levelname:<7}] [{asctime}]'
+ ' {name}: {message}',
+ '%Y-%m-%d %H:%M:%S', style='{')
+
+ handler.setFormatter(fmt)
+ logger.addHandler(handler)
+
+ yield
+ finally:
+ handlers = logger.handlers[:]
+ for handler in handlers:
+ handler.close()
+ logger.removeHandler(handler)
+
+
+if __name__ == "__main__":
+ tutux = TuxBot()
+ with setup_logging():
+ tutux.run()
diff --git a/bot.py b/bot.py
deleted file mode 100755
index 74e18ba..0000000
--- a/bot.py
+++ /dev/null
@@ -1,250 +0,0 @@
-import contextlib
-import datetime
-import json
-import logging
-import sys
-from collections import deque, Counter
-from typing import List
-
-import aiohttp
-import discord
-import git
-import sqlalchemy
-from discord.ext import commands
-
-from utils.functions import Config
-from utils.functions import Texts
-from utils.functions import Version
-from utils.functions import ContextPlus
-
-from utils.models import metadata, database
-
-description = """
-Je suis TuxBot, le bot qui vit de l'OpenSource ! ;)
-"""
-
-build = git.Repo(search_parent_directories=True).head.object.hexsha
-version = (2, 0, 0)
-
-log = logging.getLogger(__name__)
-
-l_extensions: List[str] = [
- 'cogs.Admin',
- 'cogs.API',
- 'cogs.Help',
- 'cogs.Logs',
- # 'cogs.Monitoring',
- 'cogs.Poll',
- 'cogs.Useful',
- 'cogs.User',
- 'jishaku',
-]
-
-
-async def _prefix_callable(bot, message: discord.message) -> list:
-<<<<<<< HEAD
- extras = [bot.cluster.get('Name') + '.']
- if message.guild is not None:
- if str(message.guild.id) in bot.prefixes:
- extras.extend(
- bot.prefixes.get(str(message.guild.id), "prefixes").split(
- bot.config.get("misc", "Separator")
- )
- )
-=======
- try:
- with open(f'./configs/guilds/{message.guild.id}.json', 'r') as f:
- data = json.load(f)
-
- custom_prefix = data['prefixes']
- except FileNotFoundError:
- custom_prefix = ['']
-
- extras = [bot.cluster.get('Name') + '.']
- extras.extend(custom_prefix)
->>>>>>> cce7bb409303e9ad27ef4e5617d0bc9068810f13
-
- return commands.when_mentioned_or(*extras)(bot, message)
-
-
-class TuxBot(commands.AutoShardedBot):
-
- def __init__(self, ):
- super().__init__(command_prefix=_prefix_callable, pm_help=None,
- help_command=None, description=description,
- help_attrs=dict(hidden=True),
- activity=discord.Game(
- name=Texts().get('Starting...'))
- )
-
- self.socket_stats = Counter()
- self.command_stats = Counter()
-
- self.config = Config('./configs/config.cfg')
- self.blacklist = Config('./configs/blacklist.cfg')
- self.fallbacks = Config('./configs/fallbacks.cfg')
- self.cluster = self.fallbacks.find('True', key='This', first=True)
-
- self.uptime: datetime = datetime.datetime.utcnow()
- self._prev_events = deque(maxlen=10)
- self.session = aiohttp.ClientSession(loop=self.loop)
-
- self.database, self.metadata = database, metadata
- self.engine = sqlalchemy.create_engine(str(self.database.url))
- self.metadata.create_all(self.engine)
-
- self.version = Version(*version, pre_release='rc2', build=build)
- self.owners_id = [int(owner_id) for owner_id in self.config.get('permissions', 'Owners').split(', ')]
- self.owner_id = int(self.owners_id[0])
-
- for extension in l_extensions:
- try:
- self.load_extension(extension)
- print(Texts().get("Extension loaded successfully : ")
- + extension)
- log.info(Texts().get("Extension loaded successfully : ")
- + extension)
- except Exception as e:
- print(Texts().get("Failed to load extension : ")
- + extension, file=sys.stderr)
- print(e)
- log.error(Texts().get("Failed to load extension : ")
- + extension, exc_info=e)
-
- @property
- def owner(self):
- return self.get_user(self.owner_id)
-
- @property
- def owners(self):
- return [self.get_user(owner_id) for owner_id in self.owners_id]
-
- async def is_owner(self, user: discord.User) -> bool:
- return user in self.owners
-
- async def get_context(self, message, *, cls=None):
- return await super().get_context(message, cls=cls or ContextPlus)
-
- async def on_socket_response(self, msg):
- self._prev_events.append(msg)
-
- async def on_command_error(self, ctx: discord.ext.commands.Context, error):
- if isinstance(error, commands.NoPrivateMessage):
- await ctx.author.send(
- Texts().get("This command cannot be used in private messages.")
- )
-
- elif isinstance(error, commands.DisabledCommand):
- await ctx.author.send(
- Texts().get(
- "Sorry. This command is disabled and cannot be used."
- )
- )
- elif isinstance(error, commands.CommandOnCooldown):
- await ctx.send(str(error))
-
- async def process_commands(self, message: discord.message):
- ctx: commands.Context = await self.get_context(message)
-
- if ctx.command is None:
- return
-
- await self.invoke(ctx)
-
- async def on_message(self, message: discord.message):
- if message.author.id in self.blacklist \
- or (message.guild is not None
- and message.guild.id in self.blacklist):
- return
-
- if message.author.bot and message.author.id != int(
- self.config.get('bot', 'Tester')):
- return
-
- await self.process_commands(message)
-
- async def on_ready(self):
- if not hasattr(self, 'uptime'):
- self.uptime = datetime.datetime.utcnow()
-
- print('-' * 60)
- print(Texts().get("Ready:") + f' {self.user} (ID: {self.user.id})')
- print(self.version)
-
- presence: dict = dict(status=discord.Status.dnd)
- if self.config.get("bot", "Activity", fallback=None) is not None:
- presence.update(
- activity=discord.Game(
- name=self.config.get("bot", "Activity")
- )
- )
- print(f"Discord.py: {discord.__version__}")
- print(f"Server: {self.cluster.get('Name')}")
- print('-' * 60)
-
- await self.change_presence(**presence)
-
- @staticmethod
- async def on_resumed():
- print('resumed...')
-
- @property
- def logs_webhook(self) -> discord.Webhook:
- webhook_config = self.config["webhook"]
- webhook = discord.Webhook.partial(
- id=webhook_config.get('ID'),
- token=webhook_config.get('Token'),
- adapter=discord.AsyncWebhookAdapter(
- self.session
- )
- )
-
- return webhook
-
- async def close(self):
- extensions = self.extensions.copy()
- for extension in extensions:
- self.unload_extension(extension)
- await super().close()
- await self.session.close()
-
- def run(self):
- super().run(self.config.get("bot", "Token"), reconnect=True)
-
-
-@contextlib.contextmanager
-def setup_logging():
- logging.getLogger('discord').setLevel(logging.INFO)
- logging.getLogger('discord.http').setLevel(logging.WARNING)
-
- log = logging.getLogger()
- log.setLevel(logging.INFO)
-
- try:
- handler = logging.FileHandler(filename='logs/tuxbot.log',
- encoding='utf-8', mode='w')
- fmt = logging.Formatter('[{levelname:<7}] [{asctime}]'
- ' {name}: {message}',
- '%Y-%m-%d %H:%M:%S', style='{')
-
- handler.setFormatter(fmt)
- log.addHandler(handler)
-
- yield
- finally:
- handlers = log.handlers[:]
- for handler in handlers:
- handler.close()
- log.removeHandler(handler)
-
-
-if __name__ == "__main__":
- print(Texts().get('Starting...'))
-
- app = TuxBot()
-
- try:
- with setup_logging():
- app.run()
- except KeyboardInterrupt:
- app.close()
diff --git a/cogs/API.py b/cogs/API.py
deleted file mode 100644
index a483b25..0000000
--- a/cogs/API.py
+++ /dev/null
@@ -1,56 +0,0 @@
-import logging
-
-import discord
-from aiohttp import web
-from discord.ext import commands
-
-from bot import TuxBot
-
-log = logging.getLogger(__name__)
-
-
-class API(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.site = web.TCPSite
-
- app = web.Application()
- app.add_routes([web.get('/users/{user_id}', self.users)])
-
- self.runner = web.AppRunner(app)
- self.bot.loop.create_task(self.start_HTTPMonitoring_server())
-
- async def start_HTTPMonitoring_server(self):
- host = self.bot.config.get('API', 'Host')
- port = self.bot.config.get('API', 'Port')
-
- print(f"Starting API server on {host}:{port}")
-
- await self.runner.setup()
- self.site = web.TCPSite(self.runner, host, port)
- await self.site.start()
-
- async def users(self, request):
- try:
- user = await self.bot.fetch_user(request.match_info['user_id'])
- except discord.NotFound:
- return web.Response(status=404)
-
- json = {
- 'id': user.id,
- 'username': user.name,
- 'discriminator': user.discriminator,
- 'avatar': user.avatar,
- 'default_avatar': user.default_avatar.value,
- 'bot': user.bot,
- 'system': user.system,
- }
-
- return web.json_response(
- json
- )
-
-
-def setup(bot: TuxBot):
- bot.add_cog(API(bot))
diff --git a/cogs/Admin.py b/cogs/Admin.py
deleted file mode 100644
index a3bc330..0000000
--- a/cogs/Admin.py
+++ /dev/null
@@ -1,534 +0,0 @@
-import asyncio
-import datetime
-import logging
-from typing import Union
-
-import discord
-import humanize
-from discord.ext import commands
-
-from bot import TuxBot
-from utils import Texts
-from utils.models import WarnModel
-from utils import command_extra, group_extra
-
-log = logging.getLogger(__name__)
-
-
-class Admin(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.icon = ":shield:"
- self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/160/twitter/233/shield_1f6e1.png"
-
- async def cog_check(self, ctx: commands.Context) -> bool:
- permissions: discord.Permissions = ctx.channel.permissions_for(
- ctx.author)
-
- has_permission = permissions.administrator
- is_owner = await self.bot.is_owner(ctx.author)
-
- return has_permission or is_owner
-
- @staticmethod
- async def kick_ban_message(ctx: commands.Context,
- **kwargs) -> discord.Embed:
- member: discord.Member = kwargs.get('member')
- reason = kwargs.get(
- 'reason',
- Texts('admin', ctx).get("Please enter a reason")
- )
-
- if kwargs.get('type') == 'ban':
- title = '**Ban** ' + str(len(await ctx.guild.bans()))
- color = discord.Color.dark_red()
- else:
- title = '**Kick**'
- color = discord.Color.red()
- e = discord.Embed(
- title=title,
- description=reason,
- timestamp=datetime.datetime.utcnow(),
- color=color
- )
- e.set_author(
- name=f'{member.name}#{member.discriminator} ({member.id})',
- icon_url=member.avatar_url_as(format='jpg')
- )
- e.set_footer(
- text=f'{ctx.author.name}#{ctx.author.discriminator}',
- icon_url=ctx.author.avatar_url_as(format='png')
- )
-
- return e
-
- ###########################################################################
-
- @group_extra(name='say', invoke_without_command=True, category='text')
- async def _say(self, ctx: commands.Context, *, content: str):
- if ctx.invoked_subcommand is None:
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
- await ctx.send(content)
-
- @_say.command(name='edit')
- async def _say_edit(self, ctx: commands.Context, message_id: int, *,
- content: str):
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
- try:
- message: discord.Message = await ctx.channel.fetch_message(
- message_id)
- await message.edit(content=content)
- except (discord.errors.NotFound, discord.errors.Forbidden):
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the message"),
- delete_after=5)
-
- @_say.command(name='to')
- async def _say_to(self, ctx: commands.Context,
- channel: Union[discord.TextChannel, discord.User], *,
- content):
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
- await channel.send(content)
-
- ###########################################################################
-
- @command_extra(name='ban', category='administration')
- async def _ban(self, ctx: commands.Context, user: discord.Member, *,
- reason=""):
- try:
- member: discord.Member = await ctx.guild.fetch_member(user.id)
-
- try:
- await member.ban(reason=reason)
- e: discord.Embed = await self.kick_ban_message(
- ctx,
- member=member,
- type='ban',
- reason=reason
- )
-
- await ctx.send(embed=e)
- except discord.Forbidden:
- await ctx.send(
- Texts('admin', ctx).get("Unable to ban this user"),
- delete_after=5)
- except discord.errors.NotFound:
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the user..."),
- delete_after=5)
-
- ###########################################################################
-
- @command_extra(name='kick', category='administration')
- async def _kick(self, ctx: commands.Context, user: discord.Member, *,
- reason=""):
- try:
- member: discord.Member = await ctx.guild.fetch_member(user.id)
-
- try:
- await member.kick(reason=reason)
- e: discord.Embed = await self.kick_ban_message(
- ctx,
- member=member,
- type='kick',
- reason=reason
- )
-
- await ctx.send(embed=e)
- except discord.Forbidden:
- await ctx.send(
- Texts('admin', ctx).get("Unable to kick this user"),
- delete_after=5)
- except discord.errors.NotFound:
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the user..."),
- delete_after=5)
-
- ###########################################################################
-
- @command_extra(name='clear', category='text')
- async def _clear(self, ctx: commands.Context, count: int):
- try:
- await ctx.message.delete()
- await ctx.channel.purge(limit=count)
- except discord.errors.Forbidden:
- pass
-
- ###########################################################################
-
- @group_extra(name='react', category='text')
- async def _react(self, ctx: commands.Context):
- if ctx.invoked_subcommand is None:
- await ctx.send_help('react')
-
- @_react.command(name='add')
- async def _react_add(self, ctx: commands.Context, message_id: int, *,
- emojis: str):
- emojis: list = emojis.split(' ')
-
- try:
- message: discord.Message = await ctx.channel.fetch_message(
- message_id)
-
- for emoji in emojis:
- await message.add_reaction(emoji)
- except discord.errors.NotFound:
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the message"),
- delete_after=5)
-
- @_react.command(name='remove', aliases=['clear'])
- async def _react_remove(self, ctx: commands.Context, message_id: int):
- try:
- message: discord.Message = await ctx.channel.fetch_message(
- message_id)
- await message.clear_reactions()
- except discord.errors.NotFound:
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the message"),
- delete_after=5)
-
- ###########################################################################
-
- @group_extra(name='delete', invoke_without_command=True, category='text')
- async def _delete(self, ctx: commands.Context, message_id: int):
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
- try:
- message: discord.Message = await ctx.channel.fetch_message(
- message_id)
- await message.delete()
- except (discord.errors.NotFound, discord.errors.Forbidden):
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the message"),
- delete_after=5)
-
- @_delete.command(name='from', aliases=['to', 'in'])
- async def _delete_from(self, ctx: commands.Context,
- channel: discord.TextChannel, message_id: int):
- try:
- await ctx.message.delete()
- except discord.errors.Forbidden:
- pass
-
- try:
- message: discord.Message = await channel.fetch_message(
- message_id
- )
- await message.delete()
- except (discord.errors.NotFound, discord.errors.Forbidden):
- await ctx.send(
- Texts('utils', ctx).get("Unable to find the message"),
- delete_after=5
- )
-
- ###########################################################################
-
- async def get_warn(self, ctx: commands.Context,
- member: discord.Member = False):
- await ctx.trigger_typing()
-
- if member:
- warns = WarnModel.objects.filter(
- server_id=str(ctx.guild.id),
- user_id=member.id
- )
- else:
- warns = WarnModel.objects.filter(
- server_id=str(ctx.guild.id)
- )
- warns_list = ''
-
- for warn in await warns.all():
- row_id = warn.id
- user_id = warn.user_id
- user = await self.bot.fetch_user(user_id)
- reason = warn.reason
- ago = humanize.naturaldelta(
- datetime.datetime.now() - warn.created_at
- )
-
- warns_list += f"[{row_id}] **{user}**: `{reason}` *({ago} ago)*\n"
-
- return warns_list, warns
-
- async def add_warn(self, ctx: commands.Context, member: discord.Member,
- reason):
-
- now = datetime.datetime.now()
- warn = WarnModel(server_id=ctx.guild.id, user_id=member.id,
- reason=reason,
- created_at=now)
-
- self.bot.database.session.add(warn)
- self.bot.database.session.commit()
-
- @group_extra(name='warn', aliases=['warns'], category='administration')
- async def _warn(self, ctx: commands.Context):
- await ctx.trigger_typing()
- if ctx.invoked_subcommand is None:
- warns_list, warns = await self.get_warn(ctx)
- e = discord.Embed(
- title=f"{warns.count()} {Texts('admin', ctx).get('last warns')}: ",
- description=warns_list
- )
-
- await ctx.send(embed=e)
-
- @_warn.command(name='add', aliases=['new'])
- async def _warn_add(self, ctx: commands.Context, member: discord.Member,
- *, reason="N/A"):
- if not member:
- return await ctx.send(
- Texts('utils', ctx).get("Unable to find the user...")
- )
-
- def check(pld: discord.RawReactionActionEvent):
- if pld.message_id != choice.id \
- or pld.user_id != ctx.author.id:
- return False
- return pld.emoji.name in ('1⃣', '2⃣', '3⃣')
-
- warns_list, warns = await self.get_warn(ctx, member)
-
- if warns.count() >= 2:
- e = discord.Embed(
- title=Texts('admin', ctx).get('More than 2 warns'),
- description=f"{member.mention} "
- + Texts('admin', ctx).get('has more than 2 warns')
- )
- e.add_field(
- name='__Actions__',
- value=':one: kick\n'
- ':two: ban\n'
- ':three: ' + Texts('admin', ctx).get('ignore')
- )
-
- choice = await ctx.send(embed=e)
-
- for reaction in ('1⃣', '2⃣', '3⃣'):
- await choice.add_reaction(reaction)
-
- try:
- payload = await self.bot.wait_for(
- 'raw_reaction_add',
- check=check,
- timeout=50.0
- )
- except asyncio.TimeoutError:
- return await ctx.send(
- Texts('admin', ctx).get('Took too long. Aborting.')
- )
- finally:
- await choice.delete()
-
- if payload.emoji.name == '1⃣':
- from jishaku.models import copy_context_with
-
- alt_ctx = await copy_context_with(
- ctx,
- content=f"{ctx.prefix}"
- f"kick "
- f"{member} "
- f"{Texts('admin', ctx).get('More than 2 warns')}"
- )
- return await alt_ctx.command.invoke(alt_ctx)
-
- elif payload.emoji.name == '2⃣':
- from jishaku.models import copy_context_with
-
- alt_ctx = await copy_context_with(
- ctx,
- content=f"{ctx.prefix}"
- f"ban "
- f"{member} "
- f"{Texts('admin', ctx).get('More than 2 warns')}"
- )
- return await alt_ctx.command.invoke(alt_ctx)
-
- await self.add_warn(ctx, member, reason)
- await ctx.send(
- content=f"{member.mention} "
- f"**{Texts('admin', ctx).get('got a warn')}**"
- f"\n**{Texts('admin', ctx).get('Reason')}:** `{reason}`"
- )
-
- @_warn.command(name='remove', aliases=['revoke', 'del', 'delete'])
- async def _warn_remove(self, ctx: commands.Context, warn_id: int):
- warn = self.bot.database.session \
- .query(WarnModel) \
- .filter(WarnModel.id == warn_id) \
- .one()
-
- self.bot.database.session.delete(warn)
-
- await ctx.send(f"{Texts('admin', ctx).get('Warn with id')} `{warn_id}`"
- f" {Texts('admin', ctx).get('successfully removed')}")
-
- @_warn.command(name='show', aliases=['list', 'all'])
- async def _warn_show(self, ctx: commands.Context, member: discord.Member):
- warns_list, warns = await self.get_warn(ctx, member)
-
- e = discord.Embed(
- title=f"{warns.count()} {Texts('admin', ctx).get('last warns')}: ",
- description=warns_list
- )
-
- await ctx.send(embed=e)
-
- @_warn.command(name='edit', aliases=['change', 'modify'])
- async def _warn_edit(self, ctx: commands.Context, warn_id: int, *, reason):
- warn = self.bot.database.session \
- .query(WarnModel) \
- .filter(WarnModel.id == warn_id) \
- .one()
- warn.reason = reason
-
- self.bot.database.session.commit()
-
- await ctx.send(f"{Texts('admin', ctx).get('Warn with id')} `{warn_id}`"
- f" {Texts('admin', ctx).get('successfully edited')}")
-
- ###########################################################################
-
- @command_extra(name='language', aliases=['lang', 'langue', 'langage'], category='server')
- async def _language(self, ctx: commands.Context, locale: str):
- available = self.bot.database.session \
- .query(LangModel.value) \
- .filter(LangModel.key == 'available') \
- .first()[0] \
- .split(',')
-
- if locale.lower() not in available:
- await ctx.send(
- Texts('admin', ctx).get('Unable to find this language'))
- else:
- current = self.bot.database.session \
- .query(LangModel) \
- .filter(LangModel.key == str(ctx.guild.id))
-
- if current.count() > 0:
- current = current.one()
- current.value = locale.lower()
- self.bot.database.session.commit()
- else:
- new_row = LangModel(key=str(ctx.guild.id),
- value=locale.lower())
- self.bot.database.session.add(new_row)
- self.bot.database.session.commit()
-
- await ctx.send(
- Texts('admin', ctx).get('Language changed successfully'))
-
- ###########################################################################
-
- @group_extra(name='prefix', aliases=['prefixes'], category='server')
- async def _prefix(self, ctx: commands.Context):
- if ctx.invoked_subcommand is None:
- await ctx.send_help('prefix')
-
- @_prefix.command(name='add', aliases=['set', 'new'])
- async def _prefix_add(self, ctx: commands.Context, prefix: str):
- if str(ctx.guild.id) in self.bot.prefixes:
- prefixes = self.bot.prefixes.get(
- str(ctx.guild.id), "prefixes"
- ).split(
- self.bot.config.get("misc", "separator")
- )
-
- if prefix in prefixes:
- return await ctx.send(
- Texts('admin', ctx).get('This prefix already exists')
- )
- else:
- prefixes.append(prefix)
- self.bot.prefixes.set(
- str(ctx.guild.id),
- "prefixes",
- self.bot.config.get("misc", "separator")
- .join(prefixes)
- )
- with open('./configs/prefixes.cfg', 'w') as configfile:
- self.bot.prefixes.write(configfile)
- else:
- self.bot.prefixes.add_section(str(ctx.guild.id))
- self.bot.prefixes.set(str(ctx.guild.id), "prefixes", prefix)
- with open('./configs/prefixes.cfg', 'w') as configfile:
- self.bot.prefixes.write(configfile)
-
- await ctx.send(
- Texts('admin', ctx).get('Prefix added successfully')
- )
-
- @_prefix.command(name='remove', aliases=['drop', 'del', 'delete'])
- async def _prefix_remove(self, ctx: commands.Context, prefix: str):
- if str(ctx.guild.id) in self.bot.prefixes:
- prefixes = self.bot.prefixes.get(
- str(ctx.guild.id), "prefixes"
- ).split(
- self.bot.config.get("misc", "separator")
- )
-
- if prefix in prefixes:
- prefixes.remove(prefix)
- self.bot.prefixes.set(
- str(ctx.guild.id),
- "prefixes",
- self.bot.config.get("misc", "separator")
- .join(prefixes)
- )
- with open('./configs/prefixes.cfg', 'w') as configfile:
- self.bot.prefixes.write(configfile)
-
- return await ctx.send(
- Texts('admin', ctx).get('Prefix removed successfully')
- )
-
- await ctx.send(
- Texts('admin', ctx).get('This prefix does not exist')
- )
-
- @_prefix.command(name='list', aliases=['show', 'all'])
- async def _prefix_list(self, ctx: commands.Context):
- extras = ['.']
- if ctx.message.guild is not None:
- extras = []
- if str(ctx.message.guild.id) in self.bot.prefixes:
- extras.extend(
- self.bot.prefixes.get(str(ctx.message.guild.id),
- "prefixes").split(
- self.bot.config.get("misc", "separator")
- )
- )
-
- prefixes = [self.bot.user.mention]
- prefixes.extend(extras)
-
- if len(prefixes) <= 1:
- text = Texts('admin', ctx) \
- .get('The only prefix for this guild is :\n')
- else:
- text = Texts('admin', ctx) \
- .get('Available prefixes for this guild are :\n')
-
- await ctx.send(text + "\n • ".join(prefixes))
-
-
-def setup(bot: TuxBot):
- bot.add_cog(Admin(bot))
diff --git a/cogs/Help.py b/cogs/Help.py
deleted file mode 100644
index 396c23c..0000000
--- a/cogs/Help.py
+++ /dev/null
@@ -1,227 +0,0 @@
-# Created by romain at 04/01/2020
-
-import logging
-
-import discord
-from discord.ext import commands
-
-from bot import TuxBot
-from utils import Texts, GroupPlus
-from utils import FieldPages
-
-log = logging.getLogger(__name__)
-
-
-class HelpCommand(commands.HelpCommand):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.ignore_cogs = ["Monitoring", "Help", "Jishaku"]
- self.owner_cogs = []
- self.admin_cogs = ["Admin"]
-
- def command_formatting(self, e, command):
- prefix = self.context.prefix \
- if str(self.context.bot.user.id) not in self.context.prefix \
- else f"@{self.context.bot.user.name}"
- file = Texts(command.cog.qualified_name.lower() + '_help', self.context)
-
- if command.parent is not None:
- description = file.get(f"_{command.parent}_{command.name}")
- usage = file.get(f"_{command.parent}_{command.name}__usage")
- else:
- description = file.get(f"_{command.name}")
- usage = file.get(f"_{command.name}__usage")
-
- e.title = self.get_command_signature(command) + usage
- e.description = description
-
- e.add_field(
- name=Texts(
- 'help', self.context
- ).get(
- 'command_help.params'
- ),
- value=usage
- )
- e.add_field(
- name=Texts(
- 'help', self.context
- ).get(
- 'command_help.usage'
- ),
- value=f"{prefix}{command.qualified_name} " + usage
- )
-
- aliases = "`" + '`, `'.join(command.aliases) + "`"
- if aliases == "``":
- aliases = Texts(
- 'help', self.context
- ).get(
- 'command_help.no_aliases'
- )
- e.add_field(
- name=Texts(
- 'help', self.context
- ).get(
- 'command_help.aliases'
- ),
- value=aliases
- )
-
- return e
-
- async def send_bot_help(self, mapping):
- owners = self.context.bot.owners
- prefix = self.context.prefix \
- if str(self.context.bot.user.id) not in self.context.prefix \
- else f"@{self.context.bot.user.name} "
-
- e = discord.Embed(
- color=discord.Color.blue(),
- description=Texts(
- 'help', self.context
- ).get(
- 'main_page.description'
- )
- )
- e.set_author(
- icon_url=self.context.author.avatar_url_as(format='png'),
- name=self.context.author
- )
- e.set_footer(
- text=Texts(
- 'help', self.context
- ).get(
- 'main_page.footer'
- ).format(
- prefix
- )
- )
-
- for extension in self.context.bot.cogs.values():
- if self.context.author not in owners \
- and extension.__class__.__name__ in self.owner_cogs:
- continue
- if extension.__class__.__name__ in self.ignore_cogs:
- continue
-
- count = len(extension.get_commands())
- text = Texts('help', self.context).get('main_page.commands')
-
- if count <= 1:
- text = text[:-1]
-
- e.add_field(
- name=f"__{extension.icon} **{extension.qualified_name}**__",
- value=f"{count} {text}"
- )
-
- await self.context.send(embed=e)
-
- async def send_cog_help(self, cog):
- pages = {}
- prefix = self.context.prefix \
- if str(self.context.bot.user.id) not in self.context.prefix \
- else f"@{self.context.bot.user.name}"
- file = Texts(cog.qualified_name.lower() + '_help', self.context)
-
- if cog.__class__.__name__ in self.owner_cogs \
- and self.context.author not in self.context.bot.owners:
- return self.command_not_found(cog.qualified_name)
-
- for cmd in cog.get_commands():
- if self.context.author not in self.context.bot.owners \
- and (cmd.hidden or cmd.category == "Hidden"):
- continue
-
- if cmd.category not in pages:
- pages[cmd.category] = "```asciidoc\n"
-
- pages[cmd.category] \
- += f"{cmd.name}" \
- + ' ' * int(13 - len(cmd.name)) \
- + f":: {file.get(f'_{cmd.name}__short')}\n"
-
- if isinstance(cmd, GroupPlus):
- for group_command in cmd.commands:
- pages[cmd.category] \
- += f"└> {group_command.name}" \
- + ' ' * int(10 - len(group_command.name)) \
- + f":: {file.get(f'_{group_command.parent}_{group_command.name}__short')}\n"
- for e in pages:
- pages[e] += "```"
- formatted = []
- for name, cont in pages.items():
- formatted.append((name, cont))
- footer_text = Texts('help', self.context) \
- .get('main_page.footer') \
- .format(prefix)
-
- pages = FieldPages(
- self.context,
- embed_color=discord.Color.blue(),
- entries=formatted,
- title=cog.qualified_name.upper(),
- thumbnail=cog.big_icon,
- footericon=self.context.bot.user.avatar_url,
- footertext=footer_text,
- per_page=1
- )
- await pages.paginate()
-
- async def send_group_help(self, group):
- if group.cog_name in self.ignore_cogs:
- return await self.send_error_message(
- self.command_not_found(group.name)
- )
- file = Texts(group.qualified_name.lower() + '_help', self.context)
-
- formatted = self.command_formatting(
- discord.Embed(color=discord.Color.blue()),
- group
- )
- sub_command_list = "⠀" # this is braille, please don't touch unless you know what you're doing
- for group_command in group.commands:
- sub_command_list += f"└> **{group_command.name}** - {file.get(f'_{group_command.parent}_{group_command.name}')}\n"
-
- subcommands = Texts(
- 'help', self.context
- ).get(
- 'command_help.subcommands'
- )
-
- formatted.add_field(name=subcommands, value=sub_command_list, inline=False)
- await self.context.send(embed=formatted)
-
- async def send_command_help(self, command):
- if isinstance(command, commands.Group):
- return await self.send_group_help(command)
-
- if command.cog_name in self.ignore_cogs:
- return await self.send_error_message(
- self.command_not_found(command.name))
-
- formatted = self.command_formatting(
- discord.Embed(color=discord.Color.blue()),
- command
- )
-
- await self.context.send(embed=formatted)
-
- def command_not_found(self, command):
- return Texts(
- 'help', self.context
- ).get(
- 'main_page.not_found'
- ).format(
- command
- )
-
-
-class Help(commands.Cog):
- def __init__(self, bot: TuxBot):
- bot.help_command = HelpCommand()
-
-
-def setup(bot: TuxBot):
- bot.add_cog(Help(bot))
diff --git a/cogs/Images.py b/cogs/Images.py
new file mode 100644
index 0000000..957eece
--- /dev/null
+++ b/cogs/Images.py
@@ -0,0 +1,180 @@
+import logging
+from io import BytesIO
+
+import discord
+from discord.ext import commands, flags
+
+from app import TuxBot
+from utils.functions.extra import ContextPlus
+
+log = logging.getLogger(__name__)
+
+
+class Images(commands.Cog, name="Images"):
+ def __init__(self, bot):
+ self.bot = bot
+ self.image_api = "http://0.0.0.0:8080"
+
+ async def _send_meme(self, ctx: ContextPlus, endpoint: str, **passed_flags):
+ async with ctx.typing():
+ url = f"{self.image_api}/{endpoint}?"
+ for key, val in passed_flags.items():
+ if val:
+ url += f"{key}={val}&"
+
+ async with self.bot.session.get(url) as r:
+ if r.status != 200:
+ return await ctx.send("Failed...")
+
+ data = BytesIO(await r.read())
+
+ await ctx.send(
+ file=discord.File(data, "output.png")
+ )
+
+ @commands.command(name="phcomment")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _phcomment(self, ctx: ContextPlus, user: discord.User = None, *, message: commands.clean_content(fix_channel_mentions=True, escape_markdown=True)):
+ async with ctx.typing():
+ message = message.replace("&", "%26")
+ if user is None:
+ avatar = ctx.author.avatar_url_as(format='png')
+ username = ctx.author.name
+ else:
+ avatar = user.avatar_url_as(format='png')
+ username = user.name
+
+ url = f"{self.image_api}/ph/comment" \
+ f"?image={avatar}" \
+ f"&username={username}" \
+ f"&message={message}"
+
+ async with self.bot.session.get(url) as r:
+ if r.status != 200:
+ return await ctx.send("Failed...")
+
+ data = BytesIO(await r.read())
+
+ await ctx.send(
+ file=discord.File(data, "output.png")
+ )
+
+ @commands.command(name="phvideo")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _phvideo(self, ctx: ContextPlus, image: str, author: discord.User, *, title: commands.clean_content(fix_channel_mentions=True, escape_markdown=True)):
+ async with ctx.typing():
+ url = f"{self.image_api}/ph/video" \
+ f"?image={image}" \
+ f"&username={author.name}" \
+ f"&title={title}"
+
+ async with self.bot.session.get(url) as r:
+ if r.status != 200:
+ return await ctx.send("Failed...")
+
+ data = BytesIO(await r.read())
+
+ await ctx.send(
+ file=discord.File(data, "output.png")
+ )
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.add_flag("--text3", type=str)
+ @flags.command(name="balloon")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _balloon(self, ctx: ContextPlus, **passed_flags):
+ passed_flags["text3"] = passed_flags.get("text3")
+ passed_flags["text4"] = passed_flags.get("text1")
+ passed_flags["text5"] = passed_flags.get("text2")
+
+ await self._send_meme(ctx, 'balloon', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.add_flag("--text3", type=str)
+ @flags.command(name="butterfly")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _butterfly(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'butterfly', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.command(name="buttons")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _buttons(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'buttons', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.command(name="cmm")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _cmm(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'change_my_mind', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.command(name="drake")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _drake(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'drake', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str, default=False)
+ @flags.command(name="fry")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _fry(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'fry', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str, default=False)
+ @flags.command(name="imagination")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _imagination(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'imagination', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str, default=False)
+ @flags.command(name="everywhere")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _everywhere(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'everywhere', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.add_flag("--text3", type=str)
+ @flags.command(name="choice")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _choice(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'choice', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.command(name="pika")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _pika(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'pika', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.add_flag("--text3", type=str)
+ @flags.command(name="pkp")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _pkp(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'pkp', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.add_flag("--text2", type=str)
+ @flags.command(name="puppet")
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _puppet(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'puppet', **passed_flags)
+
+ @flags.add_flag("--text1", type=str)
+ @flags.command(name="scroll_of_truth", alias=['sot'])
+ @commands.cooldown(1, 5, commands.BucketType.user)
+ async def _sot(self, ctx: ContextPlus, **passed_flags):
+ await self._send_meme(ctx, 'scroll_of_truth', **passed_flags)
+
+
+def setup(bot: TuxBot):
+ cog = Images(bot)
+ bot.add_cog(cog)
diff --git a/cogs/Logs.py b/cogs/Logs.py
index 7caa4ec..a238d7b 100644
--- a/cogs/Logs.py
+++ b/cogs/Logs.py
@@ -18,9 +18,7 @@ import humanize
import psutil
from discord.ext import commands, tasks
-from bot import TuxBot
-from utils import Texts
-from utils import command_extra
+from app import TuxBot
log = logging.getLogger(__name__)
@@ -52,9 +50,6 @@ class Logs(commands.Cog):
self._resumes = []
self._identifies = defaultdict(list)
- self.icon = ":newspaper:"
- self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/twitter/233/newspaper_1f4f0.png"
-
def _clear_gateway_data(self):
one_week_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7)
to_remove = [
@@ -112,8 +107,19 @@ class Logs(commands.Cog):
self.bot.socket_stats[msg.get('t')] += 1
@property
- def webhook(self):
- return self.bot.logs_webhook
+ def logs(self):
+ webhooks = {}
+
+ for key, value in self.bot.logs_channels.items():
+ webhooks[key] = discord.Webhook.partial(
+ id=value.get('webhook')['id'],
+ token=value.get('webhook')['token'],
+ adapter=discord.AsyncWebhookAdapter(
+ self.bot.session
+ )
+ )
+
+ return webhooks
async def log_error(self, *, ctx=None, extra=None):
e = discord.Embed(title='Error', colour=0xdd5f53)
@@ -131,7 +137,7 @@ class Logs(commands.Cog):
e.add_field(name='Channel', value=channel)
e.add_field(name='Guild', value=guild)
- await self.webhook.send(embed=e)
+ await self.logs.get('errors').send(embed=e)
async def send_guild_stats(self, e, guild):
e.add_field(name='Name', value=guild.name)
@@ -155,7 +161,7 @@ class Logs(commands.Cog):
if guild.me:
e.timestamp = guild.me.joined_at
- await self.webhook.send(embed=e)
+ await self.logs.get('guilds').send(embed=e)
@commands.Cog.listener()
async def on_guild_join(self, guild: discord.guild):
@@ -169,17 +175,37 @@ class Logs(commands.Cog):
@commands.Cog.listener()
async def on_message(self, message: discord.message):
- if message.guild is None:
- e = discord.Embed(colour=0x0a97f5, title='New DM') # blue colour
+ ctx = await self.bot.get_context(message)
+ if ctx.valid:
+ return
+
+ if isinstance(message.channel, discord.DMChannel):
+ if message.author is self.bot.user:
+ e = discord.Embed(
+ title=f"DM to: {message.channel.recipient}",
+ description=message.content,
+ color=0x39e326
+ )
+ else:
+ e = discord.Embed(
+ title="New DM:",
+ description=message.content,
+ color=0x0A97F5
+ )
e.set_author(
- name=message.author,
- icon_url=message.author.avatar_url_as(format='png')
+ name=message.channel.recipient,
+ icon_url=message.channel.recipient.avatar_url_as(format="png")
)
- e.description = message.content
- if len(message.attachments) > 0:
- e.set_image(url=message.attachments[0].url)
- e.set_footer(text=f"User ID: {message.author.id}")
- await self.webhook.send(embed=e)
+
+ if message.attachments:
+ attachment_url = message.attachments[0].url
+ e.set_image(url=attachment_url)
+
+ e.set_footer(
+ text=f"User ID: {message.channel.recipient.id}"
+ )
+
+ await self.logs["dm"].send(embed=e)
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
@@ -212,7 +238,7 @@ class Logs(commands.Cog):
)
e.description = f'```py\n{exc}\n```'
e.timestamp = datetime.datetime.utcnow()
- await self.webhook.send(embed=e)
+ await self.logs.get('errors').send(embed=e)
@commands.Cog.listener()
async def on_socket_raw_send(self, data):
@@ -241,9 +267,9 @@ class Logs(commands.Cog):
emoji = types.get(record.levelname, ':heavy_multiplication_x:')
dt = datetime.datetime.utcfromtimestamp(record.created)
msg = f'{emoji} `[{dt:%Y-%m-%d %H:%M:%S}] {record.message}`'
- await self.webhook.send(msg)
+ await self.logs.get('gateway').send(msg)
- @command_extra(name='commandstats', hidden=True, category='misc')
+ @commands.command('commandstats')
@commands.is_owner()
async def _commandstats(self, ctx, limit=20):
counter = self.bot.command_stats
@@ -258,7 +284,7 @@ class Logs(commands.Cog):
await ctx.send(f'```\n{output}\n```')
- @command_extra(name='socketstats', hidden=True, category='misc')
+ @commands.command('socketstats')
@commands.is_owner()
async def _socketstats(self, ctx):
delta = datetime.datetime.utcnow() - self.bot.uptime
@@ -268,7 +294,7 @@ class Logs(commands.Cog):
await ctx.send(
f'{total} socket events observed ({cpm:.2f}/minute):\n{self.bot.socket_stats}')
- @command_extra(name='uptime', category='misc')
+ @commands.command('uptime')
async def _uptime(self, ctx):
uptime = humanize.naturaltime(
datetime.datetime.utcnow() - self.bot.uptime)
@@ -287,7 +313,7 @@ async def on_error(self, event, *args):
args_str.append('```')
e.add_field(name='Args', value='\n'.join(args_str), inline=False)
- hook = self.get_cog('Logs').webhook
+ hook = self.get_cog('Logs').logs.get('errors')
try:
await hook.send(embed=e)
except (discord.HTTPException, discord.NotFound,
diff --git a/cogs/Monitoring.py b/cogs/Monitoring.py
deleted file mode 100644
index 5827299..0000000
--- a/cogs/Monitoring.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import logging
-import urllib.request
-from datetime import datetime
-
-import discord
-from aiohttp import web
-from discord.ext import tasks, commands
-
-from bot import TuxBot
-
-log = logging.getLogger(__name__)
-
-
-class Monitoring(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.site = web.TCPSite
-
- self.ping_clusters.start()
-
- app = web.Application()
- app.add_routes([web.get('/', self.handle)])
-
- self.runner = web.AppRunner(app)
- self.bot.loop.create_task(self.start_HTTPMonitoring_server())
-
- def cog_unload(self):
- self.ping_clusters.stop()
-
- @tasks.loop(seconds=10.0)
- async def ping_clusters(self):
- for cluster in self.bot.fallbacks:
- if cluster == 'DEFAULT':
- pass
- else:
- cluster = self.bot.fallbacks[cluster]
- if not cluster.get('This', False):
- host = cluster.get('Host')
- port = cluster.get('Port')
-
- try:
- req = urllib.request.urlopen(
- f"http://{host}:{port}",
- timeout=2
- )
- except Exception:
- global_channel = await self.bot.fetch_channel(
- 661347412463321098
- )
-
- e = discord.Embed(
- title=f"Server `{cluster.get('Name')}`",
- color=discord.colour.Color.red(),
- description=f"Server **`{cluster.get('Name')}`** with address **`http://{host}:{port}`** is down ! ",
- timestamp=datetime.now()
- )
- e.set_thumbnail(
- url='https://upload.wikimedia.org/wikipedia/commons/7/75/Erroricon404.PNG'
- )
-
- await global_channel.send(embed=e)
- else:
- print(req.read().decode())
-
- @ping_clusters.before_loop
- async def before_pinging(self):
- await self.bot.wait_until_ready()
-
- cluster = self.bot.cluster
- host = cluster.get('Host')
- port = cluster.get('Port')
-
- global_channel = await self.bot.fetch_channel(
- 661347412463321098
- )
-
- e = discord.Embed(
- title=f"Server `{cluster.get('Name')}`",
- color=discord.colour.Color.green(),
- description=f"Server **`{cluster.get('Name')}`** with address **`http://{host}:{port}`** is started ! ",
- timestamp=datetime.now()
- )
- e.set_thumbnail(
- url='https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/MW-Icon-CheckMark.svg/1024px-MW-Icon-CheckMark.svg.png'
- )
-
- await global_channel.send(embed=e)
-
- async def start_HTTPMonitoring_server(self):
- host = self.bot.cluster.get('WebPage')
- port = self.bot.cluster.get('Port')
-
- print(f"Starting HTTP Monitoring server on {host}:{port}")
-
- await self.runner.setup()
- self.site = web.TCPSite(self.runner, host, port)
- await self.site.start()
-
- async def handle(self, _):
- return web.json_response(
- {
- 'message': "I'm alive !",
- 'ws': self.bot.latency * 1000
- }
- )
-
-
-def setup(bot: TuxBot):
- bot.add_cog(Monitoring(bot))
diff --git a/cogs/Poll.py b/cogs/Poll.py
deleted file mode 100644
index 44dd1eb..0000000
--- a/cogs/Poll.py
+++ /dev/null
@@ -1,222 +0,0 @@
-import json
-import logging
-from typing import Union
-
-import discord
-from discord.ext import commands
-from yarl import URL
-
-from bot import TuxBot
-from utils import PollModel, ResponsesModel
-from utils import Texts
-from utils.functions import emotes as utils_emotes
-from utils import group_extra
-
-log = logging.getLogger(__name__)
-
-
-class Poll(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.icon = ":bar_chart:"
- self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/twitter/233/bar-chart_1f4ca.png:"
-
- def get_poll(self, pld) -> Union[bool, PollModel]:
- if pld.user_id != self.bot.user.id:
- poll = self.bot.database.session \
- .query(PollModel) \
- .filter(PollModel.message_id == pld.message_id)
-
- if poll.count() > 0:
- poll = poll.one()
- emotes = utils_emotes.get(poll.available_choices)
- if pld.emoji.name in emotes:
- return poll
-
- return False
-
- async def remove_reaction(self, pld):
- channel: discord.TextChannel = self.bot.get_channel(pld.channel_id)
- message: discord.Message = await channel.fetch_message(pld.message_id)
- user: discord.User = await self.bot.fetch_user(pld.user_id)
-
- await message.remove_reaction(pld.emoji.name, user)
-
- @commands.Cog.listener()
- async def on_raw_reaction_add(self, pld: discord.RawReactionActionEvent):
- poll = self.get_poll(pld)
-
- if poll:
- if poll.is_anonymous:
- try:
- await self.remove_reaction(pld)
- except discord.errors.Forbidden:
- pass
- choice = utils_emotes.get_index(pld.emoji.name)
-
- responses = self.bot.database.session.query(ResponsesModel) \
- .filter(
- ResponsesModel.poll_id == poll.id,
- ResponsesModel.user == pld.user_id,
- ResponsesModel.choice == choice
- )
-
- if responses.count() != 0:
- response = responses.first()
- self.bot.database.session.delete(response)
- self.bot.database.session.commit()
- else:
- response = ResponsesModel(
- user=pld.user_id,
- poll_id=poll.id,
- choice=choice
- )
- self.bot.database.session.add(response)
- self.bot.database.session.commit()
-
- await self.update_poll(poll.id)
-
- @commands.Cog.listener()
- async def on_raw_reaction_remove(self,
- pld: discord.RawReactionActionEvent):
- poll = self.get_poll(pld)
-
- if poll:
- choice = utils_emotes.get_index(pld.emoji.name)
-
- responses = self.bot.database.session.query(ResponsesModel) \
- .filter(
- ResponsesModel.poll_id == poll.id,
- ResponsesModel.user == pld.user_id,
- ResponsesModel.choice == choice
- )
-
- if responses.count() != 0:
- response = responses.first()
- self.bot.database.session.delete(response)
- self.bot.database.session.commit()
- await self.update_poll(poll.id)
-
- ###########################################################################
-
- async def create_poll(self, ctx: commands.Context, poll: str, anonymous):
- question = (poll.split('|')[0]).strip()
- responses = [response.strip() for response in poll.split('|')[1:]]
- emotes = utils_emotes.get(len(responses))
-
- stmt = await ctx.send(Texts('poll', ctx).get('**Preparation...**'))
-
- poll_row = PollModel()
- self.bot.database.session.add(poll_row)
- self.bot.database.session.flush()
-
- e = discord.Embed(description=f"**{question}**")
- e.set_author(
- name=ctx.author,
- icon_url="https://cdn.gnous.eu/tuxbot/survey1.png"
- )
- for i, response in enumerate(responses):
- e.add_field(
- name=f"__{emotes[i]}` - {response.capitalize()}`__",
- value="**0** vote"
- )
- e.set_footer(text=f"ID: #{poll_row.id}")
-
- poll_row.channel_id = stmt.channel.id
- poll_row.message_id = stmt.id
- poll_row.content = e.to_dict()
- poll_row.is_anonymous = anonymous
- poll_row.available_choices = len(responses)
-
- self.bot.database.session.commit()
-
- await stmt.edit(content='', embed=e)
- for emote in range(len(responses)):
- await stmt.add_reaction(emotes[emote])
-
- async def update_poll(self, poll_id: int):
- poll = self.bot.database.session \
- .query(PollModel) \
- .filter(PollModel.id == poll_id) \
- .one()
- channel: discord.TextChannel = self.bot.get_channel(poll.channel_id)
- message: discord.Message = await channel.fetch_message(poll.message_id)
-
- chart_base_url = "https://quickchart.io/chart?backgroundColor=white&c="
- chart_options = {
- 'type': 'pie',
- 'data': {
- 'labels': [],
- 'datasets': [
- {
- 'data': []
- }
- ]
- }
- }
-
- content = json.loads(poll.content) \
- if isinstance(poll.content, str) \
- else poll.content
- raw_responses = self.bot.database.session \
- .query(ResponsesModel) \
- .filter(ResponsesModel.poll_id == poll_id)
- responses = {}
-
- for response in raw_responses.all():
- if responses.get(response.choice):
- responses[response.choice] += 1
- else:
- responses[response.choice] = 1
-
- for i, field in enumerate(content.get('fields')):
- responders = responses.get(i, 0)
- chart_options.get('data') \
- .get('labels') \
- .append(field.get('name')[5:].replace('__', ''))
- chart_options.get('data') \
- .get('datasets')[0] \
- .get('data') \
- .append(responders)
-
- if responders <= 1:
- field['value'] = f"**{responders}** vote"
- else:
- field['value'] = f"**{responders}** votes"
-
- e = discord.Embed(description=content.get('description'))
- e.set_author(
- name=content.get('author').get('name'),
- icon_url=content.get('author').get('icon_url')
- )
- chart_url = URL(chart_base_url + json.dumps(chart_options))
- e.set_thumbnail(url=str(chart_url))
- for field in content.get('fields'):
- e.add_field(
- name=field.get('name'),
- value=field.get('value'),
- inline=True
- )
- e.set_footer(text=content.get('footer').get('text'))
-
- await message.edit(embed=e)
-
- poll.content = json.dumps(content)
- self.bot.database.session.commit()
-
- @group_extra(name='poll', aliases=['sondage'], category='poll')
- async def _poll(self, ctx: commands.Context):
- if ctx.invoked_subcommand is None:
- await ctx.send_help('poll')
-
- @_poll.group(name='create', aliases=['new', 'nouveau'])
- async def _poll_create(self, ctx: commands.Context, *, poll: str):
- is_anonymous = '--anonyme' in poll
- poll = poll.replace('--anonyme', '')
-
- await self.create_poll(ctx, poll, anonymous=is_anonymous)
-
-
-def setup(bot: TuxBot):
- bot.add_cog(Poll(bot))
diff --git a/cogs/Useful.py b/cogs/Useful.py
deleted file mode 100644
index f4344c0..0000000
--- a/cogs/Useful.py
+++ /dev/null
@@ -1,410 +0,0 @@
-# Created by romain at 04/01/2020
-import logging
-import os
-import pathlib
-import platform
-import random
-import re
-import socket
-import time
-from socket import AF_INET6
-from io import BytesIO
-from PIL import Image
-from PIL import ImageFont
-from PIL import ImageDraw
-from PIL import ImageOps
-
-import aiohttp
-import discord
-import humanize
-import psutil
-from discord.ext import commands
-from tcp_latency import measure_latency
-
-from bot import TuxBot
-from utils import Texts
-from utils import command_extra, group_extra
-
-log = logging.getLogger(__name__)
-
-
-class Useful(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.icon = ":toolbox:"
- self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/twitter/233/toolbox_1f9f0.png"
-
- @staticmethod
- def _latest_commits():
- cmd = 'git log -n 3 -s --format="[\`%h\`](https://git.gnous.eu/gnouseu/tuxbot-bot/commits/%H) %s (%cr)"'
-
- return os.popen(cmd).read().strip()
-
- @staticmethod
- def fetch_info():
- total_lines = 0
- total_python_lines = 0
- file_amount = 0
- python_file_amount = 0
- ENV = "env"
-
- for path, _, files in os.walk("."):
- for name in files:
- file_dir = str(pathlib.PurePath(path, name))
- if (
- not name.endswith(".py")
- and not name.endswith(".po")
- and not name.endswith(".json")
- ) or ENV in file_dir:
- continue
- file_amount += 1
- python_file_amount += 1 if name.endswith(".py") else 0
- with open(file_dir, "r", encoding="utf-8") as file:
- for line in file:
- if not line.strip().startswith("#") \
- or not line.strip():
- total_lines += 1
- total_python_lines += 1 if name.endswith(".py") \
- else 0
-
- return (file_amount, total_lines), (
- python_file_amount, total_python_lines)
-
- @staticmethod
- def luhn_checker(number: int):
- digits = [int(x) for x in reversed(str(number))]
-
- for index, digit in enumerate(digits, start=1):
- digit = digit * 2 if index % 2 == 0 else digit
- if digit >= 10:
- digit = sum(int(x) for x in list(str(digit)))
-
- digits[index - 1] = digit
-
- return sum(digits) % 10 == 0
-
- ###########################################################################
-
- @command_extra(name='iplocalise', category='network')
- async def _iplocalise(self, ctx: commands.Context, addr, ip_type=''):
- addr = re.sub(r'http(s?)://', '', addr)
- addr = addr[:-1] if addr.endswith('/') else addr
-
- await ctx.trigger_typing()
-
- try:
- if 'v6' in ip_type:
- try:
- ip = socket.getaddrinfo(addr, None, AF_INET6)[1][4][0]
- except socket.gaierror:
- return await ctx.send(
- Texts('useful', ctx).get('ipv6 not available'))
- else:
- ip = socket.gethostbyname(addr)
-
- async with self.bot.session.get(f"http://ip-api.com/json/{ip}") \
- as s:
- response: dict = await s.json()
- if response.get('status') == 'success':
- e = discord.Embed(
- title=f"{Texts('useful', ctx).get('Information for')}"
- f" ``{addr}`` *`({response.get('query')})`*",
- color=0x5858d7
- )
-
- e.add_field(
- name=Texts('useful', ctx).get('Belongs to :'),
- value=response['org'] if response['org'] else 'N/A',
- inline=False
- )
-
- e.add_field(
- name=Texts('useful', ctx).get('Is located at :'),
- value=response['city'] if response['city'] else 'N/A',
- inline=True
- )
-
- e.add_field(
- name="Region :",
- value=f"{response['regionName'] if response['regionName'] else 'N/A'} "
- f"({response['country'] if response['country'] else 'N/A'})",
- inline=True
- )
-
- e.set_thumbnail(
- url=f"https://www.countryflags.io/"
- f"{response.get('countryCode')}/flat/64.png")
-
- await ctx.send(embed=e)
- else:
- await ctx.send(
- content=f"{Texts('useful', ctx).get('info not available')}"
- f"``{response['query'] if response['query'] else 'N/A'}``")
-
- except Exception as e:
- await ctx.send(e)
- await ctx.send(
- f"{Texts('useful', ctx).get('Cannot connect to host')} {addr}"
- )
-
- ###########################################################################
-
- @command_extra(name='getheaders', category='network')
- async def _getheaders(self, ctx: commands.Context, addr: str):
- if (addr.startswith('http') or addr.startswith('ftp')) is not True:
- addr = f"http://{addr}"
-
- await ctx.trigger_typing()
-
- try:
- async with self.bot.session.get(addr) as s:
- e = discord.Embed(
- title=f"{Texts('useful', ctx).get('Headers of')} {addr}",
- color=0xd75858
- )
- e.add_field(name="Status", value=s.status, inline=True)
- e.set_thumbnail(url=f"https://http.cat/{s.status}")
-
- headers = dict(s.headers.items())
- headers.pop('Set-Cookie', headers)
-
- for key, value in headers.items():
- e.add_field(name=key, value=value, inline=True)
- await ctx.send(embed=e)
-
- except aiohttp.ClientError:
- await ctx.send(
- f"{Texts('useful', ctx).get('Cannot connect to host')} {addr}"
- )
-
- ###########################################################################
-
- @command_extra(name='git', aliases=['sources', 'source', 'github'], category='misc')
- async def _git(self, ctx):
- e = discord.Embed(
- title=Texts('useful', ctx).get('git repo'),
- description=Texts('useful', ctx).get('git text'),
- colour=0xE9D460
- )
- e.set_author(
- name='Gnous',
- icon_url="https://cdn.gnous.eu/logo1.png"
- )
- await ctx.send(embed=e)
-
- ###########################################################################
-
- @command_extra(name='quote', category='misc')
- async def _quote(self, ctx, message_id: discord.Message):
- e = discord.Embed(
- colour=message_id.author.colour,
- description=message_id.clean_content,
- timestamp=message_id.created_at
- )
- e.set_author(
- name=message_id.author.display_name,
- icon_url=message_id.author.avatar_url_as(format="jpg")
- )
- if len(message_id.attachments) >= 1:
- e.set_image(url=message_id.attachments[0].url)
-
- e.add_field(name="**Original**",
- value=f"[Go!]({message_id.jump_url})")
- e.set_footer(text="#" + message_id.channel.name)
-
- await ctx.send(embed=e)
-
- ###########################################################################
-
- @command_extra(name='ping', category='network')
- async def _ping(self, ctx: commands.Context):
- start = time.perf_counter()
- await ctx.trigger_typing()
- end = time.perf_counter()
-
- latency = round(self.bot.latency * 1000, 2)
- typing = round((end - start) * 1000, 2)
- discordapp = measure_latency(host='discordapp.com', wait=0)[0]
-
- e = discord.Embed(title='Ping', color=discord.Color.teal())
- e.add_field(name='Websocket', value=f'{latency}ms')
- e.add_field(name='Typing', value=f'{typing}ms')
- e.add_field(name='discordapp.com', value=f'{discordapp}ms')
- await ctx.send(embed=e)
-
- ###########################################################################
-
- @command_extra(name='info', aliases=['about'], category='misc')
- async def _info(self, ctx: commands.Context):
- proc = psutil.Process()
- total, python = self.fetch_info()
-
- with proc.oneshot():
- mem = proc.memory_full_info()
- e = discord.Embed(
- title=Texts('useful', ctx).get('Information about TuxBot'),
- color=0x89C4F9)
-
- e.add_field(
- name=f"__:busts_in_silhouette: "
- f"{Texts('useful', ctx).get('Development')}__",
- value=f"**Romain#5117:** [git](https://git.gnous.eu/Romain)\n"
- f"**Outout#4039:** [git](https://git.gnous.eu/mael)\n",
- inline=True
- )
- e.add_field(
- name="__<:python:596577462335307777> Python__",
- value=f"**python** `{platform.python_version()}`\n"
- f"**discord.py** `{discord.__version__}`",
- inline=True
- )
- e.add_field(
- name="__:gear: Usage__",
- value=f"**{humanize.naturalsize(mem.rss)}** "
- f"{Texts('useful', ctx).get('physical memory')}\n"
- f"**{humanize.naturalsize(mem.vms)}** "
- f"{Texts('useful', ctx).get('virtual memory')}\n",
- inline=True
- )
-
- e.add_field(
- name=f"__{Texts('useful', ctx).get('Servers count')}__",
- value=str(len(self.bot.guilds)),
- inline=True
- )
- e.add_field(
- name=f"__{Texts('useful', ctx).get('Channels count')}__",
- value=str(len([_ for _ in self.bot.get_all_channels()])),
- inline=True
- )
- e.add_field(
- name=f"__{Texts('useful', ctx).get('Members count')}__",
- value=str(len([_ for _ in self.bot.get_all_members()])),
- inline=True
- )
-
- e.add_field(
- name=f"__:file_folder: {Texts('useful', ctx).get('Files')}__",
- value=f"{total[0]} *({python[0]} <:python:596577462335307777>)*",
- inline=True
- )
- e.add_field(
- name=f"__¶ {Texts('useful', ctx).get('Lines')}__",
- value=f"{total[1]} *({python[1]} <:python:596577462335307777>)*",
- inline=True
- )
-
- e.add_field(
- name=f"__{Texts('useful', ctx).get('Latest changes')}__",
- value=self._latest_commits(),
- inline=False
- )
-
- e.add_field(
- name=f"__:link: {Texts('useful', ctx).get('Links')}__",
- value="[tuxbot.gnous.eu](https://tuxbot.gnous.eu/) "
- "| [gnous.eu](https://gnous.eu/) "
- "| [git](https://git.gnous.eu/gnouseu/tuxbot-bot) "
- "| [status](https://status.gnous.eu/check/154250) "
- f"| [{Texts('useful', ctx).get('Invite')}](https://discordapp.com/oauth2/authorize?client_id=301062143942590465&scope=bot&permissions=268749888)",
- inline=False
- )
-
- e.set_footer(text=f'version: {self.bot.version} '
- f'• prefix: {ctx.prefix}')
-
- await ctx.send(embed=e)
-
- ###########################################################################
-
- @command_extra(name='credits', aliases=['contributors', 'authors'], category='misc')
- async def _credits(self, ctx: commands.Context):
- e = discord.Embed(
- title=Texts('useful', ctx).get('Contributors'),
- color=0x36393f
- )
-
- e.add_field(
- name="**Outout#4039** ",
- value="• https://git.gnous.eu/mael ⠀\n"
- "• mael@gnous.eu\n"
- "• [@outoutxyz](https://twitter.com/outouxyz)",
- inline=True
- )
- e.add_field(
- name="**Romain#5117** ",
- value="• https://git.gnous.eu/Romain\n"
- "• romain@gnous.eu",
- inline=True
- )
-
- await ctx.send(embed=e)
-
- ###########################################################################
- @group_extra(name='cb', aliases=['cc'], category='misc')
- @commands.cooldown(1, 5, type=commands.BucketType.user)
- async def _cb(self, ctx: commands.Context):
- if ctx.invoked_subcommand is None:
- await ctx.send_help('cb')
-
- @_cb.command(name='validate', aliases=['valid', 'correct'], category='misc')
- @commands.cooldown(1, 5, type=commands.BucketType.user)
- async def _cb_validate(self, ctx: commands.Context, *, number: int):
- valid = self.luhn_checker(number)
-
- await ctx.send(
- Texts(
- 'useful', ctx
- ).get(
- 'valid_credit_card'
- if valid
- else 'invalid_credit_card'
- )
- )
-
- @_cb.command(name='generate', aliases=['new', 'get'], category='misc')
- @commands.cooldown(1, 5, type=commands.BucketType.user)
- async def _cb_generate(self, ctx: commands.Context):
- await ctx.channel.trigger_typing()
-
- number = random.randint(4000_0000_0000_0000, 5999_9999_9999_9999)
- while not self.luhn_checker(number):
- number = random.randint(4000_0000_0000_0000, 5999_9999_9999_9999)
- number = str(number)
- cvv = ''.join(random.choice("abcdefghij") for _ in range(3))
-
- with Image.open("utils/images/blank_credit_card.png") as blank:
- cc_font = ImageFont.truetype('utils/fonts/credit_card.ttf', 26)
- user_font = ImageFont.truetype('utils/fonts/credit_card.ttf', 20)
- draw = ImageDraw.Draw(blank)
-
- cvv_text = Image.new('L', (500, 50))
- cvv_draw = ImageDraw.Draw(cvv_text)
- cvv_draw.text((0, 0), cvv, font=user_font, fill=255)
- cvv_rotated = cvv_text.rotate(23, expand=1)
-
- draw.text(
- (69, 510),
- ' '.join([number[i:i+4] for i in range(0, len(number), 4)]),
- (210, 210, 210),
- font=cc_font
- )
-
- draw.text(
- (69, 550),
- ctx.author.name.upper(),
- (210, 210, 210),
- font=user_font
- )
- blank.paste(ImageOps.colorize(cvv_rotated, (0, 0, 0), (0, 0, 0)), (470, 0), cvv_rotated)
-
- output = BytesIO()
- blank.save(output, 'png')
- output.seek(0)
-
- await ctx.send(file=discord.File(fp=output, filename="credit_card.png"))
-
-
-def setup(bot: TuxBot):
- bot.add_cog(Useful(bot))
diff --git a/cogs/User.py b/cogs/User.py
deleted file mode 100644
index ac0c830..0000000
--- a/cogs/User.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import logging
-
-from discord.ext import commands
-
-from bot import TuxBot
-from utils import AliasesModel
-from utils import Texts
-from utils import group_extra
-
-log = logging.getLogger(__name__)
-
-
-class User(commands.Cog):
-
- def __init__(self, bot: TuxBot):
- self.bot = bot
- self.icon = ":bust_in_silhouette:"
- self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/twitter/233/bust-in-silhouette_1f464.png"
-
- ###########################################################################
-
- @group_extra(name='alias', aliases=['aliases'], category='alias')
- async def _alias(self, ctx: commands.Context):
- if ctx.invoked_subcommand is None:
- await ctx.send_help('alias')
-
- @_alias.command(name='add', aliases=['set', 'new'])
- async def _alias_add(self, ctx: commands.Context, *, user_alias: str):
- is_global = False
- if '--global' in user_alias:
- is_global = True
- user_alias.replace('--global', '')
-
- user_alias = user_alias.split(' -> ')
- if len(user_alias) != 2:
- return await ctx.send_help('alias')
-
- command = user_alias[1]
- user_alias = user_alias[0]
-
- if self.bot.get_command(command) is None:
- return await ctx.send(Texts('user').get('Command not found'))
-
- alias = AliasesModel(
- user_id=ctx.author.id,
- alias=user_alias,
- command=command,
- guild="global" if is_global else str(ctx.guild.id)
- )
-
- self.bot.database.session.add(alias)
- self.bot.database.session.commit()
-
- @_alias.command(name='remove', aliases=['drop', 'del', 'delete'])
- async def _alias_remove(self, ctx: commands.Context, prefix: str):
- ...
-
- @_alias.command(name='list', aliases=['show', 'all'])
- async def _alias_list(self, ctx: commands.Context):
- ...
-
-
-def setup(bot: TuxBot):
- bot.add_cog(User(bot))
diff --git a/configs/bot/blacklist.json b/configs/bot/blacklist.json
new file mode 100644
index 0000000..cbbe594
--- /dev/null
+++ b/configs/bot/blacklist.json
@@ -0,0 +1,5 @@
+{
+ "channels": [],
+ "guilds": [],
+ "users": []
+}
\ No newline at end of file
diff --git a/configs/bot/protected.py b/configs/bot/protected.py
new file mode 100644
index 0000000..073705f
--- /dev/null
+++ b/configs/bot/protected.py
@@ -0,0 +1,8 @@
+from .settings import token, postgresql, logs
+
+protected = [
+ token, str(list(token)),
+ postgresql, str(list(postgresql)),
+ *[channel.get('webhook').get('token') for channel in logs.values()]
+]
+
diff --git a/configs/bot/settings.py.example b/configs/bot/settings.py.example
new file mode 100644
index 0000000..626785d
--- /dev/null
+++ b/configs/bot/settings.py.example
@@ -0,0 +1,44 @@
+token = ""
+prefix = "drw."
+
+main_guild = int
+
+logs = {
+ "gateway": {
+ 'channel': int,
+ 'webhook': {
+ 'id': int,
+ 'token': ''
+ }
+ },
+ "dm": {
+ 'channel': int,
+ 'webhook': {
+ 'id': int,
+ 'token': ''
+ }
+ },
+ "mentions": {
+ 'channel': int,
+ 'webhook': {
+ 'id': int,
+ 'token': ''
+ }
+ },
+ "guilds": {
+ 'channel': int,
+ 'webhook': {
+ 'id': int,
+ 'token': ''
+ }
+ },
+ "errors": {
+ 'channel': int,
+ 'webhook': {
+ 'id': int,
+ 'token': ''
+ }
+ },
+}
+
+postgresql = 'postgres://tuxbot:tuxbot@localhost:5432/tuxbot-rewrite'
diff --git a/configs/bot/whitelist.json b/configs/bot/whitelist.json
new file mode 100644
index 0000000..83434f3
--- /dev/null
+++ b/configs/bot/whitelist.json
@@ -0,0 +1,3 @@
+{
+ "owners": [269156684155453451]
+}
\ No newline at end of file
diff --git a/configs/config.cfg.example b/configs/config.cfg.example
deleted file mode 100644
index e156f5d..0000000
--- a/configs/config.cfg.example
+++ /dev/null
@@ -1,24 +0,0 @@
-[bot]
-Token =
-Tester =
-Activity =
-
-[postgresql]
-Username =
-Password =
-Host =
-DBName =
-
-[permissions]
-Owners =
-
-[webhook]
-ID =
-Token =
-
-[misc]
-Separator =
-
-[API]
-Host =
-Port =
\ No newline at end of file
diff --git a/configs/fallbacks.cfg.example b/configs/fallbacks.cfg.example
deleted file mode 100644
index ea9bc7b..0000000
--- a/configs/fallbacks.cfg.example
+++ /dev/null
@@ -1,18 +0,0 @@
-[fr-srv01]
-Host =
-Name = fr-srv01
-WebPage = 0.0.0.0
-Port =
-
-[rm-dev01]
-This = True
-Host = 127.0.0.1
-Name = rm-dev01
-WebPage = 0.0.0.0
-Port = 3389
-
-[rm-srv01]
-Host = 127.0.0.1
-Name = rm-srv01
-WebPage = 0.0.0.0
-Port = 3390
diff --git a/configs/prefixes.cfg b/configs/prefixes.cfg
deleted file mode 100644
index 49d6637..0000000
--- a/configs/prefixes.cfg
+++ /dev/null
@@ -1,18 +0,0 @@
-[280805240977227776]
-prefixes = b1.[301062143942590465]*
-
-[303633056944881686]
-prefixes = b1.[301062143942590465]*
-
-[373881878471770112]
-prefixes = b1.
-
-[336642139381301249]
-prefixes = ba.
-
-[274247231534792704]
-prefixes = test.
-
-[528679953399676938]
-prefixes = test.
-
diff --git a/database.py b/database.py
deleted file mode 100644
index 49127d5..0000000
--- a/database.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import sqlalchemy
-from utils.models import database, metadata
-import argparse
-
-parser = argparse.ArgumentParser()
-parser.add_argument("-m", "--migrate", action="store_true")
-parser.add_argument("-s", "--seed", action="store_true")
-args = parser.parse_args()
-
-if args.migrate:
- print("Migrate...")
- engine = sqlalchemy.create_engine(str(database.url))
- metadata.create_all(engine)
- print("Done!")
-
-if args.seed:
- print('Seeding...')
- # todo: add seeding
- print("Done!")
diff --git a/generate_locales.sh b/generate_locales.sh
deleted file mode 100755
index 78be2cd..0000000
--- a/generate_locales.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-BASEDIR=$(pwd)
-
-cd "$BASEDIR/utils/locales/en/LC_MESSAGES"
-
-for i in *.po ; do
- [[ -f "$i" ]] || continue
- /usr/lib/python3.8/Tools/i18n/msgfmt.py -o "${i%.po}.mo" "${i%.po}"
-done
-
-cd "$BASEDIR/utils/locales/fr/LC_MESSAGES"
-
-for i in *.po ; do
- [[ -f "$i" ]] || continue
- /usr/lib/python3.8/Tools/i18n/msgfmt.py -o "${i%.po}.mo" "${i%.po}"
-done
\ No newline at end of file
diff --git a/configs/blacklist.cfg b/models/__init__.py
similarity index 100%
rename from configs/blacklist.cfg
rename to models/__init__.py
diff --git a/requirements.txt b/requirements.txt
index 442102d..d5a26eb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,13 +1,27 @@
-requests
-humanize
-git+https://github.com/Rapptz/discord.py@master
-jishaku
-gitpython
-orm
-asyncpg
-psycopg2
-configparser
-psutil
-tcp_latency
-yarl
-pillow
\ No newline at end of file
+aiofiles==0.5.0
+aiohttp==3.6.2
+aiosqlite==0.13.0
+astunparse==1.6.3
+async-timeout==3.0.1
+asyncpg==0.20.1
+attrs==19.3.0
+braceexpand==0.1.5
+chardet==3.0.4
+ciso8601==2.1.3
+discord-flags==2.1.1
+discord.py==1.3.3
+humanize==2.4.0
+idna==2.9
+import-expression==1.1.2
+jishaku==1.18.2.188
+mpmath==1.1.0
+multidict==4.7.6
+Pillow==7.1.2
+psutil==5.7.0
+PyPika==0.37.6
+six==1.14.0
+sympy==1.5.1
+tortoise-orm==0.16.11
+typing-extensions==3.7.4.2
+websockets==8.1
+yarl==1.4.2
diff --git a/todo b/todo
deleted file mode 100644
index 5ac368b..0000000
--- a/todo
+++ /dev/null
@@ -1,2 +0,0 @@
-reconnaissance d'image
-commande d'archivage pour les salons vocaux avec output mp4 dans lequel on voit le pseudo de celui qui parle
diff --git a/utils/__init__.py b/utils/__init__.py
deleted file mode 100755
index ff23e97..0000000
--- a/utils/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from utils.functions.config import *
-from utils.functions.lang import *
-from utils.functions.version import *
-
-from utils.functions.extra import *
-from utils.functions.paginator import *
diff --git a/utils/fonts/credit_card.ttf b/utils/fonts/credit_card.ttf
deleted file mode 100644
index 00abec8..0000000
Binary files a/utils/fonts/credit_card.ttf and /dev/null differ
diff --git a/utils/functions/__init__.py b/utils/functions/__init__.py
deleted file mode 100644
index 171e8cc..0000000
--- a/utils/functions/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .config import Config
-from .database import Database
-from .extra import *
-from .lang import Texts
-from .paginator import *
-from .version import Version
diff --git a/utils/functions/config.py b/utils/functions/config.py
deleted file mode 100644
index 64e3f69..0000000
--- a/utils/functions/config.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from typing import List, Union
-
-import configparser
-
-
-class Config(configparser.ConfigParser):
- __slots__ = ('name', '_db')
-
- def __init__(self, name):
- super().__init__()
-
- self._db = super()
- self._db.read(name)
-
- def find(self, value: str, **kwargs) \
- -> Union[
- List[configparser.SectionProxy], configparser.SectionProxy
- ]:
- key = kwargs.get('key', None)
- first = kwargs.get('first', False)
-
- results = []
-
- for name, section in self._db.items():
- if key is None:
- for k in section.keys():
- if section.get(k) == value:
- results.append(section)
- if first and len(results) == 1:
- return results[0]
- else:
- if section.get(key) == value:
- results.append(section)
- if first and len(results) == 1:
- return results[0]
- return results
diff --git a/utils/functions/database.py b/utils/functions/database.py
deleted file mode 100644
index 20388f0..0000000
--- a/utils/functions/database.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from .config import Config
-
-import sqlalchemy
-import databases
-
-
-class Database:
- def __init__(self, config: Config):
- conf_postgresql = config["postgresql"]
- postgresql = 'postgresql://{}:{}@{}/{}'.format(
- conf_postgresql.get("Username"), conf_postgresql.get("Password"),
- conf_postgresql.get("Host"), conf_postgresql.get("DBName"))
-
- self.database = databases.Database(postgresql)
- self.metadata = sqlalchemy.MetaData()
- self.engine = sqlalchemy.create_engine(str(self.database.url))
diff --git a/utils/functions/emotes.py b/utils/functions/emotes.py
deleted file mode 100644
index d296718..0000000
--- a/utils/functions/emotes.py
+++ /dev/null
@@ -1,10 +0,0 @@
-emotes = ['1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣', '🔟', '0⃣',
- '🇦', '🇧', '🇨', '🇩', '🇪', '🇫', '🇬', '🇭', '🇮']
-
-
-def get(count):
- return emotes[:count]
-
-
-def get_index(emote):
- return emotes.index(emote)
diff --git a/utils/functions/extra.py b/utils/functions/extra.py
index b07ad88..a186dd4 100644
--- a/utils/functions/extra.py
+++ b/utils/functions/extra.py
@@ -1,32 +1,70 @@
+import ast
+import json
+import os
+
+import discord
from discord.ext import commands
-from utils.functions import Config
-
-
-class CommandsPlus(commands.Command):
- def __init__(self, func, **kwargs):
- super().__init__(func, **kwargs)
- self.category = kwargs.get("category", 'other')
-
-
-class GroupPlus(commands.Group):
- def __init__(self, func, **kwargs):
- super().__init__(func, **kwargs)
- self.category = kwargs.get("category", 'other')
+from configs.bot.protected import protected
+from configs.bot.settings import prefix
class ContextPlus(commands.Context):
- async def send(self, content=None, **kwargs):
- config = Config('./configs/config.cfg')
+ async def send(self, content=None, *args, **kwargs):
+ if content is not None:
+ for value in protected:
+ content = content.replace(
+ str(value),
+ '[Deleted]'
+ )
- content = content.replace(config.get("bot", "Token"), 'Whoops! leaked token')
- content = content.replace(config.get("webhook", "Token"), 'Whoops! leaked token')
+ if kwargs.get('content') is not None:
+ for value in protected:
+ kwargs['content'] = kwargs['content'].replace(
+ str(value),
+ '[Deleted]'
+ )
- return await super().send(content, **kwargs)
+ if kwargs.get('embeds') is not None and len(kwargs.get('embeds')) > 0:
+ for i, embed in enumerate(kwargs.get('embeds')):
+ embed = str(kwargs.get('embed').to_dict())
+ for value in protected:
+ embed = embed.replace(str(value), '[Deleted]')
+ kwargs['embeds'][i] = discord.Embed.from_dict(
+ ast.literal_eval(embed)
+ )
+
+ if kwargs.get('embed') is not None:
+ embed = str(kwargs.get('embed').to_dict())
+ for value in protected:
+ embed = embed.replace(str(value), '[Deleted]')
+ kwargs['embed'] = discord.Embed.from_dict(
+ ast.literal_eval(embed)
+ )
+
+ return await super().send(content, *args, **kwargs)
-def command_extra(*args, **kwargs):
- return commands.command(*args, **kwargs, cls=CommandsPlus)
+async def get_prefix(bot, message):
+ custom_prefix = [prefix]
+ if message.guild:
+ path = f"configs/guilds/{str(message.guild.id)}.json"
+
+ if os.path.exists(path):
+ with open(path) as f:
+ datas = json.load(f)
+
+ custom_prefix = datas["Prefix"]
+
+ return commands.when_mentioned_or(*custom_prefix)(bot, message)
-def group_extra(*args, **kwargs):
- return commands.group(*args, **kwargs, cls=GroupPlus)
+def get_owners() -> list:
+ with open("configs/bot/whitelist.json") as f:
+ datas = json.load(f)
+
+ return datas['owners']
+
+
+def get_blacklist() -> dict:
+ with open("configs/bot/blacklist.json") as f:
+ return json.load(f)
diff --git a/utils/functions/lang.py b/utils/functions/lang.py
deleted file mode 100644
index fd3330b..0000000
--- a/utils/functions/lang.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import gettext
-import json
-
-from discord.ext import commands
-
-
-class Texts:
- def __init__(self, base: str = 'base', ctx: commands.Context = None):
- self.locale = self.get_locale(ctx)
- self.base = base
-
- def get(self, text: str) -> str:
- texts = gettext.translation(self.base, localedir='utils/locales',
- languages=[self.locale])
- texts.install()
- return texts.gettext(text)
-
- def set(self, lang: str):
- self.locale = lang
-
- @staticmethod
- def get_locale(ctx: commands.Context):
- lang = 'fr'
- if ctx is not None:
- try:
- with open(f'./configs/guilds/{ctx.guild.id}.json', 'r') as f:
- data = json.load(f)
-
- lang = data['lang']
-
- except FileNotFoundError:
- pass
-
- return lang
diff --git a/utils/functions/paginator.py b/utils/functions/paginator.py
deleted file mode 100644
index b18bd84..0000000
--- a/utils/functions/paginator.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""
-
-Based on https://github.com/Rapptz/RoboDanny/blob/3ec71c4c4031f868caff3027d71aecdebc3c5cec/cogs/utils/paginator.py
-Adapted by Romain J.
-
-"""
-
-import asyncio
-
-import discord
-from discord.ext import commands
-from discord.ext.commands import Paginator as CommandPaginator
-
-
-class CannotPaginate(Exception):
- pass
-
-
-class Pages:
- """Implements a paginator that queries the user for the
- pagination interface.
- Pages are 1-index based, not 0-index based.
- If the user does not reply within 2 minutes then the pagination
- interface exits automatically.
- Parameters
- ------------
- ctx: Context
- The context of the command.
- entries: List[str]
- A list of entries to paginate.
- per_page: int
- How many entries show up per page.
- show_entry_count: bool
- Whether to show an entry count in the footer.
- Attributes
- -----------
- embed: discord.Embed
- The embed object that is being used to send pagination info.
- Feel free to modify this externally. Only the description,
- footer fields, and colour are internally modified.
- permissions: discord.Permissions
- Our permissions for the channel.
- """
-
- def __init__(self, ctx, *, entries, per_page=12, show_entry_count=True,
- embed_color=discord.Color.blurple(), title=None,
- thumbnail=None, footericon=None, footertext=None, author=None,
- delete_after=None):
- self.bot = ctx.bot
- self.entries = entries
- self.message = ctx.message
- self.channel = ctx.channel
- self.author = author if author else ctx.author
- self.thumbnail = thumbnail
- self.footericon = footericon
- self.footertext = footertext
- self.title = title
- self.delete_after = delete_after
- self.per_page = per_page
- pages, left_over = divmod(len(self.entries), self.per_page)
- if left_over:
- pages += 1
- self.maximum_pages = pages
- self.embed = discord.Embed(colour=embed_color)
- self.paginating = len(entries) > per_page
- self.show_entry_count = show_entry_count
- self.reaction_emojis = [
- ('\U000023ee\U0000fe0f', self.first_page),
- ('\N{BLACK LEFT-POINTING TRIANGLE}', self.previous_page),
- ('\U000023f9', self.stop_pages),
- ('\N{BLACK RIGHT-POINTING TRIANGLE}', self.next_page),
- ('\U000023ed\U0000fe0f', self.last_page)
- ]
-
- if ctx.guild is not None:
- self.permissions = self.channel.permissions_for(ctx.guild.me)
- else:
- self.permissions = self.channel.permissions_for(ctx.bot.user)
-
- if not self.permissions.embed_links:
- raise commands.BotMissingPermissions(
- 'I do not have permissions to : Embed links.'
- )
-
- if not self.permissions.send_messages:
- raise commands.BotMissingPermissions('Bot cannot send messages.')
-
- if self.paginating:
- # verify we can actually use the pagination session
- if not self.permissions.add_reactions:
- raise commands.BotMissingPermissions(
- 'I do not have permissions to : Add Reactions.'
- )
-
- if not self.permissions.read_message_history:
- raise commands.BotMissingPermissions(
- 'I do not have permissions to : Read Message History.'
- )
-
- def get_page(self, page):
- base = (page - 1) * self.per_page
- return self.entries[base:base + self.per_page]
-
- def get_content(self, entries, page, *, first=False):
- return None
-
- def get_embed(self, entries, page, *, first=False):
- self.prepare_embed(entries, page, first=first)
- return self.embed
-
- def prepare_embed(self, entries, page, *, first=False):
- p = []
- for index, entry in enumerate(entries,
- 1 + ((page - 1) * self.per_page)):
- p.append(f'`{index}.` {entry}')
-
- if self.maximum_pages > 1:
- if self.show_entry_count:
- text = f'Showing page {page}/{self.maximum_pages} ({len(self.entries)} entries)'
- else:
- text = f'Showing page {page}/{self.maximum_pages}'
-
- self.embed.set_footer(text=text)
-
- if self.paginating and first:
- p.append('')
-
- self.embed.description = '\n'.join(p)
- self.embed.title = self.title or discord.Embed.Empty
- self.embed.set_author(icon_url=self.author.avatar_url,
- name=str(self.author))
-
- async def show_page(self, page, *, first=False):
- self.current_page = page
- entries = self.get_page(page)
- content = self.get_content(entries, page, first=first)
- embed = self.get_embed(entries, page, first=first)
-
- if not self.paginating:
- return await self.channel.send(content=content, embed=embed)
-
- if not first:
- await self.message.edit(content=content, embed=embed)
- return
-
- self.message = await self.channel.send(content=content, embed=embed)
- for (reaction, _) in self.reaction_emojis:
- if self.maximum_pages == 2 and reaction in ('\u23ed', '\u23ee'):
- # no |<< or >>| buttons if we only have two pages
- # we can't forbid it if someone ends up using it but remove
- # it from the default set
- continue
-
- await self.message.add_reaction(reaction)
-
- async def checked_show_page(self, page):
- if page != 0 and page <= self.maximum_pages:
- await self.show_page(page)
-
- async def first_page(self):
- """goes to the first page"""
- await self.show_page(1)
-
- async def last_page(self):
- """goes to the last page"""
- await self.show_page(self.maximum_pages)
-
- async def next_page(self):
- """goes to the next page"""
- await self.checked_show_page(self.current_page + 1)
-
- async def previous_page(self):
- """goes to the previous page"""
- await self.checked_show_page(self.current_page - 1)
-
- async def show_current_page(self):
- if self.paginating:
- await self.show_page(self.current_page)
-
- async def numbered_page(self):
- """lets you type a page number to go to"""
- to_delete = []
- to_delete.append(
- await self.channel.send('What page do you want to go to?'))
-
- def message_check(m):
- return m.author == self.author and \
- self.channel == m.channel and \
- m.content.isdigit()
-
- try:
- msg = await self.bot.wait_for(
- 'message',
- check=message_check,
- timeout=30.0
- )
- except asyncio.TimeoutError:
- to_delete.append(await self.channel.send('Took too long.'))
- await asyncio.sleep(5)
- else:
- page = int(msg.content)
- to_delete.append(msg)
- if page != 0 and page <= self.maximum_pages:
- await self.show_page(page)
- else:
- to_delete.append(await self.channel.send(
- f'Invalid page given. ({page}/{self.maximum_pages})'))
- await asyncio.sleep(5)
-
- try:
- await self.channel.delete_messages(to_delete)
- except Exception:
- pass
-
- async def show_help(self):
- """shows this message"""
- messages = ['Welcome to the interactive paginator!\n']
- messages.append(
- 'This interactively allows you to see pages of text by navigating with ' \
- 'reactions. They are as follows:\n')
-
- for (emoji, func) in self.reaction_emojis:
- messages.append(f'{emoji} {func.__doc__}')
-
- embed = self.embed.copy()
- embed.clear_fields()
- embed.description = '\n'.join(messages)
- embed.set_footer(
- text=f'We were on page {self.current_page} before this message.')
- await self.message.edit(content=None, embed=embed)
-
- async def go_back_to_current_page():
- await asyncio.sleep(60.0)
- await self.show_current_page()
-
- self.bot.loop.create_task(go_back_to_current_page())
-
- async def stop_pages(self):
- """stops the interactive pagination session"""
- await self.message.delete()
- self.paginating = False
-
- def react_check(self, reaction, user):
- if user is None or user.id != self.author.id:
- return False
-
- if reaction.message.id != self.message.id:
- return False
-
- for (emoji, func) in self.reaction_emojis:
- if reaction.emoji == emoji:
- self.match = func
- return True
- return False
-
- async def paginate(self):
- """Actually paginate the entries and run the interactive loop if necessary."""
- first_page = self.show_page(1, first=True)
- if not self.paginating:
- await first_page
- else:
- # allow us to react to reactions right away if we're paginating
- self.bot.loop.create_task(first_page)
-
- while self.paginating:
- try:
- reaction, user = await self.bot.wait_for(
- 'reaction_add',
- check=self.react_check,
- timeout=self.delete_after
- )
- except asyncio.TimeoutError:
- self.paginating = False
- try:
- await self.message.delete()
- except:
- pass
- finally:
- break
-
- try:
- await self.message.remove_reaction(reaction, user)
- except:
- pass # can't remove it so don't bother doing so
-
- await self.match()
-
-
-class FieldPages(Pages):
- """Similar to Pages except entries should be a list of
- tuples having (key, value) to show as embed fields instead.
- """
-
- def __init__(self, ctx, *, entries, per_page=12, show_entry_count=True,
- title, thumbnail, footericon, footertext,
- embed_color=discord.Color.blurple()):
- super().__init__(ctx, entries=entries, per_page=per_page,
- show_entry_count=show_entry_count, title=title,
- thumbnail=thumbnail, footericon=footericon,
- footertext=footertext, embed_color=embed_color)
-
- def prepare_embed(self, entries, page, *, first=False):
- self.embed.clear_fields()
-
- for key, value in entries:
- self.embed.add_field(name=key, value=value, inline=False)
-
- self.embed.title = self.title
-
- if self.maximum_pages > 1:
- if self.show_entry_count:
- text = f' [{page}/{self.maximum_pages}]'
- else:
- text = f' [{page}/{self.maximum_pages}]'
- self.embed.title = self.title + text
-
- self.embed.set_footer(icon_url=self.footericon, text=self.footertext)
- self.embed.set_thumbnail(url=self.thumbnail)
-
-
-class TextPages(Pages):
- """Uses a commands.Paginator internally to paginate some text."""
-
- def __init__(self, ctx, text, *, prefix='```', suffix='```',
- max_size=2000):
- paginator = CommandPaginator(prefix=prefix, suffix=suffix,
- max_size=max_size - 200)
- for line in text.split('\n'):
- paginator.add_line(line)
-
- super().__init__(ctx, entries=paginator.pages, per_page=1,
- show_entry_count=False)
-
- def get_page(self, page):
- return self.entries[page - 1]
-
- def get_embed(self, entries, page, *, first=False):
- return None
-
- def get_content(self, entry, page, *, first=False):
- if self.maximum_pages > 1:
- return f'{entry}\nPage {page}/{self.maximum_pages}'
- return entry
diff --git a/utils/functions/version.py b/utils/functions/version.py
deleted file mode 100644
index 9aaf3ec..0000000
--- a/utils/functions/version.py
+++ /dev/null
@@ -1,12 +0,0 @@
-class Version:
- def __init__(self, major: int, minor: int, patch: int, **kwargs):
- self.major: int = major
- self.minor: int = minor
- self.patch: int = patch
-
- self.pre_release = kwargs.get('pre_release', '')
- self.build = kwargs.get('build', '')
-
- def __str__(self) -> str:
- build = self.build[:10]
- return f'v{self.major}.{self.minor}.{self.patch}{self.pre_release}+{build}'
diff --git a/utils/images/blank_credit_card.png b/utils/images/blank_credit_card.png
deleted file mode 100644
index b0e5a57..0000000
Binary files a/utils/images/blank_credit_card.png and /dev/null differ
diff --git a/utils/images/gnous.png b/utils/images/gnous.png
deleted file mode 100644
index 0cbfdcf..0000000
Binary files a/utils/images/gnous.png and /dev/null differ
diff --git a/utils/locales/en/LC_MESSAGES/admin.po b/utils/locales/en/LC_MESSAGES/admin.po
deleted file mode 100644
index 93677bd..0000000
--- a/utils/locales/en/LC_MESSAGES/admin.po
+++ /dev/null
@@ -1,61 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Please enter a reason"
-msgstr ""
-
-msgid "Unable to ban this user"
-msgstr ""
-
-msgid "Unable to kick this user"
-msgstr ""
-
-msgid "last warns"
-msgstr ""
-
-msgid "More than 2 warns"
-msgstr ""
-
-msgid "has more than 2 warns"
-msgstr "has more than 2 warns, what do you want to do ?"
-
-msgid "ignore"
-msgstr ""
-
-msgid "Took too long. Aborting."
-msgstr ""
-
-msgid "got a warn"
-msgstr ""
-
-msgid "Reason"
-msgstr ""
-
-msgid "WarnModel with id"
-msgstr ""
-
-msgid "successfully removed"
-msgstr ""
-
-msgid "successfully edited"
-msgstr ""
-
-msgid "Unable to find this language"
-msgstr ""
-
-msgid "Language changed successfully"
-msgstr ""
diff --git a/utils/locales/en/LC_MESSAGES/admin_help.po b/utils/locales/en/LC_MESSAGES/admin_help.po
deleted file mode 100644
index 94d24bd..0000000
--- a/utils/locales/en/LC_MESSAGES/admin_help.po
+++ /dev/null
@@ -1,252 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-###########################################################################
-########################## SAY ########################################
-###########################################################################
-
-msgid '_say'
-msgstr ''
-
-msgid '_say_short'
-msgstr '_say_short'
-
-msgid '_say_usage'
-msgstr '_say_usage'
-
-###########################################################################
-
-msgid '_say_edit'
-msgstr ''
-
-msgid '_say_edit__help'
-msgstr ''
-
-msgid '_say_edit__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_say_to'
-msgstr ''
-
-msgid '_say_to__help'
-msgstr ''
-
-msgid '_say_to__usage'
-msgstr ''
-
-###########################################################################
-########################## BAN ########################################
-###########################################################################
-msgid '_ban'
-msgstr ''
-
-msgid '_ban__help'
-msgstr ''
-
-msgid '_ban__usage'
-msgstr ''
-
-###########################################################################
-########################## KICK #######################################
-###########################################################################
-
-msgid '_kick'
-msgstr ''
-
-msgid '_kick__help'
-msgstr ''
-
-msgid '_kick__usage'
-msgstr ''
-
-###########################################################################
-########################## CLEAR ######################################
-###########################################################################
-
-msgid '_clear'
-msgstr ''
-
-msgid '_clear__help'
-msgstr ''
-
-msgid '_clear__usage'
-msgstr ''
-
-###########################################################################
-########################## REACT ######################################
-###########################################################################
-
-msgid '_react'
-msgstr ''
-
-msgid '_react__help'
-msgstr ''
-
-msgid '_react__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_react_remove'
-msgstr ''
-
-msgid '_react_remove__help'
-msgstr ''
-
-msgid '_react_remove__usage'
-msgstr ''
-
-###########################################################################
-########################## DELETE #####################################
-###########################################################################
-
-msgid '_delete'
-msgstr ''
-
-msgid '_delete__help'
-msgstr ''
-
-msgid '_delete__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_delete_from'
-msgstr ''
-
-msgid '_delete_from__help'
-msgstr ''
-
-msgid '_delete_from__usage'
-msgstr ''
-
-###########################################################################
-########################## WARN #######################################
-###########################################################################
-
-msgid '_warn'
-msgstr ''
-
-msgid '_warn__help'
-msgstr ''
-
-msgid '_warn__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_warn_new'
-msgstr ''
-
-msgid '_warn_new__help'
-msgstr ''
-
-msgid '_warn_new__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_warn_remove'
-msgstr ''
-
-msgid '_warn_remove__help'
-msgstr ''
-
-msgid '_warn_remove__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_warn_show'
-msgstr ''
-
-msgid '_warn_show__help'
-msgstr ''
-
-msgid '_warn_show__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_warn_edit'
-msgstr ''
-
-msgid '_warn_edit__help'
-msgstr ''
-
-msgid '_warn_edit__usage'
-msgstr ''
-
-###########################################################################
-########################## LANGUAGE ###################################
-###########################################################################
-
-msgid '_language'
-msgstr ''
-
-msgid '_language__help'
-msgstr ''
-
-msgid '_language__usage'
-msgstr ''
-
-###########################################################################
-########################## PREFIX #####################################
-###########################################################################
-
-msgid '_prefix'
-msgstr ''
-
-msgid '_prefix__help'
-msgstr ''
-
-msgid '_prefix__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_prefix_add'
-msgstr ''
-
-msgid '_prefix_add__help'
-msgstr ''
-
-msgid '_prefix_add__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_prefix_remove'
-msgstr ''
-
-msgid '_prefix_remove__help'
-msgstr ''
-
-msgid '_prefix_remove__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_prefix_list'
-msgstr ''
-
-msgid '_prefix_list__help'
-msgstr ''
-
-msgid '_prefix_list__usage'
-msgstr ''
diff --git a/utils/locales/en/LC_MESSAGES/base.po b/utils/locales/en/LC_MESSAGES/base.po
deleted file mode 100644
index 3ecd6d4..0000000
--- a/utils/locales/en/LC_MESSAGES/base.po
+++ /dev/null
@@ -1,62 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Starting..."
-msgstr ""
-
-msgid "Could not set up PostgreSQL..."
-msgstr ""
-
-msgid "Launch without loading the module"
-msgstr ""
-
-msgid "Search for update"
-msgstr ""
-
-msgid "Checking for update..."
-msgstr ""
-
-msgid "A new version is available !"
-msgstr ""
-
-msgid "Update ? [Y/n] "
-msgstr ""
-
-msgid "Downloading..."
-msgstr ""
-
-msgid "Tuxbot is up to date"
-msgstr ""
-
-msgid "Failed to load extension : "
-msgstr ""
-
-msgid "Extension loaded successfully : "
-msgstr ""
-
-msgid "This command cannot be used in private messages."
-msgstr ""
-
-msgid "Sorry. This command is disabled and cannot be used."
-msgstr ""
-
-msgid "In "
-msgstr ""
-
-msgid "Ready:"
-msgstr ""
-
diff --git a/utils/locales/en/LC_MESSAGES/help.po b/utils/locales/en/LC_MESSAGES/help.po
deleted file mode 100644
index 6e63ec3..0000000
--- a/utils/locales/en/LC_MESSAGES/help.po
+++ /dev/null
@@ -1,43 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid 'main_page.description'
-msgstr "When using commands, **<>** means a **required argument** and **[]** means an **optional** argument.\n***(Don't type these symbols!)***"
-
-msgid 'main_page.commands'
-msgstr 'Commands'
-
-msgid 'main_page.footer'
-msgstr '- Send {}help to see more help about a command.'
-
-msgid 'main_page.not_found'
-msgstr 'No command called "{}" found.'
-
-msgid 'command_help.subcommands'
-msgstr 'Subcommands'
-
-msgid 'command_help.aliases'
-msgstr 'Aliases'
-
-msgid 'command_help.no_aliases'
-msgstr 'No aliases'
-
-msgid 'command_help.params'
-msgstr 'Parameters'
-
-msgid 'command_help.usage'
-msgstr 'Usage'
\ No newline at end of file
diff --git a/utils/locales/en/LC_MESSAGES/logs.po b/utils/locales/en/LC_MESSAGES/logs.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/en/LC_MESSAGES/logs.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/en/LC_MESSAGES/poll.po b/utils/locales/en/LC_MESSAGES/poll.po
deleted file mode 100644
index 320f5d4..0000000
--- a/utils/locales/en/LC_MESSAGES/poll.po
+++ /dev/null
@@ -1,20 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-#: launcher.py:51
-msgid "**Preparation...**"
-msgstr ""
diff --git a/utils/locales/en/LC_MESSAGES/poll_help.po b/utils/locales/en/LC_MESSAGES/poll_help.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/en/LC_MESSAGES/poll_help.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/en/LC_MESSAGES/useful.po b/utils/locales/en/LC_MESSAGES/useful.po
deleted file mode 100644
index 904dd0b..0000000
--- a/utils/locales/en/LC_MESSAGES/useful.po
+++ /dev/null
@@ -1,83 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Information about TuxBot"
-msgstr ""
-
-msgid "Latest changes"
-msgstr ""
-
-msgid "Development"
-msgstr ""
-
-msgid "physical memory"
-msgstr ""
-
-msgid "virtual memory"
-msgstr ""
-
-msgid "Servers count"
-msgstr ""
-
-msgid "Channels count"
-msgstr ""
-
-msgid "Members count"
-msgstr ""
-
-msgid "Links"
-msgstr ""
-
-msgid "Files"
-msgstr ""
-
-msgid "Lines"
-msgstr ""
-
-msgid "Invite"
-msgstr ""
-
-msgid "Contributors"
-msgstr ""
-
-msgid "ipv6 not available"
-msgstr "Error, this address is not available in IPv6."
-
-msgid "Information for"
-msgstr ""
-
-msgid "Belongs to :"
-msgstr ""
-
-msgid "Is located at :"
-msgstr ""
-
-msgid "info not available"
-msgstr ""
-
-msgid "Headers of"
-msgstr ""
-
-msgid "Cannot connect to host"
-msgstr ""
-
-msgid "git repo"
-msgstr "TuxBot-Bot's repository"
-
-msgid "git text"
-msgstr "Whoa, do you want to see my Gitea repository to dissect me? No problem ! I am a Bot, I do not feel the pain! \n https://git.gnous.eu/gnouseu/tuxbot-bot"
-
diff --git a/utils/locales/en/LC_MESSAGES/useful_help.po b/utils/locales/en/LC_MESSAGES/useful_help.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/en/LC_MESSAGES/useful_help.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/en/LC_MESSAGES/user.po b/utils/locales/en/LC_MESSAGES/user.po
deleted file mode 100644
index e69de29..0000000
diff --git a/utils/locales/en/LC_MESSAGES/user_help.po b/utils/locales/en/LC_MESSAGES/user_help.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/en/LC_MESSAGES/user_help.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/en/LC_MESSAGES/utils.po b/utils/locales/en/LC_MESSAGES/utils.po
deleted file mode 100644
index 01482bf..0000000
--- a/utils/locales/en/LC_MESSAGES/utils.po
+++ /dev/null
@@ -1,22 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Unable to find the user..."
-msgstr ""
-
-msgid "Unable to find the message"
-msgstr ""
\ No newline at end of file
diff --git a/utils/locales/fr/LC_MESSAGES/admin.po b/utils/locales/fr/LC_MESSAGES/admin.po
deleted file mode 100644
index 83de253..0000000
--- a/utils/locales/fr/LC_MESSAGES/admin.po
+++ /dev/null
@@ -1,61 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Please enter a reason"
-msgstr "Merci d'entrer une raison"
-
-msgid "Unable to ban this user"
-msgstr "Impossible de bannir cet utilisateur"
-
-msgid "Unable to kick this user"
-msgstr "Impossible d'expulser cet utilisateur"
-
-msgid "last warns"
-msgstr "derniers avertissements"
-
-msgid "More than 2 warns"
-msgstr "Plus de 2 avertissements"
-
-msgid "has more than 2 warns"
-msgstr "a plus de 2 avertissements, que voulez-vous faire?"
-
-msgid "ignore"
-msgstr "ignorer"
-
-msgid "Took too long. Aborting."
-msgstr "Temps expiré. Abandons."
-
-msgid "got a warn"
-msgstr "a recu un avertissement"
-
-msgid "Reason"
-msgstr "Raison"
-
-msgid "WarnModel with id"
-msgstr "L'avertissement avec l'id"
-
-msgid "successfully removed"
-msgstr "a été enlevé avec succes"
-
-msgid "successfully edited"
-msgstr "a été édité avec succes"
-
-msgid "Unable to find this language"
-msgstr "Impossible de trouver cette langue"
-
-msgid "Language changed successfully"
-msgstr "Langue changée avec succès"
diff --git a/utils/locales/fr/LC_MESSAGES/admin_help.po b/utils/locales/fr/LC_MESSAGES/admin_help.po
deleted file mode 100644
index 0df3a5b..0000000
--- a/utils/locales/fr/LC_MESSAGES/admin_help.po
+++ /dev/null
@@ -1,263 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-###########################################################################
-########################## SAY ########################################
-###########################################################################
-
-msgid '_say'
-msgstr 'Permet de faire en sorte que le TuxBot envoie votre message'
-
-msgid '_say__short'
-msgstr 'Faire parler TuxBot'
-
-msgid '_say_usage'
-msgstr '[sous-commande] '
-
-###########################################################################
-
-msgid '_say_edit'
-msgstr "Permet de modifier le contenu d'un message envoyé par TuxBot"
-
-msgid '_say_edit__short'
-msgstr 'Editer un message envoyé'
-
-msgid '_say_edit__usage'
-msgstr ' '
-
-###########################################################################
-
-msgid '_say_to'
-msgstr "Permet de faire en sorte que le TuxBot envoi votre message dans un autre salon ou en MP à quelqu'un"
-
-msgid '_say_to__short'
-msgstr 'Faire parler TuxBot dans un autre salon'
-
-msgid '_say_to__usage'
-msgstr " "
-
-###########################################################################
-########################## BAN ########################################
-###########################################################################
-msgid '_ban'
-msgstr 'Permet de bannir un membre'
-
-msgid '_ban__short'
-msgstr 'Bannir un membre'
-
-msgid '_ban__usage'
-msgstr ''
-
-###########################################################################
-########################## KICK #######################################
-###########################################################################
-
-msgid '_kick'
-msgstr "Permet d'expulser un membre"
-
-msgid '_kick__short'
-msgstr 'Expulser un membre'
-
-msgid '_kick__usage'
-msgstr ''
-
-###########################################################################
-########################## CLEAR ######################################
-###########################################################################
-
-msgid '_clear'
-msgstr 'Permet de supprimer un nombre donné de message'
-
-msgid '_clear__short'
-msgstr 'Supprime X messages'
-
-msgid '_clear__usage'
-msgstr ''
-
-###########################################################################
-########################## REACT ######################################
-###########################################################################
-
-msgid '_react'
-msgstr "Affiche l'aide relative a la commande `react`"
-
-msgid '_react__short'
-msgstr "Afficher l'aide pour `react`"
-
-msgid '_react__usage'
-msgstr '[sous-commande]'
-
-###########################################################################
-
-msgid '_react_add'
-msgstr "Permet d'ajouter une réaction à un message de la part de TuxBot"
-
-msgid '_react_add__short'
-msgstr 'Ajouter une réaction'
-
-msgid '_react_add__usage'
-msgstr ' <émoji>'
-
-###########################################################################
-
-msgid '_react_remove'
-msgstr "Permet d'enlever toutes les réactions d'un message"
-
-msgid '_react_remove__short'
-msgstr "Enlever toutes les réactions d'un message"
-
-msgid '_react_remove__usage'
-msgstr ''
-
-###########################################################################
-########################## DELETE #####################################
-###########################################################################
-
-msgid '_delete'
-msgstr 'Permet de supprimer un message'
-
-msgid '_delete__short'
-msgstr 'Supprimer un message'
-
-msgid '_delete__usage'
-msgstr '[sous-commande] '
-
-###########################################################################
-
-msgid '_delete_from'
-msgstr 'Permet de supprimer un message dans un autre salon'
-
-msgid '_delete_from__short'
-msgstr 'Supprimer un message dans un autre salon'
-
-msgid '_delete_from__usage'
-msgstr ' '
-
-###########################################################################
-########################## WARN #######################################
-###########################################################################
-
-msgid '_warn'
-msgstr "Permet d'afficher les derniers avertissements donnés sur ce serveur"
-
-msgid '_warn__short'
-msgstr 'Lister les derniers avertissements'
-
-msgid '_warn__usage'
-msgstr '[sous-commande]'
-
-###########################################################################
-
-msgid '_warn_add'
-msgstr "Permet d'ajouter un avertissement à un membre en donnant une raison"
-
-msgid '_warn_add__short'
-msgstr 'Ajouter un avertissement a un membre'
-
-msgid '_warn_add__usage'
-msgstr ' '
-
-###########################################################################
-
-msgid '_warn_remove'
-msgstr "Permet de supprimer un avertissement qui a été donné à un membre"
-
-msgid '_warn_remove__short'
-msgstr "Retirer l'avertissement d'un membre"
-
-msgid '_warn_remove__usage'
-msgstr ""
-
-###########################################################################
-
-msgid '_warn_show'
-msgstr "Permet d'afficher les derniers avertissements donnés à un membre"
-
-msgid '_warn_show__short'
-msgstr "Lister les derniers avertissements d'un membre"
-
-msgid '_warn_show__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_warn_edit'
-msgstr "Permet de modifier la raison de l'avertissement donné à un membre"
-
-msgid '_warn_edit__short'
-msgstr "Modifier la raison d'un avertissement"
-
-msgid '_warn_edit__usage'
-msgstr " "
-
-###########################################################################
-########################## LANGUAGE ###################################
-###########################################################################
-
-msgid '_language'
-msgstr 'Permet de définir la langue utilisée sur ce serveur'
-
-msgid '_language__short'
-msgstr 'Définir la langue de Tuxbot'
-
-msgid '_language__usage'
-msgstr ''
-
-###########################################################################
-########################## PREFIX #####################################
-###########################################################################
-
-msgid '_prefix'
-msgstr "Affiche l'aide relative a la commande `prefix`"
-
-msgid '_prefix__short'
-msgstr "Afficher l'aide pour `prefix`"
-
-msgid '_prefix__usage'
-msgstr '[sous-commande]'
-
-###########################################################################
-
-msgid '_prefix_add'
-msgstr "Permet d'ajouter un nouveau préfixe pour ce serveur"
-
-msgid '_prefix_add__short'
-msgstr 'Ajouter un préfixe pour ce serveur'
-
-msgid '_prefix_add__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_prefix_remove'
-msgstr "Permet retirer un préfixe pour ce serveur"
-
-msgid '_prefix_remove__short'
-msgstr 'Retirer un préfixe pour ce serveur'
-
-msgid '_prefix_remove__usage'
-msgstr ''
-
-###########################################################################
-
-msgid '_prefix_list'
-msgstr "Permet d'afficher tous les prefixes définis pour ce serveur"
-
-msgid '_prefix_list__short'
-msgstr 'Lister les prefixes pour ce serveur'
-
-msgid '_prefix_list__usage'
-msgstr '⠀'
diff --git a/utils/locales/fr/LC_MESSAGES/base.po b/utils/locales/fr/LC_MESSAGES/base.po
deleted file mode 100644
index 61a4d25..0000000
--- a/utils/locales/fr/LC_MESSAGES/base.po
+++ /dev/null
@@ -1,62 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Starting..."
-msgstr "Démarrage..."
-
-msgid "Could not set up PostgreSQL..."
-msgstr "Impossible de lancer PostgreSQL..."
-
-msgid "Launch without loading the module"
-msgstr "Lancer sans charger le module "
-
-msgid "Search for update"
-msgstr "Rechercher les mises à jour"
-
-msgid "Checking for update..."
-msgstr "Recherche de mise à jour..."
-
-msgid "A new version is available !"
-msgstr "Une nouvelle version est disponible !"
-
-msgid "Update ? [Y/n] "
-msgstr "Mettre à jour ? [O/n]"
-
-msgid "Downloading..."
-msgstr "Téléchargement..."
-
-msgid "Tuxbot is up to date"
-msgstr "Tuxbot est à jour"
-
-msgid "Failed to load extension : "
-msgstr "Impossible de charger l'extension : "
-
-msgid "Extension loaded successfully : "
-msgstr "Extension chargée avec succes : "
-
-msgid "This command cannot be used in private messages."
-msgstr "Cette commande ne peut pas être utilisée en message privé."
-
-msgid "Sorry. This command is disabled and cannot be used."
-msgstr "Désolé mais cette commande est désactivée."
-
-msgid "In "
-msgstr "Dans "
-
-msgid "Ready:"
-msgstr "Prêt :"
-
diff --git a/utils/locales/fr/LC_MESSAGES/help.po b/utils/locales/fr/LC_MESSAGES/help.po
deleted file mode 100644
index 232f3a3..0000000
--- a/utils/locales/fr/LC_MESSAGES/help.po
+++ /dev/null
@@ -1,43 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid 'main_page.description'
-msgstr "Lorsque vous utilisez les commandes, **<>** correspond à un argument **obligatoire** et **[]** à un argument **optionnel**.\n***(N'écrivez pas ces symboles!)***"
-
-msgid 'main_page.commands'
-msgstr 'Commandes'
-
-msgid 'main_page.footer'
-msgstr "- Envoyez {}help pour avoir plus d'aide sur la commande."
-
-msgid 'main_page.not_found'
-msgstr 'Impossible de trouver la commande {}.'
-
-msgid 'command_help.subcommands'
-msgstr 'Sous-commandes'
-
-msgid 'command_help.aliases'
-msgstr 'Alias'
-
-msgid 'command_help.no_aliases'
-msgstr 'Aucun alias'
-
-msgid 'command_help.params'
-msgstr 'Parametres'
-
-msgid 'command_help.usage'
-msgstr 'Utilisation'
\ No newline at end of file
diff --git a/utils/locales/fr/LC_MESSAGES/logs.po b/utils/locales/fr/LC_MESSAGES/logs.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/fr/LC_MESSAGES/logs.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/fr/LC_MESSAGES/logs_help.po b/utils/locales/fr/LC_MESSAGES/logs_help.po
deleted file mode 100644
index 12ddb52..0000000
--- a/utils/locales/fr/LC_MESSAGES/logs_help.po
+++ /dev/null
@@ -1,19 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "_uptime__short"
-msgstr "Retourne depuis quand TuxBot est en ligne."
\ No newline at end of file
diff --git a/utils/locales/fr/LC_MESSAGES/poll.po b/utils/locales/fr/LC_MESSAGES/poll.po
deleted file mode 100644
index ca29875..0000000
--- a/utils/locales/fr/LC_MESSAGES/poll.po
+++ /dev/null
@@ -1,20 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-#: launcher.py:51
-msgid "**Preparation...**"
-msgstr "**Préparation...**"
diff --git a/utils/locales/fr/LC_MESSAGES/poll_help.po b/utils/locales/fr/LC_MESSAGES/poll_help.po
deleted file mode 100644
index f379622..0000000
--- a/utils/locales/fr/LC_MESSAGES/poll_help.po
+++ /dev/null
@@ -1,40 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-###########################################################################
-########################## POLLS #####################################
-###########################################################################
-
-msgid '_poll'
-msgstr "Affiche l'aide relative a la commande `sondage`"
-
-msgid '_poll__short'
-msgstr "Afficher l'aide pour `sondage`"
-
-msgid '_poll__usage'
-msgstr '[sous-commande]'
-
-###########################################################################
-
-msgid '_poll_create'
-msgstr "Créez un sondage basé sur les réactions ! *(**BETA!** ajoutez `--anonyme` pour rendre les réponses anonymes)*"
-
-msgid '_poll_create__short'
-msgstr 'Créer un sondage'
-
-msgid '_poll_create__usage'
-msgstr ' | | | [réponse C] | [réponse D] | [...]'
diff --git a/utils/locales/fr/LC_MESSAGES/useful.po b/utils/locales/fr/LC_MESSAGES/useful.po
deleted file mode 100644
index 89525c0..0000000
--- a/utils/locales/fr/LC_MESSAGES/useful.po
+++ /dev/null
@@ -1,82 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Information about TuxBot"
-msgstr "Informations sur TuxBot"
-
-msgid "Latest changes"
-msgstr "Derniers changements"
-
-msgid "Development"
-msgstr "Développement"
-
-msgid "physical memory"
-msgstr "mémoire physique"
-
-msgid "virtual memory"
-msgstr "mémoire virtuelle"
-
-msgid "Servers count"
-msgstr "Nombre de serveurs"
-
-msgid "Channels count"
-msgstr "Nombre de salons"
-
-msgid "Members count"
-msgstr "Nombre de membres"
-
-msgid "Links"
-msgstr "Liens"
-
-msgid "Files"
-msgstr "Fichiers"
-
-msgid "Lines"
-msgstr "Lignes"
-
-msgid "Invite"
-msgstr "Invitation"
-
-msgid "Contributors"
-msgstr "Contributeurs"
-
-msgid "ipv6 not available"
-msgstr "Erreur, cette adresse n'est pas disponible en IPv6."
-
-msgid "Information for"
-msgstr "Informations pour"
-
-msgid "Belongs to :"
-msgstr "Appartient à :"
-
-msgid "Is located at :"
-msgstr "Se situe à :"
-
-msgid "info not available"
-msgstr "Erreur, impossible d'obtenir des informations sur cette adresse IP"
-
-msgid "Headers of"
-msgstr "Entêtes de"
-
-msgid "Cannot connect to host"
-msgstr "Impossible de se connecter à l'hôte"
-
-msgid "git repo"
-msgstr "Repos TuxBot-Bot"
-
-msgid "git text"
-msgstr "Whoa tu veux voir mon repos Gitea pour me disséquer ? Pas de soucis ! Je suis un Bot, je ne ressens pas la douleur! \n https://git.gnous.eu/gnouseu/tuxbot-bot"
diff --git a/utils/locales/fr/LC_MESSAGES/useful_help.po b/utils/locales/fr/LC_MESSAGES/useful_help.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/fr/LC_MESSAGES/useful_help.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/fr/LC_MESSAGES/user.po b/utils/locales/fr/LC_MESSAGES/user.po
deleted file mode 100644
index e69de29..0000000
diff --git a/utils/locales/fr/LC_MESSAGES/user_help.po b/utils/locales/fr/LC_MESSAGES/user_help.po
deleted file mode 100644
index cdc6fcd..0000000
--- a/utils/locales/fr/LC_MESSAGES/user_help.po
+++ /dev/null
@@ -1,17 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
diff --git a/utils/locales/fr/LC_MESSAGES/utils.po b/utils/locales/fr/LC_MESSAGES/utils.po
deleted file mode 100644
index 9a8d3e6..0000000
--- a/utils/locales/fr/LC_MESSAGES/utils.po
+++ /dev/null
@@ -1,22 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR ORGANIZATION
-# FIRST AUTHOR , YEAR.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-09-08 19:04+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-
-
-msgid "Unable to find the user..."
-msgstr "Impossibe de trouver l'utilisateur..."
-
-msgid "Unable to find the message"
-msgstr "Impossible de trouver le message"
\ No newline at end of file
diff --git a/utils/models/__init__.py b/utils/models/__init__.py
deleted file mode 100644
index 36ba5cc..0000000
--- a/utils/models/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import databases
-import sqlalchemy
-from utils.functions import Config
-
-conf_postgresql = Config('./configs/config.cfg')["postgresql"]
-postgresql = 'postgresql://{}:{}@{}/{}'.format(
- conf_postgresql.get("Username"), conf_postgresql.get("Password"),
- conf_postgresql.get("Host"), conf_postgresql.get("DBName"))
-
-database = databases.Database(postgresql)
-metadata = sqlalchemy.MetaData()
-
-engine = sqlalchemy.create_engine(str(database.url))
-metadata.create_all(engine)
-
-from .warn import WarnModel
-from .poll import PollModel, ResponsesModel
-from .alias import AliasesModel
diff --git a/utils/models/alias.py b/utils/models/alias.py
deleted file mode 100644
index 4a1a96c..0000000
--- a/utils/models/alias.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import orm
-from . import database, metadata
-
-
-class AliasesModel(orm.Model):
- __tablename__ = 'aliases'
- __database__ = database
- __metadata__ = metadata
-
- id = orm.Integer(primary_key=True)
- user_id = orm.String(max_length=18)
- alias = orm.String(max_length=255)
- command = orm.String(max_length=255)
- guild = orm.String(max_length=255)
diff --git a/utils/models/poll.py b/utils/models/poll.py
deleted file mode 100644
index a2f793e..0000000
--- a/utils/models/poll.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import orm
-from . import database, metadata
-
-
-class ResponsesModel(orm.Model):
- __tablename__ = 'responses'
- __database__ = database
- __metadata__ = metadata
-
- id = orm.Integer(primary_key=True)
- user = orm.String(max_length=18)
-
- choice = orm.Integer()
-
-
-class PollModel(orm.Model):
- __tablename__ = 'polls'
- __database__ = database
- __metadata__ = metadata
-
- id = orm.Integer(primary_key=True)
- channel_id = orm.String(max_length=18)
- message_id = orm.String(max_length=18)
-
- content = orm.JSON()
- is_anonymous = orm.Boolean()
-
- available_choices = orm.Integer()
- choice = orm.ForeignKey(ResponsesModel)
diff --git a/utils/models/warn.py b/utils/models/warn.py
deleted file mode 100644
index 77f8833..0000000
--- a/utils/models/warn.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import orm
-from . import database, metadata
-
-
-class WarnModel(orm.Model):
- __tablename__ = 'warns'
- __database__ = database
- __metadata__ = metadata
-
- id = orm.Integer(primary_key=True)
- server_id = orm.String(max_length=18)
- user_id = orm.String(max_length=18)
- reason = orm.String(max_length=255)
- created_at = orm.DateTime()