mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
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:
parent
f3e7c2028c
commit
36e2cde04d
1
changelog.d/3235.feature.rst
Normal file
1
changelog.d/3235.feature.rst
Normal file
@ -0,0 +1 @@
|
|||||||
|
Added ``redbot-setup backup`` command.
|
||||||
1
changelog.d/3235.removal.rst
Normal file
1
changelog.d/3235.removal.rst
Normal file
@ -0,0 +1 @@
|
|||||||
|
Removed ``[p]backup`` command. Use ``redbot-setup backup`` cli command instead.
|
||||||
@ -31,7 +31,6 @@ from . import (
|
|||||||
i18n,
|
i18n,
|
||||||
config,
|
config,
|
||||||
)
|
)
|
||||||
from .utils._internal_utils import create_backup
|
|
||||||
from .utils.predicates import MessagePredicate
|
from .utils.predicates import MessagePredicate
|
||||||
from .utils.chat_formatting import (
|
from .utils.chat_formatting import (
|
||||||
box,
|
box,
|
||||||
@ -1390,75 +1389,6 @@ class Core(commands.Cog, CoreLogic):
|
|||||||
|
|
||||||
await ctx.send_interactive(pages, box_lang="Available Locales:")
|
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.command()
|
||||||
@commands.cooldown(1, 60, commands.BucketType.user)
|
@commands.cooldown(1, 60, commands.BucketType.user)
|
||||||
async def contact(self, ctx: commands.Context, *, message: str):
|
async def contact(self, ctx: commands.Context, *, message: str):
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import sys
|
|||||||
import re
|
import re
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional, Union
|
||||||
|
|
||||||
import appdirs
|
import appdirs
|
||||||
import click
|
import click
|
||||||
@ -213,13 +213,13 @@ async def do_migration(
|
|||||||
return new_storage_details
|
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)
|
data_manager.load_basic_configuration(instance)
|
||||||
backend_type = get_current_backend(instance)
|
backend_type = get_current_backend(instance)
|
||||||
if backend_type != BackendType.JSON:
|
if backend_type != BackendType.JSON:
|
||||||
await do_migration(backend_type, BackendType.JSON)
|
await do_migration(backend_type, BackendType.JSON)
|
||||||
print("Backing up the instance's data...")
|
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:
|
if backup_fpath is not None:
|
||||||
print(f"A backup of {instance} has been made. It is at {backup_fpath}")
|
print(f"A backup of {instance} has been made. It is at {backup_fpath}")
|
||||||
else:
|
else:
|
||||||
@ -293,6 +293,7 @@ async def remove_instance_interaction():
|
|||||||
@click.option("--debug", type=bool)
|
@click.option("--debug", type=bool)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx, debug):
|
def cli(ctx, debug):
|
||||||
|
"""Create a new instance."""
|
||||||
level = logging.DEBUG if debug else logging.INFO
|
level = logging.DEBUG if debug else logging.INFO
|
||||||
redbot.logging.init_logging(level=level, location=Path.cwd() / "red_setup_logs")
|
redbot.logging.init_logging(level=level, location=Path.cwd() / "red_setup_logs")
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
@ -356,6 +357,7 @@ def delete(
|
|||||||
drop_db: Optional[bool],
|
drop_db: Optional[bool],
|
||||||
remove_datapath: Optional[bool],
|
remove_datapath: Optional[bool],
|
||||||
):
|
):
|
||||||
|
"""Removes an instance."""
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.run_until_complete(
|
loop.run_until_complete(
|
||||||
remove_instance(
|
remove_instance(
|
||||||
@ -368,6 +370,7 @@ def delete(
|
|||||||
@click.argument("instance", type=click.Choice(instance_list))
|
@click.argument("instance", type=click.Choice(instance_list))
|
||||||
@click.argument("backend", type=click.Choice(["json", "postgres"]))
|
@click.argument("backend", type=click.Choice(["json", "postgres"]))
|
||||||
def convert(instance, backend):
|
def convert(instance, backend):
|
||||||
|
"""Convert data backend of an instance."""
|
||||||
current_backend = get_current_backend(instance)
|
current_backend = get_current_backend(instance)
|
||||||
target = get_target_backend(backend)
|
target = get_target_backend(backend)
|
||||||
data_manager.load_basic_configuration(instance)
|
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__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
cli() # pylint: disable=no-value-for-parameter # click
|
cli() # pylint: disable=no-value-for-parameter # click
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user