diff --git a/package.json b/package.json index f75c7a7..0546360 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "license": "ISC", "description": "", "dependencies": { + "cmd-promise": "^1.2.0", "discord.js": "^14.16.3", "jsonfile": "^6.1.0", "mysql2": "^3.11.3", diff --git a/user-bot.js b/user-bot.js index 28c580b..405c55d 100644 --- a/user-bot.js +++ b/user-bot.js @@ -4,7 +4,8 @@ import unirest from 'unirest'; import { readFileSync } from 'fs'; import mysql from 'mysql2'; const userWorkingDirectories = new Map(); - +import fs from 'fs'; +import cmd from 'cmd-promise'; let sshSurfID; // Variable to store the user ID from the database // Paths to config and tokens files @@ -316,89 +317,126 @@ client.on('interactionCreate', async interaction => { -case 'x': { + case 'x': { - const command = interaction.options.getString('command'); - - // Get the user's current working directory or default to root (/) - let userPWD = userWorkingDirectories.get(sshSurfID) || '/'; + const command = interaction.options.getString('command'); + + // Get the user's current working directory or default to root (/) + let userPWD = userWorkingDirectories.get(sshSurfID) || '/'; + + // Handle 'cd' command logic + if (command.startsWith('cd')) { + let argscmd = command.replace('cd ', '').trim(); + + // Handle 'cd ..' for going up one directory + if (argscmd === '..') { + if (userPWD !== '/') { + // Remove the last part of the current path + const newPWD = userPWD.split('/').slice(0, -1).join('/') || '/'; + userPWD = newPWD; + userWorkingDirectories.set(sshSurfID, newPWD); + await interaction.editReply(`Directory changed to: ${newPWD}`); + } else { + await interaction.editReply(`Already at the root directory: ${userPWD}`); + } + return; + } + + // Handle '~' for home directory + if (argscmd === '~') { + userPWD = '/root'; + userWorkingDirectories.set(sshSurfID, userPWD); + await interaction.editReply(`Directory changed to: ${userPWD}`); + return; + } + + // Handle absolute and relative paths + let newPWD; + if (argscmd.startsWith('/')) { + // Absolute path + newPWD = argscmd; + } else { + // Relative path + newPWD = `${userPWD}/${argscmd}`; + } + + // Normalize the path (remove extra slashes) + newPWD = newPWD.replace(/([^:]\/)\/+/g, "$1"); + + // Check if the user is trying to go back multiple directories (e.g., 'cd ../../') + if (argscmd.includes('../')) { + const numDirsBack = argscmd.split('../').length - 1; + newPWD = RemoveLastDirectoryPartOf(userPWD, numDirsBack); + } + + // Update the working directory + userWorkingDirectories.set(sshSurfID, newPWD); + await interaction.editReply(`Directory changed to: ${newPWD}`); + return; + } + + // If the command is not 'cd', run the command in the current working directory (or default to '/') + const execResponse = await makeApiRequest('/exec', apiToken, interaction, 'post', { + cmd: command, + pwd: userPWD // Use the current directory or default to '/' + }); + + // Handle the command output + if (execResponse.stdout.length > 2020) { + // If the output is too large, save it to a temporary file and upload to a paste service - // Handle 'cd' command logic - if (command.startsWith('cd')) { - let argscmd = command.replace('cd ', '').trim(); - - // Handle 'cd ..' for going up one directory - if (argscmd === '..') { - if (userPWD !== '/') { - // Remove the last part of the current path - const newPWD = userPWD.split('/').slice(0, -1).join('/') || '/'; - userPWD = newPWD; - userWorkingDirectories.set(sshSurfID, newPWD); - await interaction.editReply(`Directory changed to: ${newPWD}`); - } else { - await interaction.editReply(`Already at the root directory: ${userPWD}`); - } - return; - } - - // Handle '~' for home directory - if (argscmd === '~') { - userPWD = '/root'; - userWorkingDirectories.set(sshSurfID, userPWD); - await interaction.editReply(`Directory changed to: ${userPWD}`); - return; - } - - // Handle absolute and relative paths - let newPWD; - if (argscmd.startsWith('/')) { - // Absolute path - newPWD = argscmd; - } else { - // Relative path - newPWD = `${userPWD}/${argscmd}`; - } - - // Normalize the path (remove extra slashes) - newPWD = newPWD.replace(/([^:]\/)\/+/g, "$1"); - - // Check if the user is trying to go back multiple directories (e.g., 'cd ../../') - if (argscmd.includes('../')) { - const numDirsBack = argscmd.split('../').length - 1; - newPWD = RemoveLastDirectoryPartOf(userPWD, numDirsBack); - } - - // Update the working directory - userWorkingDirectories.set(sshSurfID, newPWD); - await interaction.editReply(`Directory changed to: ${newPWD}`); - return; - } - - // If the command is not 'cd', run the command in the current working directory (or default to '/') - const execResponse = await makeApiRequest('/exec', apiToken, interaction, 'post', { - cmd: command, - pwd: userPWD // Use the current directory or default to '/' - }); - - // Format the command output in a markdown code block - let replyMessage = `\`\`\`\n${execResponse.stdout || 'No output'}\n\`\`\``; - - // If there is an error, append the error message in another markdown code block - if (execResponse.stderr && execResponse.stderr.trim()) { - replyMessage += `\n**Error:**\n\`\`\`\n${execResponse.stderr}\n\`\`\``; - } - - // Reply with the formatted message - await interaction.editReply(replyMessage); - break; -} - -// Helper function to remove directories when using '../' -function RemoveLastDirectoryPartOf(the_url, num) { - var the_arr = the_url.split('/'); - the_arr.splice(-num, num); - return the_arr.join('/') || '/'; -} + + const tempFilePath = '/tmp/paste'; + const pasteCommand = `Command: ${command} | Container Owner: ${interaction.user.username}\n${execResponse.stdout}`; + + fs.writeFileSync(tempFilePath, pasteCommand, (err) => { + if (err) { + console.error(err); + return; + } + }); + + const pasteout = await cmd("sleep 2; cat /tmp/paste | dpaste"); + + // Create an embed with the paste link + const mainEmbed = new EmbedBuilder() + .setColor('#0099ff') + .setTitle(`Container Owner: ${interaction.user.username}`) + .setDescription(`The command: ${command} was too large for Discord.`) + .addFields( + { + name: 'Please check the below output log:', + value: pasteout.stdout.replace("Pro tip: you can password protect your paste just by typing a username and password after your paste command.", "") + .replace("Paste Saved: ", "") + .replace("-------------------------------------------------------", "") + } + ) + .setFooter({ text: `Requested by ${interaction.user.username}`, iconURL: `${interaction.user.displayAvatarURL()}` }); + + await interaction.editReply({ embeds: [mainEmbed] }); + + } else { + // If the output is small enough, format it in a markdown code block + let replyMessage = `\`\`\`\n${execResponse.stdout || 'No output'}\n\`\`\``; + + // If there is an error, append the error message in another markdown code block + if (execResponse.stderr && execResponse.stderr.trim()) { + replyMessage += `\n**Error:**\n\`\`\`\n${execResponse.stderr}\n\`\`\``; + } + + // Reply with the formatted message + await interaction.editReply(replyMessage); + } + break; + } + + // Helper function to remove directories when using '../' + function RemoveLastDirectoryPartOf(the_url, num) { + var the_arr = the_url.split('/'); + the_arr.splice(-num, num); + return the_arr.join('/') || '/'; + } + case 'notify':