Move [p]backup command to cli command - redbot-setup backup (#3235)

* refactor: replace backup command with cli command

* chore(changelog): add towncrier entries
This commit is contained in:
jack1142 2020-01-02 15:03:32 +01:00 committed by Michael H
parent f3e7c2028c
commit 36e2cde04d
4 changed files with 23 additions and 73 deletions

View File

@ -0,0 +1 @@
Added ``redbot-setup backup`` command.

View File

@ -0,0 +1 @@
Removed ``[p]backup`` command. Use ``redbot-setup backup`` cli command instead.

View File

@ -31,7 +31,6 @@ from . import (
i18n,
config,
)
from .utils._internal_utils import create_backup
from .utils.predicates import MessagePredicate
from .utils.chat_formatting import (
box,
@ -1390,75 +1389,6 @@ class Core(commands.Cog, CoreLogic):
await ctx.send_interactive(pages, box_lang="Available Locales:")
@commands.command()
@checks.is_owner()
async def backup(self, ctx: commands.Context, *, backup_dir: str = None):
"""Creates a backup of all data for this bot instance.
This backs up the bot's data and settings.
You may provide a path to a directory for the backup archive to
be placed in. If the directory does not exist, the bot will
attempt to create it.
"""
if backup_dir is None:
dest = Path.home()
else:
dest = Path(backup_dir)
driver_cls = drivers.get_driver_class()
if driver_cls != drivers.JsonDriver:
await ctx.send(_("Converting data to JSON for backup..."))
async with ctx.typing():
await config.migrate(driver_cls, drivers.JsonDriver)
log.info("Creating backup for this instance...")
try:
backup_fpath = await create_backup(dest)
except OSError as exc:
await ctx.send(
_(
"Creating the backup archive failed! Please check your console or logs for "
"details."
)
)
log.exception("Failed to create backup archive", exc_info=exc)
return
if backup_fpath is None:
await ctx.send(_("Your datapath appears to be empty."))
return
log.info("Backup archive created successfully at '%s'", backup_fpath)
await ctx.send(
_("A backup has been made of this instance. It is located at `{path}`.").format(
path=backup_fpath
)
)
if backup_fpath.stat().st_size > 8_000_000:
await ctx.send(_("This backup is too large to send via DM."))
return
await ctx.send(_("Would you like to receive a copy via DM? (y/n)"))
pred = MessagePredicate.yes_or_no(ctx)
try:
await ctx.bot.wait_for("message", check=pred, timeout=60)
except asyncio.TimeoutError:
await ctx.send(_("Response timed out."))
else:
if pred.result is True:
await ctx.send(_("OK, it's on its way!"))
try:
async with ctx.author.typing():
await ctx.author.send(
_("Here's a copy of the backup"), file=discord.File(str(backup_fpath))
)
except discord.Forbidden:
await ctx.send(_("I don't seem to be able to DM you. Do you have closed DMs?"))
except discord.HTTPException:
await ctx.send(_("I could not send the backup file."))
else:
await ctx.send(_("OK then."))
@commands.command()
@commands.cooldown(1, 60, commands.BucketType.user)
async def contact(self, ctx: commands.Context, *, message: str):

View File

@ -7,7 +7,7 @@ import sys
import re
from copy import deepcopy
from pathlib import Path
from typing import Dict, Any, Optional
from typing import Dict, Any, Optional, Union
import appdirs
import click
@ -213,13 +213,13 @@ async def do_migration(
return new_storage_details
async def create_backup(instance: str) -> None:
async def create_backup(instance: str, destination_folder: Path = Path.home()) -> None:
data_manager.load_basic_configuration(instance)
backend_type = get_current_backend(instance)
if backend_type != BackendType.JSON:
await do_migration(backend_type, BackendType.JSON)
print("Backing up the instance's data...")
backup_fpath = await red_create_backup()
backup_fpath = await red_create_backup(destination_folder)
if backup_fpath is not None:
print(f"A backup of {instance} has been made. It is at {backup_fpath}")
else:
@ -293,6 +293,7 @@ async def remove_instance_interaction():
@click.option("--debug", type=bool)
@click.pass_context
def cli(ctx, debug):
"""Create a new instance."""
level = logging.DEBUG if debug else logging.INFO
redbot.logging.init_logging(level=level, location=Path.cwd() / "red_setup_logs")
if ctx.invoked_subcommand is None:
@ -356,6 +357,7 @@ def delete(
drop_db: Optional[bool],
remove_datapath: Optional[bool],
):
"""Removes an instance."""
loop = asyncio.get_event_loop()
loop.run_until_complete(
remove_instance(
@ -368,6 +370,7 @@ def delete(
@click.argument("instance", type=click.Choice(instance_list))
@click.argument("backend", type=click.Choice(["json", "postgres"]))
def convert(instance, backend):
"""Convert data backend of an instance."""
current_backend = get_current_backend(instance)
target = get_target_backend(backend)
data_manager.load_basic_configuration(instance)
@ -393,6 +396,21 @@ def convert(instance, backend):
)
@cli.command()
@click.argument("instance", type=click.Choice(instance_list))
@click.argument(
"destination_folder",
type=click.Path(
exists=False, dir_okay=True, file_okay=False, resolve_path=True, writable=True
),
default=Path.home(),
)
def backup(instance: str, destination_folder: Union[str, Path]) -> None:
"""Backup instance's data."""
loop = asyncio.get_event_loop()
loop.run_until_complete(create_backup(instance, Path(destination_folder)))
if __name__ == "__main__":
try:
cli() # pylint: disable=no-value-for-parameter # click