diff --git a/DiscordBotPlugin/PluginMain.cs b/DiscordBotPlugin/PluginMain.cs index 7331846..96436ae 100644 --- a/DiscordBotPlugin/PluginMain.cs +++ b/DiscordBotPlugin/PluginMain.cs @@ -935,10 +935,7 @@ private async Task OnButtonPress(SocketMessageComponent arg) // Check if the user has the appropriate role if (arg.User is SocketGuildUser user) { - _client.PurgeUserCache(); // Try to clear cache so we can get the latest roles - - string[] roles = _settings.MainSettings.DiscordRole.Split(','); - hasServerPermission = !_settings.MainSettings.RestrictFunctions || user.Roles.Any(r => roles.Contains(r.Name)); + hasServerPermission = HasServerPermission(user); } if (!hasServerPermission) @@ -2012,9 +2009,7 @@ private async Task SlashCommandHandler(SocketSlashCommand command) if (command.User is SocketGuildUser user) { - // The user has the permission if either RestrictFunctions is turned off, or if they are part of the appropriate role. - string[] roles = _settings.MainSettings.DiscordRole.Split(','); - hasServerPermission = !_settings.MainSettings.RestrictFunctions || user.Roles.Any(r => roles.Contains(r.Name)); + hasServerPermission = HasServerPermission(user); } if (!hasServerPermission) @@ -2139,9 +2134,7 @@ private async Task SlashCommandHandler(SocketSlashCommand command) if (command.User is SocketGuildUser user) { - // The user has the permission if either RestrictFunctions is turned off, or if they are part of the appropriate role. - string[] roles = _settings.MainSettings.DiscordRole.Split(','); - hasServerPermission = !_settings.MainSettings.RestrictFunctions || user.Roles.Any(r => roles.Contains(r.Name)); + hasServerPermission = HasServerPermission(user); } if (!hasServerPermission) @@ -2303,6 +2296,15 @@ private string GetMemoryUsage() } } + private bool HasServerPermission(SocketGuildUser user) + { + _client.PurgeUserCache(); // Try to clear cache so we can get the latest roles + + // The user has the permission if either RestrictFunctions is turned off, or if they are part of the appropriate role. + string[] roles = _settings.MainSettings.DiscordRole.Split(','); + return !_settings.MainSettings.RestrictFunctions || user.Roles.Any(r => roles.Contains(r.Name)) || user.Roles.Any(r => roles.Contains(r.Id.ToString())); + } + public class ServerInfo { public string ServerName { get; set; } diff --git a/DiscordBotPlugin/Settings.cs b/DiscordBotPlugin/Settings.cs index e5e2ba5..d9414a4 100644 --- a/DiscordBotPlugin/Settings.cs +++ b/DiscordBotPlugin/Settings.cs @@ -48,7 +48,7 @@ public class DiscordBotSettings : SettingSectionStore [WebSetting("Restrict Functions to Discord Role", "Restrict server functions (start/stop/restart/kill/update/console/manage) to Discord role", false, Subcategory: "Discord Config:settings:1")] public bool RestrictFunctions = false; - [WebSetting("Discord Role Name(s)", "Name of the role in your Discord server that should be allowed to excecute server functions. For multiple roles, enter each one split by a comma (e.g Role1,Role2)", false, Subcategory: "Discord Config:settings:1")] + [WebSetting("Discord Role Name(s)/ID(s)", "Name or ID of the role(s) in your Discord server that should be allowed to excecute server functions. For multiple roles, enter each one split by a comma (e.g Role1,Role2)", false, Subcategory: "Discord Config:settings:1")] public string DiscordRole = ""; [WebSetting("Log Button Presses and Commands", "Log when buttons are pressed and commands are used", false, Subcategory: "Logging:output:4")] diff --git a/README.md b/README.md index e6587cd..94526ff 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,11 @@ Web Panel: ## Install Script Thanks to [Bluscream](https://github.com/Bluscream) there is now a handy install script to take care of activating instances, downloading the plugin, and enabling it. + The script can be found [here](https://github.com/winglessraven/AMP-Discord-Bot/blob/master/install_script.py). +For instructions to run the script, see [here](https://github.com/winglessraven/AMP-Discord-Bot/wiki/How-to-Run-the-Install-Script). + ## Configure AMP Before the plugin can be used you need to configure AMP in a specific way. **NOTE: The plugin cannot be used on ADS. It can only run on non-ADS instances.** ### Activate with a Developer Licence diff --git a/install_script.py b/install_script.py index 801551c..744aa5d 100644 --- a/install_script.py +++ b/install_script.py @@ -8,8 +8,9 @@ from datetime import datetime from pathlib import Path from typing import Any, Optional, Union -PathLike = Union[str, Path] +import argparse +PathLike = Union[str, Path] self: Path = Path(__file__).resolve() @@ -22,6 +23,7 @@ stream_handler.setFormatter(logging.Formatter(log_format)) logging.basicConfig(level=logging.DEBUG, handlers=[file_handler, stream_handler]) logger = logging.getLogger(__name__) + logger.debug(f'Logging started at {datetime.now()}') logger.debug('WARNING: This log might contain sensitive information, like license keys, instance names and paths.') logger.debug('Do not share this log unaltered!') @@ -31,13 +33,12 @@ def get_user_input(prompt: str, default: Union[str, None] = None) -> str: user_input = input(f"{prompt} (Default: {default}): ") return user_input if user_input else default -if os.name == 'nt': # Windows +if os.name == 'nt': # Windows base_path: Path = Path('C:\\AMPDatastore\\Instances\\') -elif os.name == 'posix': # Linux +elif os.name == 'posix': # Linux base_path: Path = Path('/home/amp/.ampdata/instances/') - -developer_license_key: str = '' +developer_license_key: str = '' github_api_url: str = 'https://api.github.com/repos/winglessraven/AMP-Discord-Bot/releases/latest' plugin_name: str = 'DiscordBotPlugin' dll_file_name: str = f'{plugin_name}.dll' @@ -67,19 +68,19 @@ def update_amp_config(instance_path: Path) -> None: shutil.copy2(config_path, backup_path) with open(config_path, 'r') as f: lines = f.readlines() - for i, line in enumerate(lines): - if line.startswith('AMP.LoadPlugins='): - plugins = line.split('=')[1].strip() - plugins_list = eval(plugins) - if plugin_name not in plugins_list: - plugins_list.append(plugin_name) + for i, line in enumerate(lines): + if line.startswith('AMP.LoadPlugins='): + plugins = line.split('=')[1].strip() + plugins_list = eval(plugins) + if plugin_name not in plugins_list: + plugins_list.append(plugin_name) lines[i] = 'AMP.LoadPlugins={}\n'.format(str(plugins_list)) with open(config_path, 'w') as f: f.writelines(lines) - logger.info(f'Updated AMP.LoadPlugins in {ampconfig_name}') + logger.info(f'Updated AMP.LoadPlugins in {config_path}') + break else: logger.info(f'{plugin_name} already in AMP.LoadPlugins') - break def copy_dll_to_plugin_folder(instance_path: Path) -> None: discordbot_plugin_dir = instance_path / plugin_dll_dir @@ -88,68 +89,72 @@ def copy_dll_to_plugin_folder(instance_path: Path) -> None: logger.info(f'Creating DiscordBotPlugin folder at {discordbot_plugin_dir}') discordbot_plugin_dir.mkdir(exist_ok=True) logger.info(f'Copying {dll_file_path} to {discordbot_plugin_dir}') - if discordbot_plugin_file.is_file(): - logger.info(f'{discordbot_plugin_file} already exists, overwriting') shutil.copy2(dll_file_path, discordbot_plugin_dir) def get_instance_dirs(base_path: Path) -> list[Path]: return [path for path in base_path.iterdir() if path.is_dir()] if __name__ == "__main__": + parser = argparse.ArgumentParser(description="AMP Discord Bot Install Script") + parser.add_argument('--update-only', action='store_true', help="Update only existing instances") + args = parser.parse_args() + # Get user input base_path = Path(get_user_input("Set base path", base_path)) - developer_license_key = get_user_input("Set developer license key [Empty skips activation]", developer_license_key) ads_instance_name = get_user_input("Set ADS name", ads_instance_name) + if not args.update_only: + developer_license_key = get_user_input("Set developer license key [Empty skips activation]", developer_license_key) + # Download latest plugin dll with urllib.request.urlopen(github_api_url) as response: release_info = json.load(response) - for asset in release_info['assets']: - if asset['name'] == dll_file_name: - asset_url = asset['browser_download_url'] - break - download_latest_dll(asset_url, dll_file_path) + for asset in release_info['assets']: + if asset['name'] == dll_file_name: + asset_url = asset['browser_download_url'] + break + download_latest_dll(asset_url, dll_file_path) # Get instance folders instance_dirs: list[Path] = get_instance_dirs(base_path) logger.info(f'Found instances: {[path.name for path in instance_dirs]}') - # Select instances to process - for instance_folder in list(instance_dirs): - if instance_folder.name == ads_instance_name: - instance_dirs.remove(instance_folder) - else: + # Remove ADS instance + instance_dirs = [d for d in instance_dirs if d.name != ads_instance_name] + + if not args.update_only: + # Select instances to process + for instance_folder in list(instance_dirs): choice = get_user_input(f'Process instance {instance_folder.name}?', 'y') if choice.lower() != 'y': logger.info(f'Skipping instance {instance_folder.name}') instance_dirs.remove(instance_folder) - logger.info(f'Selected instances: {[path.name for path in instance_dirs]}') + else: + instance_dirs = [d for d in instance_dirs if (d / plugin_dll_dir / dll_file_name).is_file()] + logger.info(f'Selected instances for update: {[path.name for path in instance_dirs]}') # Stop selected instances for instance_folder in instance_dirs: logger.info(f'Stopping instance {instance_folder.name}') execute_os_command(['ampinstmgr', 'stop', instance_folder.name]) - # Copy plugin dll and update amp config + # Copy plugin dll and update amp config + for instance_folder in instance_dirs: copy_dll_to_plugin_folder(instance_folder) - update_amp_config(instance_folder) + if not args.update_only: + update_amp_config(instance_folder) - # (Re)activate ADS instance - if developer_license_key: - #stop ADS + if not args.update_only and developer_license_key: + # (Re)activate ADS instance logger.info(f'Stopping {ads_instance_name}') execute_os_command(['ampinstmgr', 'stop', ads_instance_name]) - for instance_folder in instance_dirs: logger.info(f'Reactivating instance {instance_folder.name}') execute_os_command(['ampinstmgr', 'reactivate', instance_folder.name, developer_license_key]) - - #start ADS logger.info(f'Starting {ads_instance_name}') execute_os_command(['ampinstmgr', 'start', ads_instance_name]) - else: + elif not args.update_only: logger.info("Skipping activation, make sure you're using a developer license key for this instance.") - # Start selected instances for instance_folder in instance_dirs: