async def _setup_driver(): backend_type = _get_backend_type() storage_details = {} data_manager.storage_type = lambda: backend_type.value data_manager.storage_details = lambda: storage_details driver_cls = drivers.get_driver_class(backend_type) await driver_cls.initialize(**storage_details) yield await driver_cls.teardown()
async def do_migration(current_backend: BackendType, target_backend: BackendType) -> Dict[str, Any]: cur_driver_cls = drivers._get_driver_class_include_old(current_backend) new_driver_cls = drivers.get_driver_class(target_backend) cur_storage_details = data_manager.storage_details() new_storage_details = new_driver_cls.get_config_details() await cur_driver_cls.initialize(**cur_storage_details) await new_driver_cls.initialize(**new_storage_details) await config.migrate(cur_driver_cls, new_driver_cls) await cur_driver_cls.teardown() await new_driver_cls.teardown() return new_storage_details
async def remove_instance( instance, interactive: bool = False, delete_data: Optional[bool] = None, _create_backup: Optional[bool] = None, drop_db: Optional[bool] = None, remove_datapath: Optional[bool] = None, ): data_manager.load_basic_configuration(instance) if interactive is True and delete_data is None: delete_data = click.confirm( "Would you like to delete this instance's data?", default=False) if interactive is True and _create_backup is None: _create_backup = click.confirm( "Would you like to make a backup of the data for this instance?", default=False) if _create_backup is True: await create_backup(instance) backend = get_current_backend(instance) driver_cls = drivers.get_driver_class(backend) await driver_cls.initialize(**data_manager.storage_details()) try: if delete_data is True: await driver_cls.delete_all_data(interactive=interactive, drop_db=drop_db) if interactive is True and remove_datapath is None: remove_datapath = click.confirm( "Would you like to delete the instance's entire datapath?", default=False) if remove_datapath is True: data_path = data_manager.core_data_path().parent safe_delete(data_path) save_config(instance, {}, remove=True) finally: await driver_cls.teardown() print("The instance {} has been removed\n".format(instance))
def basic_setup(): """ Creates the data storage folder. :return: """ print( "Hello! Before we begin, we need to gather some initial information for the new instance." ) name = get_name() default_data_dir = get_data_dir(name) default_dirs = deepcopy(data_manager.basic_config_default) default_dirs["DATA_PATH"] = default_data_dir storage = get_storage_type() storage_dict = {1: BackendType.JSON, 2: BackendType.POSTGRES} storage_type: BackendType = storage_dict.get(storage, BackendType.JSON) default_dirs["STORAGE_TYPE"] = storage_type.value driver_cls = drivers.get_driver_class(storage_type) default_dirs["STORAGE_DETAILS"] = driver_cls.get_config_details() if name in instance_data: print("WARNING: An instance already exists with this name. " "Continuing will overwrite the existing instance config.") if not click.confirm( "Are you absolutely certain you want to continue?", default=False): print("Not continuing") sys.exit(0) save_config(name, default_dirs) print() print( "Your basic configuration has been saved. Please run `beastbot <name>` to" " continue your setup process and to run the bot.\n\n" "First time? Read the quickstart guide:\n" "https://docs.discord.red/en/stable/getting_started.html")
def handle_edit(cli_flags: Namespace): """ This one exists to not log all the things like it's a full run of the bot. """ loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) data_manager.load_basic_configuration(cli_flags.instance_name) red = Red(cli_flags=cli_flags, description="Red V3", dm_help=None) try: driver_cls = drivers.get_driver_class() loop.run_until_complete( driver_cls.initialize(**data_manager.storage_details())) loop.run_until_complete(edit_instance(red, cli_flags)) loop.run_until_complete(driver_cls.teardown()) except (KeyboardInterrupt, EOFError): print("Aborted!") finally: loop.run_until_complete(asyncio.sleep(1)) asyncio.set_event_loop(None) loop.stop() loop.close() sys.exit(0)
async def run_bot(red: Red, cli_flags: Namespace) -> None: """ This runs the bot. Any shutdown which is a result of not being able to log in needs to raise a SystemExit exception. If the bot starts normally, the bot should be left to handle the exit case. It will raise SystemExit in a task, which will reach the event loop and interrupt running forever, then trigger our cleanup process, and does not need additional handling in this function. """ driver_cls = drivers.get_driver_class() await driver_cls.initialize(**data_manager.storage_details()) beastbot.logback.init_logging( level=cli_flags.logging_level, location=data_manager.core_data_path() / "logs", force_rich_logging=cli_flags.rich_logging, ) log.debug("====Basic Config====") log.debug("Data Path: %s", data_manager._base_data_path()) log.debug("Storage Type: %s", data_manager.storage_type()) # lib folder has to be in sys.path before trying to load any 3rd-party cog (GH-3061) # We might want to change handling of requirements in Downloader at later date LIB_PATH = data_manager.cog_data_path(raw_name="Downloader") / "lib" LIB_PATH.mkdir(parents=True, exist_ok=True) if str(LIB_PATH) not in sys.path: sys.path.append(str(LIB_PATH)) # "It's important to note that the global `working_set` object is initialized from # `sys.path` when `pkg_resources` is first imported, but is only updated if you do # all future `sys.path` manipulation via `pkg_resources` APIs. If you manually modify # `sys.path`, you must invoke the appropriate methods on the `working_set` instance # to keep it in sync." # Source: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#workingset-objects pkg_resources.working_set.add_entry(str(LIB_PATH)) sys.meta_path.insert(0, SharedLibImportWarner()) if cli_flags.token: token = cli_flags.token else: token = os.environ.get("RED_TOKEN", None) if not token: token = await red._config.token() prefix = cli_flags.prefix or await red._config.prefix() if not (token and prefix): if cli_flags.no_prompt is False: new_token = await interactive_config(red, token_set=bool(token), prefix_set=bool(prefix)) if new_token: token = new_token else: log.critical("Token and prefix must be set in order to login.") sys.exit(1) if cli_flags.dry_run: await red.http.close() sys.exit(0) try: await red.start(token, bot=True, cli_flags=cli_flags) except discord.LoginFailure: log.critical("This token doesn't seem to be valid.") db_token = await red._config.token() if db_token and not cli_flags.no_prompt: if confirm("\nDo you want to reset the token?"): await red._config.token.set("") print("Token has been reset.") sys.exit(0) sys.exit(1) except discord.PrivilegedIntentsRequired: print( "Red requires all Privileged Intents to be enabled.\n" "You can find out how to enable Privileged Intents with this guide:\n" "https://docs.discord.red/en/stable/bot_application_guide.html#enabling-privileged-intents" ) sys.exit(1) return None