diff --git a/markdown/Deep Dive: Discord-Linux Automated Container Platform.md b/markdown/Deep Dive: Discord-Linux Automated Container Platform.md index e7ec5d3..0599f97 100644 --- a/markdown/Deep Dive: Discord-Linux Automated Container Platform.md +++ b/markdown/Deep Dive: Discord-Linux Automated Container Platform.md @@ -498,6 +498,159 @@ The menu is dynamically generated, allowing users to make their selection. If th This safeguard prevents users from accidentally deleting important containers or data, which is especially useful in environments where multiple users or containers are being managed. + +# Executing Shell Commands Using Discord Bot (Non-Interactive Execution) + +The platform’s ability to execute commands non-interactively via Discord is a game-changer for container management and remote server operations. This powerful feature lets users run commands, manage files, check system statuses, and more—all from a simple Discord interface, without needing further interaction after issuing a command. In this post, we will dive into how the system works, highlighting some special custom-coded commands like `cd`, `pwd`, and `ls`, and how the platform ensures non-interactive command execution. + +### Non-Interactive Command Execution Overview + +Non-interactive execution means that once a user submits a command through the bot, it completes without asking for additional input. This is incredibly useful when dealing with long-running processes or package installations, where user input (like confirmations) is usually required. The bot takes care of everything—from preparing the command, running it, and presenting the result. + +The bot executes commands inside Docker containers specific to each user, providing isolated environments. These containers are used to execute commands non-interactively, meaning once you send the command, the bot does the rest. + +### Command Handling Flow + +The bot's `/x` command allows users to execute commands within their container. Here’s the general structure of how it works: + +```javascript +module.exports = { + name: "x", + description: "Execute a command non-interactively.", + options: [ + { + name: "cmd", + description: "Command to Execute", + required: true, + type: 3 // STRING type + } + ], + run: async (client, interaction) => { + let sshSurfID = await getUserContainerID(interaction.user.id); + let userPWD = await getUserPWD(interaction.user.id); + + if (!sshSurfID) { + await interaction.editReply("You don't have a container currently. Please generate one using /generate."); + return; + } + + let commandToRun = interaction.options.get("cmd").value; + + // Handle special cases (custom commands like cd, pwd, and ls) + commandToRun = handleCustomCommands(commandToRun, userPWD, sshSurfID, interaction); + + // Run the command in a non-interactive manner within the user's container + executeCommandInContainer(sshSurfID, userPWD, commandToRun, interaction); + } +}; +``` + +### Custom Coded Commands: `cd`, `pwd`, `ls` + +In addition to executing common system commands like `apt`, `yum`, or `neofetch`, the platform includes custom implementations for commands like `cd`, `pwd`, and `ls`. These are custom coded to work seamlessly with the platform, ensuring non-interactive behavior. + +#### `cd` (Change Directory) +The `cd` command allows users to navigate through the file system within their container. Since changing directories is fundamental for any file operation, the platform implements `cd` in a custom way. + +The custom `cd` command ensures that the current working directory is updated on the platform, and it intelligently handles edge cases like moving up (`cd ..`), moving to a root directory (`cd /`), or using the home directory shortcut (`cd ~`). This is all handled behind the scenes, and the updated directory is stored in the user’s session for future commands. + +Here’s a simplified view of the custom `cd` logic: + +```javascript +if (commandToRun.startsWith("cd")) { + let newDirectory = handleCdCommand(commandToRun, userPWD); // Handles various cases like `..`, `~`, and `/` + updatePWD(newDirectory, sshSurfID); // Update user's current directory + interaction.editReply(`Directory changed to: ${newDirectory}`); +} +``` + +#### `pwd` (Print Working Directory) +The `pwd` command is another custom implementation. Instead of executing the Linux `pwd` command inside the container, the bot retrieves the user's current working directory directly from the platform’s stored session. This ensures faster responses and removes the need for running the command in the container itself. + +```javascript +if (commandToRun === "pwd") { + interaction.editReply(`\`\`\`${userPWD}\`\`\``); +} +``` + +This custom `pwd` command guarantees that the bot provides accurate feedback on the user's current directory, without needing to execute a process inside the container. + +#### `ls` (List Directory Contents) +The `ls` command is handled in a slightly more complex way because it needs to interact with the file system to show directory contents. The platform uses Docker's `exec` feature to run the `ls` command inside the container, while still ensuring non-interactive execution. + +```javascript +if (commandToRun.startsWith("ls")) { + // Execute ls inside the user's container non-interactively + customerContainer.exec(['/bin/bash', '-c', `cd ${userPWD} && ls -lah`], { stdout: true, stderr: true }, (err, out) => { + interaction.editReply(`\`\`\`${out.stdout}\`\`\``); + }); +} +``` + +The result is that `ls` works just like it would in a standard Linux environment, listing directory contents in a user-friendly way. + +### Handling Non-Interactive Execution + +Non-interactive commands are a core feature of this platform. Commands that typically require user input (like `apt install`) are automatically modified to run without interaction. For example, if a user runs `apt install`, the bot adds the `-y` flag to ensure the process runs without requiring further confirmation: + +```javascript +if (commandToRun.startsWith("apt install") || commandToRun.startsWith("yum install")) { + if (!commandToRun.includes("-y")) { + commandToRun += " -y"; // Automatically add non-interactive flag + } +} +``` + +This customization ensures that no matter what command you issue, it will complete without stopping to ask for confirmation or additional input. + +### Executing Commands in the Container + +Once the command is prepared, the bot uses Docker to execute it inside the user's container. This is done non-interactively, meaning the user doesn’t need to stay engaged for the command to finish. + +Here’s how the bot executes commands inside the container: + +```javascript +const customerContainer = docker.getContainer(sshSurfID); + +customerContainer.exec(['/bin/bash', '-c', `cd ${userPWD} && ${commandToRun}`], { stdout: true, stderr: true }, (err, out) => { + if (err || !out) { + interaction.editReply("```️️️️Your container either needs to be generated or is not running.```"); + return; + } + + if (out.inspect.ExitCode !== 0) { + interaction.editReply(`\`\`\`Error: ${out.stderr}\`\`\``); + } else { + interaction.editReply(`\`\`\`${out.stdout}\`\`\``); + } +}); +``` + +The command is executed within the container, and the result (either success or failure) is sent back to the user in Discord. + +### Output Management + +Command outputs are returned directly in Discord. However, if the output is too long to fit in a single message, the platform uses a service like `dpaste` to upload the output and return a link to the user: + +```javascript +if (out.stdout.length > 2020) { + fs.writeFile('/tmp/paste', `Command: ${commandToRun}\n${out.stdout}`, err => { + if (err) console.error(err); + }); + cmd("sleep 2; cat /tmp/paste | dpaste").then(pasteout => { + interaction.editReply(`The command output was too large for Discord. Check it here: ${pasteout.stdout}`); + }); +} else { + interaction.editReply(`\`\`\`${out.stdout}\`\`\``); +} +``` + +This ensures that even large outputs can be managed efficiently and that users always receive the results of their commands. + +The platform’s ability to run commands non-interactively via Discord is incredibly powerful. With custom-coded commands like `cd`, `pwd`, and `ls`, users can easily navigate and interact with their containerized environments. The platform's non-interactive approach ensures that commands run to completion without requiring additional input, making it a smooth experience for users managing servers and systems remotely. + +By leveraging Docker, REST logging, and thoughtful command handling, the platform delivers a flexible and secure way for users to run commands, all within a familiar interface like Discord. + ### Container Destruction Once the user confirms that they want to proceed, the bot performs the actual destruction of the container. This is done by stopping and removing the container using Docker’s command-line interface.