diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dictionaries/romain.xml b/.idea/dictionaries/romain.xml
index 0299aeb..3f737c1 100644
--- a/.idea/dictionaries/romain.xml
+++ b/.idea/dictionaries/romain.xml
@@ -2,6 +2,7 @@
commandstats
+ francais
ipinfo
iplocalise
localiseip
diff --git a/Makefile b/Makefile
index 572fa01..59bc550 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,7 @@
PYTHON = python
-VENV = ~/tuxvenv
+VENV = venv
+
+XGETTEXT_FLAGS = --no-wrap --language='python' --keyword=_ --from-code='UTF-8' --msgid-bugs-address='rick@gnous.eu' --width=79 --package-name='Tuxbot-bot'
# Init
main:
@@ -12,4 +14,20 @@ update:
# Blackify code
reformat:
- $(PYTHON) -m black `git ls-files "*.py"`
\ No newline at end of file
+ $(PYTHON) -m black `git ls-files "*.py"`
+
+# Translations
+xgettext:
+ for cog in tuxbot/cogs/*/; do \
+ xgettext `find $$cog -type f -name '*.py'` --output=$$cog/locales/messages.pot $(XGETTEXT_FLAGS); \
+ done
+msginit:
+ for cog in tuxbot/cogs/*/; do \
+ msginit --input=$$cog/locales/messages.pot --output=$$cog/locales/fr-FR.po --locale=fr_FR.UTF-8 --no-translator; \
+ msginit --input=$$cog/locales/messages.pot --output=$$cog/locales/en-US.po --locale=en_US.UTF-8 --no-translator; \
+ done
+msgmerge:
+ for cog in tuxbot/cogs/*/; do \
+ msgmerge --update $$cog/locales/fr-FR.po $$cog/locales/messages.pot; \
+ msgmerge --update $$cog/locales/en-US.po $$cog/locales/messages.pot; \
+ done
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 15755a6..94e1e30 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,6 +17,7 @@ install_requires =
async-timeout==3.0.1
asyncpg==0.20.1
attrs==19.3.0
+ babel==2.8.0
black==19.10b0
braceexpand==0.1.5
cachetools==4.1.0
diff --git a/tuxbot/__main__.py b/tuxbot/__main__.py
index ae7e6d4..b102edb 100644
--- a/tuxbot/__main__.py
+++ b/tuxbot/__main__.py
@@ -31,12 +31,12 @@ def list_instances() -> NoReturn:
with data_manager.config_file.open() as fs:
datas = json.load(fs)
- instances = list(datas.keys())
-
info = {"title": "Instances", "rows": []}
- for instance in instances:
- info["rows"].append(f"-> {instance}")
+ for instance, details in datas.items():
+ info["rows"].append(
+ f"-> {instance} " f"{'up' if details.get('IS_RUNNING') else 'down'}"
+ )
print(bordered(info))
sys.exit(0)
diff --git a/tuxbot/cogs/admin/__init__.py b/tuxbot/cogs/admin/__init__.py
new file mode 100644
index 0000000..463e1d1
--- /dev/null
+++ b/tuxbot/cogs/admin/__init__.py
@@ -0,0 +1,18 @@
+from collections import namedtuple
+
+from .admin import Admin
+from ...core.bot import Tux
+
+VersionInfo = namedtuple("VersionInfo", "major minor micro releaselevel")
+version_info = VersionInfo(major=2, minor=0, micro=0, releaselevel="alpha")
+
+__version__ = "v{}.{}.{}-{}".format(
+ version_info.major,
+ version_info.minor,
+ version_info.micro,
+ version_info.releaselevel,
+).replace("\n", "")
+
+
+def setup(bot: Tux):
+ bot.add_cog(Admin(bot))
diff --git a/tuxbot/cogs/admin/admin.py b/tuxbot/cogs/admin/admin.py
new file mode 100644
index 0000000..6c1b13f
--- /dev/null
+++ b/tuxbot/cogs/admin/admin.py
@@ -0,0 +1,48 @@
+import logging
+
+import discord
+from discord.ext import commands
+
+from tuxbot.core import checks
+from tuxbot.core.bot import Tux
+from tuxbot.core.i18n import Translator, set_locale, _locale_key_value
+from tuxbot.core.utils.functions.extra import group_extra, ContextPlus
+
+log = logging.getLogger("tuxbot.cogs.admin")
+_ = Translator("Admin", __file__)
+
+
+class Admin(commands.Cog, name="Admin"):
+ def __init__(self, bot: Tux):
+ self.bot = bot
+
+ @group_extra(
+ name="lang",
+ aliases=["locale", "langue"],
+ deletable=True
+ )
+ @commands.guild_only()
+ @checks.is_admin()
+ async def _lang(self, ctx: ContextPlus):
+ """Manage lang settings."""
+
+ @_lang.command(name="set", aliases=["define", "choice"])
+ async def _lang_set(self, ctx: ContextPlus, lang: str):
+ try:
+ set_locale(lang.lower())
+ await ctx.send(
+ _("Locale changed to {lang} successfully")
+ .format(lang=f"`{lang}`")
+ )
+ except NotImplementedError:
+ await ctx.send(_("This locale isn't available, execute `lang list` to view available locales"))
+
+ @_lang.command(name="list", aliases=["liste", "all", "view"])
+ async def _lang_list(self, ctx: ContextPlus):
+ e = discord.Embed(
+ title=_("List of available locales: "),
+ description='\n'.join([i[0] for i in _locale_key_value.values()]),
+ color=0x36393E
+ )
+
+ await ctx.send(embed=e)
diff --git a/tuxbot/cogs/admin/locales/en-US.po b/tuxbot/cogs/admin/locales/en-US.po
new file mode 100644
index 0000000..fbf8e4f
--- /dev/null
+++ b/tuxbot/cogs/admin/locales/en-US.po
@@ -0,0 +1,32 @@
+# English translations for Tuxbot-bot package.
+# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the Tuxbot-bot package.
+# Automatically generated, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Tuxbot-bot\n"
+"Report-Msgid-Bugs-To: rick@gnous.eu\n"
+"POT-Creation-Date: 2020-06-11 00:59+0200\n"
+"PO-Revision-Date: 2020-06-10 00:38+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_US\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: tuxbot/cogs/admin/admin.py:33
+#, fuzzy, python-brace-format
+msgid "Locale changed to {lang} successfully"
+msgstr "Lang changed to {lang} successfully"
+
+#: tuxbot/cogs/admin/admin.py:37
+msgid ""
+"This locale isn't available, execute `lang list` to view available locales"
+msgstr ""
+
+#: tuxbot/cogs/admin/admin.py:42
+msgid "List of available locales: "
+msgstr ""
diff --git a/tuxbot/cogs/admin/locales/en-US.po~ b/tuxbot/cogs/admin/locales/en-US.po~
new file mode 100644
index 0000000..ca18c7c
--- /dev/null
+++ b/tuxbot/cogs/admin/locales/en-US.po~
@@ -0,0 +1,28 @@
+# English translations for Tuxbot-bot package.
+# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the Tuxbot-bot package.
+# Automatically generated, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Tuxbot-bot\n"
+"Report-Msgid-Bugs-To: rick@gnous.eu\n"
+"POT-Creation-Date: 2020-06-11 00:49+0200\n"
+"PO-Revision-Date: 2020-06-10 00:38+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_US\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: tuxbot/cogs/admin/admin.py:33
+#, fuzzy, python-brace-format
+msgid "Locale changed to {lang} successfully"
+msgstr "Lang changed to {lang} successfully"
+
+#: tuxbot/cogs/admin/admin.py:37
+msgid ""
+"This locale isn't available, execute `lang list` to view available locales"
+msgstr ""
diff --git a/tuxbot/cogs/admin/locales/fr-FR.po b/tuxbot/cogs/admin/locales/fr-FR.po
new file mode 100644
index 0000000..78cb879
--- /dev/null
+++ b/tuxbot/cogs/admin/locales/fr-FR.po
@@ -0,0 +1,35 @@
+# French translations for Tuxbot-bot package
+# Traductions françaises du paquet Tuxbot-bot.
+# Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the Tuxbot-bot package.
+# Automatically generated, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Tuxbot-bot\n"
+"Report-Msgid-Bugs-To: rick@gnous.eu\n"
+"POT-Creation-Date: 2020-06-11 00:59+0200\n"
+"PO-Revision-Date: 2020-06-10 00:38+0200\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: tuxbot/cogs/admin/admin.py:33
+#, fuzzy, python-brace-format
+msgid "Locale changed to {lang} successfully"
+msgstr "Langue changée pour {lang} avec succès"
+
+#: tuxbot/cogs/admin/admin.py:37
+msgid ""
+"This locale isn't available, execute `lang list` to view available locales"
+msgstr ""
+"Cette langue n'est pas disponible, exécutez `lang list` pour voir les "
+"langues disponibles"
+
+#: tuxbot/cogs/admin/admin.py:42
+msgid "List of available locales: "
+msgstr "Liste des langues disponibles : "
diff --git a/tuxbot/cogs/admin/locales/messages.pot b/tuxbot/cogs/admin/locales/messages.pot
new file mode 100644
index 0000000..7b5dc0f
--- /dev/null
+++ b/tuxbot/cogs/admin/locales/messages.pot
@@ -0,0 +1,31 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the Tuxbot-bot package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Tuxbot-bot\n"
+"Report-Msgid-Bugs-To: rick@gnous.eu\n"
+"POT-Creation-Date: 2020-06-11 00:59+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: tuxbot/cogs/admin/admin.py:33
+#, python-brace-format
+msgid "Locale changed to {lang} successfully"
+msgstr ""
+
+#: tuxbot/cogs/admin/admin.py:37
+msgid "This locale isn't available, execute `lang list` to view available locales"
+msgstr ""
+
+#: tuxbot/cogs/admin/admin.py:42
+msgid "List of available locales: "
+msgstr ""
diff --git a/tuxbot/cogs/anti_raid/anti_raid.py b/tuxbot/cogs/anti_raid/anti_raid.py
index 61f096c..41e6a7c 100644
--- a/tuxbot/cogs/anti_raid/anti_raid.py
+++ b/tuxbot/cogs/anti_raid/anti_raid.py
@@ -6,11 +6,11 @@ from tuxbot.core import checks
from tuxbot.core.bot import Tux
from tuxbot.core.i18n import Translator
-log = logging.getLogger("tuxbot.cogs.admin")
-T_ = Translator("Admin", __file__)
+log = logging.getLogger("tuxbot.cogs.anti_raid")
+T_ = Translator("AntiRaid", __file__)
-class Admin(commands.Cog, name="Admin"):
+class AntiRaid(commands.Cog, name="AntiRaid"):
def __init__(self, bot: Tux):
self.bot = bot
@@ -20,5 +20,5 @@ class Admin(commands.Cog, name="Admin"):
)
@commands.guild_only()
@checks.is_admin()
- async def _warn(self, ctx: commands.Context):
+ async def _anti_raid(self, ctx: commands.Context):
pass
diff --git a/tuxbot/core/bot.py b/tuxbot/core/bot.py
index 15d669d..61c0719 100644
--- a/tuxbot/core/bot.py
+++ b/tuxbot/core/bot.py
@@ -26,7 +26,7 @@ NAME = r"""
|_| \__,_/_/\_\_.__/ \___/ \__| |_.__/ \___/ \__|
"""
-packages: List[str] = ["jishaku", "tuxbot.cogs.warnings"]
+packages: List[str] = ["jishaku", "tuxbot.cogs.warnings", "tuxbot.cogs.admin"]
class Tux(commands.AutoShardedBot):
diff --git a/tuxbot/core/i18n.py b/tuxbot/core/i18n.py
index 7993910..dfb594b 100644
--- a/tuxbot/core/i18n.py
+++ b/tuxbot/core/i18n.py
@@ -1,29 +1,41 @@
import logging
import os
from pathlib import Path
-from typing import Callable, Union
+from typing import Callable, Union, Dict, List
-__all__ = [
- "get_locale",
- "set_locale",
- "reload_locales",
- "Translator",
-]
+from babel.messages.pofile import read_po
log = logging.getLogger("tuxbot.core.i18n")
_translators = []
+
_current_locale = "en-US"
+_locale_key_value: Dict[str, List[str]] = {
+ "en": ["english", "anglais", "en", "us"],
+ "fr": ["français", "francais", "french", "fr", "be"],
+}
+_available_locales: Dict[str, str] = {"en": "en-US", "fr": "fr-FR"}
def get_locale() -> str:
return _current_locale
+def find_locale(locale: str) -> str:
+ """We suppose `locale` is in `_locale_key_value.values()`"""
+
+ for key, val in _locale_key_value.items():
+ if locale in val:
+ return key
+
+
def set_locale(locale: str) -> None:
- global _current_locale
- _current_locale = locale
- reload_locales()
+ if not any(locale in values for values in _locale_key_value.values()):
+ raise NotImplementedError("This locale isn't implemented")
+ else:
+ global _current_locale
+ _current_locale = _available_locales.get(find_locale(locale))
+ reload_locales()
def reload_locales() -> None:
@@ -32,7 +44,7 @@ def reload_locales() -> None:
class Translator(Callable[[str], str]):
- """Class to load locales at init."""
+ """Class to load texts at init."""
def __init__(self, name: str, file_location: Union[str, Path, os.PathLike]):
"""Initializes the Translator object.
@@ -59,6 +71,12 @@ class Translator(Callable[[str], str]):
except KeyError:
return untranslated
+ def __repr__(self):
+ return "" % (
+ self.cog_name,
+ self.cog_folder,
+ )
+
def load_translations(self):
"""Loads the current translations.
@@ -66,7 +84,12 @@ class Translator(Callable[[str], str]):
self.translations = {}
locale_path = self.cog_folder / "locales" / f"{get_locale()}.po"
- ...
+ with locale_path.open("r") as f:
+ catalog = read_po(f)
+
+ for message in catalog:
+ if message.id:
+ self._add_translation(message.id, message.string)
def _add_translation(self, untranslated, translated):
if translated:
diff --git a/tuxbot/core/utils/functions/extra.py b/tuxbot/core/utils/functions/extra.py
index f675eba..4571200 100644
--- a/tuxbot/core/utils/functions/extra.py
+++ b/tuxbot/core/utils/functions/extra.py
@@ -20,7 +20,7 @@ class ContextPlus(commands.Context):
)
try:
- await self.bot.wait_for("reaction_add", timeout=60.0, check=check)
+ await self.bot.wait_for("reaction_add", timeout=45.0, check=check)
except asyncio.TimeoutError:
await message.remove_reaction("🗑", self.bot.user)
else: