fix(commands|Custom>alias): close TUXBOT-BOT-1A, close TUXBOT-BOT-1H, close TUXBOT-BOT-1J
This commit is contained in:
parent
c7ddba1bae
commit
b5ca338d6c
19 changed files with 198 additions and 365 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -43,3 +43,6 @@ build
|
|||
.env
|
||||
.envs/*
|
||||
!.envs/.local/
|
||||
|
||||
|
||||
data/settings/
|
68
Makefile
68
Makefile
|
@ -1,38 +1,74 @@
|
|||
PYTHON = python
|
||||
VENV = venv
|
||||
ifeq ($(ISPROD), 1)
|
||||
DOCKER_LOCAL := docker-compose -f production.yml
|
||||
else
|
||||
DOCKER_LOCAL := docker-compose -f local.yml
|
||||
endif
|
||||
|
||||
XGETTEXT_FLAGS = --no-wrap --language='python' --keyword=_ --from-code='UTF-8' --msgid-bugs-address='rick@gnous.eu' --width=79 --package-name='Tuxbot-bot'
|
||||
INSTANCE := preprod
|
||||
|
||||
DOCKER_TUXBOT := $(DOCKER_LOCAL) run --rm tuxbot
|
||||
VIRTUAL_ENV := venv
|
||||
PYTHON_PATH := $(VIRTUAL_ENV)/bin/python
|
||||
|
||||
XGETTEXT_FLAGS := --no-wrap --language='python' --keyword=_ --from-code='UTF-8' --msgid-bugs-address='rick@gnous.eu' --width=79 --package-name='Tuxbot-bot'
|
||||
|
||||
# Init
|
||||
.PHONY: main
|
||||
main:
|
||||
$(PYTHON) -m venv --clear $(VENV)
|
||||
$(VENV)/bin/pip install -U pip setuptools
|
||||
install:
|
||||
$(VENV)/bin/pip install .
|
||||
install-dev:
|
||||
$(VENV)/bin/pip install -r dev.requirements.txt
|
||||
update:
|
||||
$(VENV)/bin/pip install --upgrade --force-reinstall .
|
||||
update_soft:
|
||||
$(VENV)/bin/pip install --upgrade .
|
||||
$(PYTHON_PATH) -m venv --clear $(VENV)
|
||||
$(VIRTUAL_ENV)/bin/pip install -U pip setuptools
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
$(VIRTUAL_ENV)/bin/pip install .
|
||||
|
||||
.PHONY: install-dev
|
||||
install-dev:
|
||||
$(VIRTUAL_ENV)/bin/pip install -r dev.requirements.txt
|
||||
|
||||
.PHONY: update
|
||||
update:
|
||||
$(VIRTUAL_ENV)/bin/pip install --upgrade .
|
||||
|
||||
.PHONY: update-all
|
||||
update-all:
|
||||
$(VIRTUAL_ENV)/bin/pip install --upgrade --force-reinstall .
|
||||
|
||||
.PHONY: dev
|
||||
dev: black update
|
||||
tuxbot
|
||||
|
||||
# Docker
|
||||
.PHONY: docker
|
||||
docker:
|
||||
$(DOCKER_LOCAL) build
|
||||
$(DOCKER_LOCAL) up -d
|
||||
|
||||
.PHONY: docker-start
|
||||
docker-start:
|
||||
$(DOCKER_TUXBOT) tuxbot
|
||||
|
||||
dev: black update_soft
|
||||
tuxbot dev
|
||||
|
||||
# Blackify code
|
||||
.PHONY: black
|
||||
black:
|
||||
$(PYTHON) -m black `git ls-files "*.py"` --line-length=79 && $(PYTHON) -m pylint tuxbot
|
||||
$(PYTHON_PATH) -m black `git ls-files "*.py"` --line-length=79 && $(PYTHON_PATH) -m pylint tuxbot
|
||||
|
||||
# Translations
|
||||
.PHONY: xgettext
|
||||
xgettext:
|
||||
for cog in tuxbot/cogs/*/; do \
|
||||
xgettext `find $$cog -type f -name '*.py'` --output=$$cog/locales/messages.pot $(XGETTEXT_FLAGS); \
|
||||
done
|
||||
|
||||
.PHONY: msginit
|
||||
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
|
||||
|
||||
.PHONY: msgmerge
|
||||
msgmerge:
|
||||
for cog in tuxbot/cogs/*/; do \
|
||||
msgmerge --update $$cog/locales/fr-FR.po $$cog/locales/messages.pot; \
|
||||
|
|
|
@ -14,7 +14,7 @@ Installing the pre-requirements
|
|||
|
||||
- The pre-requirements are:
|
||||
|
||||
- Python 3.8 or greater
|
||||
- Python 3.9 or greater
|
||||
- Pip
|
||||
- Git
|
||||
|
||||
|
@ -134,7 +134,7 @@ To update the whole bot after a :bash:`git pull`, just execute
|
|||
|
||||
$ make update
|
||||
|
||||
.. |image0| image:: https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-%23007ec6
|
||||
.. |image0| image:: https://img.shields.io/badge/python-3.9%20%7C%203.10-%23007ec6
|
||||
.. |image1| image:: https://img.shields.io/github/issues/Rom1-J/tuxbot-bot
|
||||
.. |image2| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
.. |image3| image:: https://wakatime.com/badge/github/Rom1-J/tuxbot-bot.svg
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.8-slim-buster
|
||||
FROM python:3.9-slim-buster
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
ENV PYTHONDONTWRITEBYTECODE 1
|
||||
|
@ -19,6 +19,7 @@ RUN apt-get update \
|
|||
# Requirements are installed here to ensure they will be cached.
|
||||
COPY ./dev.requirements.txt /app/dev.requirements.txt
|
||||
COPY ./tuxbot /app/tuxbot
|
||||
COPY ./data /app/data
|
||||
COPY ./setup.cfg /app/setup.cfg
|
||||
COPY ./setup.py /app/setup.py
|
||||
RUN pip install -r /app/dev.requirements.txt
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
FROM node:10-stretch-slim as client-builder
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./package.json /app
|
||||
RUN npm install && npm cache clean --force
|
||||
COPY . /app
|
||||
RUN npm run build
|
||||
|
||||
# Python build stage
|
||||
FROM python:3.8-slim-buster
|
||||
FROM python:3.9-slim-buster
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
|
@ -26,8 +22,6 @@ RUN addgroup --system tuxbot \
|
|||
&& adduser --system --ingroup tuxbot tuxbot
|
||||
|
||||
# Requirements are installed here to ensure they will be cached.
|
||||
RUN pip install --no-cache-dir psycopg2==2.8.6
|
||||
|
||||
COPY --chown=tuxbot:tuxbot ./compose/production/tuxbot/entrypoint /entrypoint
|
||||
RUN sed -i 's/\r$//g' /entrypoint
|
||||
RUN chmod +x /entrypoint
|
||||
|
|
|
@ -13,23 +13,24 @@ if [ -z "${POSTGRES_USER}" ]; then
|
|||
fi
|
||||
export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}"
|
||||
|
||||
echo "psql at: ${DATABASE_URL}"
|
||||
|
||||
postgres_ready() {
|
||||
python << END
|
||||
import sys
|
||||
|
||||
import psycopg2
|
||||
import asyncpg
|
||||
import asyncio
|
||||
|
||||
try:
|
||||
psycopg2.connect(
|
||||
dbname="${POSTGRES_DB}",
|
||||
user="${POSTGRES_USER}",
|
||||
password="${POSTGRES_PASSWORD}",
|
||||
host="${POSTGRES_HOST}",
|
||||
port="${POSTGRES_PORT}",
|
||||
)
|
||||
except psycopg2.OperationalError:
|
||||
async def main():
|
||||
try:
|
||||
conn = await asyncpg.connect('postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}')
|
||||
except Exception:
|
||||
sys.exit(-1)
|
||||
sys.exit(0)
|
||||
await conn.close()
|
||||
sys.exit(0)
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
||||
|
||||
END
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ services:
|
|||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/local/tuxbot/Dockerfile
|
||||
restart: always
|
||||
image: tuxbot_bot_local_tuxbot
|
||||
container_name: tuxbot
|
||||
depends_on:
|
||||
|
|
30
production.yml
Normal file
30
production.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
version: '3'
|
||||
|
||||
volumes:
|
||||
production_postgres_data: {}
|
||||
production_postgres_data_backups: {}
|
||||
production_traefik: {}
|
||||
|
||||
services:
|
||||
tuxbot:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/production/tuxbot/Dockerfile
|
||||
image: tuxbot_bot_production_tuxbot
|
||||
depends_on:
|
||||
- postgres
|
||||
env_file:
|
||||
- ./.envs/.production/.tuxbot
|
||||
- ./.envs/.production/.postgres
|
||||
command: /start
|
||||
|
||||
postgres:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/production/postgres/Dockerfile
|
||||
image: tuxbot_bot_production_postgres
|
||||
volumes:
|
||||
- production_postgres_data:/var/lib/postgresql/data:Z
|
||||
- production_postgres_data_backups:/backups:z
|
||||
env_file:
|
||||
- ./.envs/.production/.postgres
|
|
@ -13,9 +13,8 @@ platforms = linux
|
|||
|
||||
[options]
|
||||
packages = find_namespace:
|
||||
python_requires = >=3.8
|
||||
python_requires = >=3.9
|
||||
install_requires =
|
||||
appdirs==1.4.4
|
||||
asyncpg==0.21.0
|
||||
Babel==2.8.0
|
||||
discord.py @ git+https://github.com/Rapptz/discord.py
|
||||
|
@ -26,7 +25,7 @@ install_requires =
|
|||
psutil==5.7.2
|
||||
pydig==0.3.0
|
||||
rich==9.10.0
|
||||
sentry_sdk==0.20.0
|
||||
sentry_sdk>=0.20.2
|
||||
structured_config==4.12
|
||||
tortoise-orm==0.16.17
|
||||
|
||||
|
|
2
setup.py
2
setup.py
|
@ -1,5 +1,5 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
python_requires=">=3.8",
|
||||
python_requires=">=3.9",
|
||||
)
|
||||
|
|
|
@ -5,20 +5,16 @@ import signal
|
|||
import sys
|
||||
import os
|
||||
from argparse import Namespace
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
import humanize
|
||||
import pip
|
||||
from rich.columns import Columns
|
||||
from rich.panel import Panel
|
||||
from rich.table import Table, box
|
||||
from rich.text import Text
|
||||
from rich import print as rprint
|
||||
|
||||
import tuxbot.logging
|
||||
from tuxbot.core.bot import Tux
|
||||
from tuxbot.core import config
|
||||
from tuxbot.core.utils import data_manager
|
||||
from tuxbot.core.utils.console import console
|
||||
from . import __version__, version_info, ExitCodes
|
||||
|
@ -28,41 +24,6 @@ log = logging.getLogger("tuxbot.main")
|
|||
BORDER_STYLE = "not dim"
|
||||
|
||||
|
||||
def list_instances() -> None:
|
||||
"""List all available instances"""
|
||||
app_config = config.ConfigFile(
|
||||
data_manager.config_dir / "config.yaml", config.AppConfig
|
||||
).config
|
||||
|
||||
console.print(
|
||||
Panel("[bold green]Instances", style="green"), justify="center"
|
||||
)
|
||||
console.print()
|
||||
|
||||
columns = Columns(expand=True, padding=2, align="center")
|
||||
for instance, details in app_config.Instances.items():
|
||||
active = details["active"]
|
||||
last_run = (
|
||||
humanize.naturaltime(
|
||||
datetime.now() - datetime.fromtimestamp(details["last_run"])
|
||||
)
|
||||
or "[i]unknown"
|
||||
)
|
||||
|
||||
table = Table(
|
||||
style="dim", border_style=BORDER_STYLE, box=box.HEAVY_HEAD
|
||||
)
|
||||
table.add_column("Name")
|
||||
table.add_column(("Running since" if active else "Last run"))
|
||||
table.add_row(instance, last_run)
|
||||
table.title = Text(instance, style="green" if active else "red")
|
||||
columns.add_renderable(table)
|
||||
console.print(columns)
|
||||
console.print()
|
||||
|
||||
sys.exit(os.EX_OK)
|
||||
|
||||
|
||||
def debug_info() -> None:
|
||||
"""Show debug info relatives to the bot"""
|
||||
python_version = sys.version.replace("\n", "")
|
||||
|
@ -134,7 +95,7 @@ def parse_cli_flags(args: list) -> Namespace:
|
|||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Tuxbot - OpenSource bot",
|
||||
usage="tuxbot <instance_name> [arguments]",
|
||||
usage="tuxbot [arguments]",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version",
|
||||
|
@ -145,20 +106,9 @@ def parse_cli_flags(args: list) -> Namespace:
|
|||
parser.add_argument(
|
||||
"--debug", action="store_true", help="Show debug information."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--list-instances",
|
||||
"-L",
|
||||
action="store_true",
|
||||
help="List all instance names",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--token", "-T", type=str, help="Run Tuxbot with passed token"
|
||||
)
|
||||
parser.add_argument(
|
||||
"instance_name",
|
||||
nargs="?",
|
||||
help="Name of the bot instance created during `tuxbot-setup`.",
|
||||
)
|
||||
|
||||
args = parser.parse_args(args)
|
||||
|
||||
|
@ -206,7 +156,7 @@ async def run_bot(tux: Tux, cli_flags: Namespace) -> None:
|
|||
None
|
||||
When exiting, this function return None.
|
||||
"""
|
||||
data_path = data_manager.data_path(tux.instance_name)
|
||||
data_path = data_manager.data_path
|
||||
|
||||
tuxbot.logging.init_logging(10, location=data_path / "logs")
|
||||
|
||||
|
@ -245,9 +195,7 @@ def run() -> None:
|
|||
tux = None
|
||||
cli_flags = parse_cli_flags(sys.argv[1:])
|
||||
|
||||
if cli_flags.list_instances:
|
||||
list_instances()
|
||||
elif cli_flags.debug:
|
||||
if cli_flags.debug:
|
||||
debug_info()
|
||||
elif cli_flags.version:
|
||||
rprint(f"Tuxbot V{version_info.major}")
|
||||
|
@ -259,13 +207,6 @@ def run() -> None:
|
|||
asyncio.set_event_loop(loop)
|
||||
|
||||
try:
|
||||
if not cli_flags.instance_name:
|
||||
console.print(
|
||||
"[red]No instance provided ! "
|
||||
"You can use 'tuxbot -L' to list all available instances"
|
||||
)
|
||||
sys.exit(ExitCodes.CRITICAL)
|
||||
|
||||
tux = Tux(
|
||||
cli_flags=cli_flags,
|
||||
description="Tuxbot, made from and for OpenSource",
|
||||
|
|
|
@ -5,7 +5,7 @@ from discord.ext import commands
|
|||
|
||||
from tuxbot.cogs.Custom.functions.converters import AliasConvertor
|
||||
from tuxbot.core.bot import Tux
|
||||
from tuxbot.core.config import set_for_key, search_for
|
||||
from tuxbot.core.config import set_for_key, search_for, set_if_none
|
||||
from tuxbot.core.config import Config
|
||||
from tuxbot.core.i18n import (
|
||||
Translator,
|
||||
|
@ -33,14 +33,14 @@ class Custom(commands.Cog, name="Custom"):
|
|||
# =========================================================================
|
||||
# =========================================================================
|
||||
|
||||
async def _get_aliases(self, ctx: ContextPlus) -> dict:
|
||||
return search_for(self.bot.config.Users, ctx.author.id, "aliases")
|
||||
|
||||
async def _save_lang(self, ctx: ContextPlus, lang: str) -> None:
|
||||
set_for_key(
|
||||
self.bot.config.Users, ctx.author.id, Config.User, locale=lang
|
||||
)
|
||||
|
||||
async def _get_aliases(self, ctx: ContextPlus) -> dict:
|
||||
return search_for(self.bot.config.Users, ctx.author.id, "aliases")
|
||||
|
||||
async def _save_alias(self, ctx: ContextPlus, alias: dict) -> None:
|
||||
set_for_key(
|
||||
self.bot.config.Users, ctx.author.id, Config.User, alias=alias
|
||||
|
@ -76,13 +76,17 @@ class Custom(commands.Cog, name="Custom"):
|
|||
|
||||
@_custom.command(name="alias", aliases=["aliases"])
|
||||
async def _custom_alias(self, ctx: ContextPlus, *, alias: AliasConvertor):
|
||||
args = alias.split(" | ")
|
||||
args = str(alias).split(" | ")
|
||||
|
||||
command = args[0]
|
||||
alias = args[1]
|
||||
|
||||
user_aliases = await self._get_aliases(ctx)
|
||||
|
||||
if not user_aliases:
|
||||
set_if_none(self.bot.config.Users, ctx.author.id, Config.User)
|
||||
user_aliases = await self._get_aliases(ctx)
|
||||
|
||||
if alias in user_aliases.keys():
|
||||
return await ctx.send(
|
||||
_(
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
from structured_config import Structure, StrField
|
||||
from structured_config import Structure
|
||||
|
||||
HAS_MODELS = False
|
||||
|
||||
|
||||
class DevConfig(Structure):
|
||||
sentryKey: str = StrField("")
|
||||
pass
|
||||
|
||||
|
||||
extra = {
|
||||
"sentryKey": {
|
||||
"type": str,
|
||||
"description": "Sentry KEY for error logging (https://sentry.io/)",
|
||||
},
|
||||
}
|
||||
extra = {}
|
||||
|
|
|
@ -56,9 +56,7 @@ class Logs(commands.Cog, name="Logs"):
|
|||
self.gateway_worker.start() # pylint: disable=no-member
|
||||
|
||||
self.__config: LogsConfig = ConfigFile(
|
||||
str(
|
||||
cogs_data_path(self.bot.instance_name, "Logs") / "config.yaml"
|
||||
),
|
||||
str(cogs_data_path("Logs") / "config.yaml"),
|
||||
LogsConfig,
|
||||
).config
|
||||
|
||||
|
@ -266,6 +264,19 @@ class Logs(commands.Cog, name="Logs"):
|
|||
e.timestamp = datetime.datetime.utcnow()
|
||||
await self.webhook("errors").send(embed=e)
|
||||
|
||||
e.description = _(
|
||||
"```An error occurred, the bot owner has been advertised...```",
|
||||
ctx,
|
||||
self.bot.config,
|
||||
)
|
||||
e.remove_field(0)
|
||||
e.remove_field(1)
|
||||
e.remove_field(1)
|
||||
|
||||
e.set_footer(text=sentry_sdk.last_event_id())
|
||||
|
||||
await ctx.send(embed=e)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_socket_raw_send(self, data):
|
||||
if '"op":2' not in data and '"op":6' not in data:
|
||||
|
|
|
@ -54,10 +54,7 @@ class Network(commands.Cog, name="Network"):
|
|||
def __init__(self, bot: Tux):
|
||||
self.bot = bot
|
||||
self.__config: NetworkConfig = ConfigFile(
|
||||
str(
|
||||
cogs_data_path(self.bot.instance_name, "Network")
|
||||
/ "config.yaml"
|
||||
),
|
||||
str(cogs_data_path("Network") / "config.yaml"),
|
||||
NetworkConfig,
|
||||
).config
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ from tortoise import Tortoise
|
|||
from tuxbot import version_info
|
||||
from tuxbot.core.utils.data_manager import (
|
||||
logs_data_path,
|
||||
data_path,
|
||||
config_dir,
|
||||
config_file,
|
||||
)
|
||||
from tuxbot.core.utils.functions.extra import ContextPlus
|
||||
from tuxbot.core.utils.functions.prefix import get_prefixes
|
||||
|
@ -28,8 +27,6 @@ from tuxbot.core.config import (
|
|||
Config,
|
||||
ConfigFile,
|
||||
search_for,
|
||||
AppConfig,
|
||||
set_for_key,
|
||||
)
|
||||
from . import __version__, ExitCodes
|
||||
from . import exceptions
|
||||
|
@ -57,17 +54,15 @@ class Tux(commands.AutoShardedBot):
|
|||
# it's a crash
|
||||
self.shutdown_code = ExitCodes.CRITICAL
|
||||
self.cli_flags = cli_flags
|
||||
self.instance_name = self.cli_flags.instance_name
|
||||
self.last_exception = None
|
||||
self.logs = logs_data_path(self.instance_name)
|
||||
self.logs = logs_data_path()
|
||||
|
||||
self.console = console
|
||||
|
||||
self.stats = {"commands": Counter(), "socket": Counter()}
|
||||
|
||||
self.config: Config = ConfigFile(
|
||||
str(data_path(self.instance_name) / "config.yaml"), Config
|
||||
).config
|
||||
self.config: Config = ConfigFile(config_file, Config).config
|
||||
self.instance_name = self.config.Core.instance_name
|
||||
|
||||
async def _prefixes(bot, message) -> List[str]:
|
||||
prefixes = self.config.Core.prefixes
|
||||
|
@ -157,14 +152,6 @@ class Tux(commands.AutoShardedBot):
|
|||
|
||||
self.uptime = datetime.datetime.now()
|
||||
self.last_on_ready = self.uptime
|
||||
app_config = ConfigFile(config_dir / "config.yaml", AppConfig).config
|
||||
set_for_key(
|
||||
app_config.Instances,
|
||||
self.instance_name,
|
||||
AppConfig.Instance,
|
||||
active=True,
|
||||
last_run=datetime.datetime.timestamp(self.uptime),
|
||||
)
|
||||
|
||||
with self._progress["main"] as progress:
|
||||
progress.stop_task(self._progress["tasks"]["discord_connecting"])
|
||||
|
@ -189,6 +176,7 @@ class Tux(commands.AutoShardedBot):
|
|||
table.add_row(f"Language: {self.config.Core.locale}")
|
||||
table.add_row(f"Tuxbot Version: {__version__}")
|
||||
table.add_row(f"Discord.py Version: {discord.__version__}")
|
||||
table.add_row(f"Instance name: {self.instance_name}")
|
||||
table.add_row(f"Shards: {self.shard_count}")
|
||||
table.add_row(f"Servers: {len(self.guilds)}")
|
||||
table.add_row(f"Users: {len(self.users)}")
|
||||
|
@ -315,8 +303,8 @@ class Tux(commands.AutoShardedBot):
|
|||
task_id = self._progress["tasks"][
|
||||
"discord_connecting"
|
||||
] = progress.add_task(
|
||||
"discord_connecting",
|
||||
task_name="Connecting to Discord...",
|
||||
"Connecting to Discord...",
|
||||
task_name="discord_connecting",
|
||||
start=False,
|
||||
)
|
||||
progress.update(task_id)
|
||||
|
@ -327,14 +315,6 @@ class Tux(commands.AutoShardedBot):
|
|||
|
||||
Todo: add postgresql logout here
|
||||
"""
|
||||
app_config = ConfigFile(config_dir / "config.yaml", AppConfig).config
|
||||
set_for_key(
|
||||
app_config.Instances,
|
||||
self.instance_name,
|
||||
AppConfig.Instance,
|
||||
active=False,
|
||||
)
|
||||
|
||||
with self._progress["main"] as progress:
|
||||
for task in self._progress["tasks"]:
|
||||
progress.log("Shutting down", task)
|
||||
|
|
|
@ -11,7 +11,6 @@ from structured_config import (
|
|||
__all__ = [
|
||||
"Config",
|
||||
"ConfigFile",
|
||||
"AppConfig",
|
||||
"search_for",
|
||||
"set_for_key",
|
||||
"set_for",
|
||||
|
@ -60,20 +59,7 @@ class Config(Structure):
|
|||
mentionable: bool = BoolField("")
|
||||
locale: str = StrField("")
|
||||
disabled_command: List[str] = []
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Configuration of Tuxbot Application (not the bot)
|
||||
# =============================================================================
|
||||
|
||||
|
||||
class AppConfig(Structure):
|
||||
class Instance(Structure):
|
||||
path: str = StrField("")
|
||||
active: bool = BoolField(False)
|
||||
last_run: int = IntField(0)
|
||||
|
||||
Instances: Dict[str, Instance] = {}
|
||||
instance_name: str = StrField("")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
@ -87,6 +73,11 @@ def search_for(config, key, value, default=False) -> Any:
|
|||
return default
|
||||
|
||||
|
||||
def set_if_none(config, key, ctype) -> None:
|
||||
if key not in config:
|
||||
config[key] = ctype()
|
||||
|
||||
|
||||
def set_for_key(config, key, ctype, **values) -> None:
|
||||
# pylint: disable=anomalous-backslash-in-string
|
||||
"""
|
||||
|
@ -105,8 +96,7 @@ def set_for_key(config, key, ctype, **values) -> None:
|
|||
rip roxy .*' / .*' ; .*`- +' `*'
|
||||
201?-2020 :,( `*-* `*-* `*-*'
|
||||
"""
|
||||
if key not in config:
|
||||
config[key] = ctype()
|
||||
set_if_none(config, key, ctype)
|
||||
|
||||
for k, v in values.items():
|
||||
setattr(config[key], k, v)
|
||||
|
|
|
@ -1,51 +1,32 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import appdirs
|
||||
import os
|
||||
|
||||
log = logging.getLogger("tuxbot.core.data_manager")
|
||||
|
||||
app_dir = appdirs.AppDirs("Tuxbot-bot")
|
||||
config_dir = Path(app_dir.user_config_dir)
|
||||
config_file = config_dir / "config.yaml"
|
||||
core_path = Path(os.getcwd())
|
||||
|
||||
data_path = core_path / "data"
|
||||
config_path = data_path / "settings"
|
||||
config_file = config_path / "config.yaml"
|
||||
|
||||
|
||||
def data_path(instance_name: str) -> Path:
|
||||
"""Return Path for data configs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instance_name:str
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Generated path for data configs.
|
||||
"""
|
||||
return Path(app_dir.user_data_dir) / "data" / instance_name
|
||||
|
||||
|
||||
def logs_data_path(instance_name: str) -> Path:
|
||||
def logs_data_path() -> Path:
|
||||
"""Return Path for Logs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instance_name:str
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Generated path for Logs files.
|
||||
"""
|
||||
return data_path(instance_name) / "logs"
|
||||
return data_path / "logs"
|
||||
|
||||
|
||||
def cogs_data_path(instance_name: str, cog_name: str = "") -> Path:
|
||||
def cogs_data_path(cog_name: str = "") -> Path:
|
||||
"""Return Path for cogs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instance_name:str
|
||||
cog_name:str
|
||||
|
||||
Returns
|
||||
|
@ -53,4 +34,4 @@ def cogs_data_path(instance_name: str, cog_name: str = "") -> Path:
|
|||
Path
|
||||
Generated path for cogs configs.
|
||||
"""
|
||||
return data_path(instance_name) / "cogs" / cog_name
|
||||
return data_path / "settings" / "cogs" / cog_name
|
||||
|
|
203
tuxbot/setup.py
203
tuxbot/setup.py
|
@ -17,31 +17,26 @@ from rich.style import Style
|
|||
from rich.traceback import install
|
||||
|
||||
from tuxbot import version_info
|
||||
from tuxbot.core.config import set_for, set_for_key
|
||||
from tuxbot.core.config import set_for
|
||||
from tuxbot.logging import formatter
|
||||
from tuxbot.core.utils.data_manager import config_dir, app_dir, cogs_data_path
|
||||
from tuxbot.core.utils.data_manager import (
|
||||
config_path,
|
||||
config_file,
|
||||
cogs_data_path,
|
||||
)
|
||||
from tuxbot.core import config
|
||||
|
||||
console = Console()
|
||||
install(console=console)
|
||||
install(console=console, show_locals=True)
|
||||
|
||||
try:
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
config_path.mkdir(parents=True, exist_ok=True)
|
||||
except PermissionError:
|
||||
console.print(
|
||||
f"mkdir: cannot create directory '{config_dir}': Permission denied"
|
||||
f"mkdir: cannot create directory '{config_path}': Permission denied"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
app_config = config.ConfigFile(
|
||||
config_dir / "config.yaml", config.AppConfig
|
||||
).config
|
||||
|
||||
if not app_config.Instances:
|
||||
instances_list = []
|
||||
else:
|
||||
instances_list = list(app_config.Instances.keys())
|
||||
|
||||
|
||||
def get_name() -> str:
|
||||
"""Get instance name via input.
|
||||
|
@ -66,80 +61,6 @@ def get_name() -> str:
|
|||
return name
|
||||
|
||||
|
||||
def get_data_dir(instance_name: str) -> Path:
|
||||
"""Returning data path.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
instance_name:str
|
||||
Instance name.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
The data config path corresponding to the instance.
|
||||
|
||||
"""
|
||||
data_path = Path(app_dir.user_data_dir) / "data" / instance_name
|
||||
data_path_input = ""
|
||||
console.print()
|
||||
|
||||
def make_data_dir(path: Path) -> Union[Path, str]:
|
||||
try:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
except OSError:
|
||||
console.print()
|
||||
console.print(
|
||||
f"mkdir: cannot create directory '{path}': Permission denied"
|
||||
)
|
||||
path = ""
|
||||
|
||||
return path
|
||||
|
||||
while not data_path_input:
|
||||
data_path_input = Path(
|
||||
Prompt.ask(
|
||||
"where do you want to save the configurations?",
|
||||
default=str(data_path),
|
||||
console=console,
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
exists = data_path_input.exists()
|
||||
except OSError:
|
||||
console.print()
|
||||
console.print(
|
||||
"[prompt.invalid]"
|
||||
"Impossible to verify the validity of the path,"
|
||||
" make sure it does not contain any invalid characters."
|
||||
)
|
||||
data_path_input = ""
|
||||
exists = False
|
||||
|
||||
if data_path_input and not exists:
|
||||
data_path_input = make_data_dir(data_path_input)
|
||||
|
||||
console.print()
|
||||
console.print(
|
||||
f"You have chosen {data_path_input} to be your config directory for "
|
||||
f"`{instance_name}` instance"
|
||||
)
|
||||
|
||||
if (
|
||||
Prompt.ask(
|
||||
"Please confirm", choices=["y", "n"], default="y", console=console
|
||||
)
|
||||
!= "y"
|
||||
):
|
||||
console.print("Rerun the process to redo this configuration.")
|
||||
sys.exit(0)
|
||||
|
||||
(data_path_input / "Logs").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
return data_path_input
|
||||
|
||||
|
||||
def get_token() -> str:
|
||||
"""Get token via input.
|
||||
|
||||
|
@ -250,7 +171,7 @@ def get_extra(question: str, value_type: type) -> Union[str, int]:
|
|||
return prompt.ask(question, console=console)
|
||||
|
||||
|
||||
def additional_config(instance: str, cogs: str = "**"):
|
||||
def additional_config(cogs: str = "**"):
|
||||
"""Asking for additional configs in cogs.
|
||||
|
||||
Returns
|
||||
|
@ -277,7 +198,7 @@ def additional_config(instance: str, cogs: str = "**"):
|
|||
mod_extra = mod.extra
|
||||
|
||||
mod_config = config.ConfigFile(
|
||||
str(cogs_data_path(instance, cog_name) / "config.yaml"),
|
||||
str(cogs_data_path(cog_name) / "config.yaml"),
|
||||
mod_config_type,
|
||||
).config
|
||||
|
||||
|
@ -296,14 +217,10 @@ def additional_config(instance: str, cogs: str = "**"):
|
|||
)
|
||||
|
||||
|
||||
def finish_setup(data_dir: Path) -> None:
|
||||
"""Configs who directly refer to the bot.
|
||||
def finish_setup() -> None:
|
||||
"""Configs who directly refer to the bot."""
|
||||
name = get_name()
|
||||
|
||||
Parameters
|
||||
----------
|
||||
data_dir:Path
|
||||
Where to save configs.
|
||||
"""
|
||||
console.print(
|
||||
Rule("Now, it's time to finish this setup by giving bot information")
|
||||
)
|
||||
|
@ -363,22 +280,21 @@ def finish_setup(data_dir: Path) -> None:
|
|||
),
|
||||
}
|
||||
|
||||
instance_config = config.ConfigFile(
|
||||
str(data_dir / "config.yaml"), config.Config
|
||||
)
|
||||
_config_file = config.ConfigFile(str(config_file), config.Config)
|
||||
|
||||
instance_config.config.Core.owners_id = owners_id
|
||||
instance_config.config.Core.prefixes = prefixes
|
||||
instance_config.config.Core.token = token
|
||||
instance_config.config.Core.ip = ip
|
||||
instance_config.config.Core.mentionable = mentionable
|
||||
instance_config.config.Core.locale = "en-US"
|
||||
_config_file.config.Core.owners_id = owners_id
|
||||
_config_file.config.Core.prefixes = prefixes
|
||||
_config_file.config.Core.token = token
|
||||
_config_file.config.Core.ip = ip
|
||||
_config_file.config.Core.mentionable = mentionable
|
||||
_config_file.config.Core.locale = "en-US"
|
||||
_config_file.config.Core.instance_name = name
|
||||
|
||||
instance_config.config.Core.Database.username = database["username"]
|
||||
instance_config.config.Core.Database.password = database["password"]
|
||||
instance_config.config.Core.Database.domain = database["domain"]
|
||||
instance_config.config.Core.Database.port = database["port"]
|
||||
instance_config.config.Core.Database.db_name = database["db_name"]
|
||||
_config_file.config.Core.Database.username = database["username"]
|
||||
_config_file.config.Core.Database.password = database["password"]
|
||||
_config_file.config.Core.Database.domain = database["domain"]
|
||||
_config_file.config.Core.Database.port = database["port"]
|
||||
_config_file.config.Core.Database.db_name = database["db_name"]
|
||||
|
||||
|
||||
def basic_setup() -> None:
|
||||
|
@ -388,47 +304,15 @@ def basic_setup() -> None:
|
|||
"Hi ! it's time for you to give me information about you instance"
|
||||
)
|
||||
)
|
||||
console.print()
|
||||
name = get_name()
|
||||
|
||||
data_dir = get_data_dir(name)
|
||||
|
||||
if name in instances_list:
|
||||
console.print()
|
||||
console.print(
|
||||
f"WARNING: An instance named `{name}` already exists "
|
||||
f"Continuing will overwrite this instance configs.",
|
||||
style="red",
|
||||
)
|
||||
if (
|
||||
Prompt.ask(
|
||||
"Are you sure you want to continue?",
|
||||
choices=["y", "n"],
|
||||
default="n",
|
||||
)
|
||||
== "n"
|
||||
):
|
||||
console.print("Abandon...")
|
||||
sys.exit(0)
|
||||
|
||||
set_for_key(
|
||||
app_config.Instances,
|
||||
name,
|
||||
config.AppConfig.Instance,
|
||||
path=str(data_dir.resolve()),
|
||||
active=False,
|
||||
)
|
||||
|
||||
console.print("\n" * 4)
|
||||
|
||||
finish_setup(data_dir)
|
||||
finish_setup()
|
||||
|
||||
console.print()
|
||||
console.print(
|
||||
f"Instance successfully created! "
|
||||
f"You can now run `tuxbot {name}` to launch this instance now or "
|
||||
f"setup the additional configs by running "
|
||||
f"`tuxbot-setup {name} --additional-config=all`"
|
||||
"Instance successfully created! "
|
||||
"You can now run `tuxbot` to launch it now or "
|
||||
"setup the additional configs by running "
|
||||
"`tuxbot-setup --additional-config=all`"
|
||||
)
|
||||
|
||||
|
||||
|
@ -440,10 +324,7 @@ def update() -> None:
|
|||
)
|
||||
|
||||
if response.get("sha")[:6] == version_info.build:
|
||||
print(
|
||||
"Nothing to update, you can run `tuxbot [instance_name]` "
|
||||
"to start the bot"
|
||||
)
|
||||
print("Nothing to update, you can run `tuxbot` " "to start the bot")
|
||||
else:
|
||||
print(f"Updating to {response.get('sha')[:6]}...")
|
||||
|
||||
|
@ -465,12 +346,7 @@ def parse_cli_flags(args: list) -> Namespace:
|
|||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Tuxbot Setup - OpenSource bot",
|
||||
usage="tuxbot-setup [instance] [arguments]",
|
||||
)
|
||||
parser.add_argument(
|
||||
"instance_name",
|
||||
nargs="?",
|
||||
help="Name of the bot instance to edit.",
|
||||
usage="tuxbot-setup [arguments]",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
|
@ -507,15 +383,8 @@ def setup() -> None:
|
|||
stdout_handler.setFormatter(formatter)
|
||||
base_logger.addHandler(stdout_handler)
|
||||
|
||||
if cli_flags.additional_config and not cli_flags.instance_name:
|
||||
console.print(
|
||||
"[red]No instance to modify provided ! "
|
||||
"You can use 'tuxbot -L' to list all available instances"
|
||||
)
|
||||
elif cli_flags.instance_name:
|
||||
additional_config(
|
||||
cli_flags.instance_name, cli_flags.additional_config
|
||||
)
|
||||
if cli_flags.additional_config:
|
||||
additional_config(cli_flags.additional_config)
|
||||
else:
|
||||
console.clear()
|
||||
basic_setup()
|
||||
|
|
Loading…
Reference in a new issue