589 lines
29 KiB
JavaScript
589 lines
29 KiB
JavaScript
import { Client } from "twitter-api-sdk";
|
|
import Twit from "twit";
|
|
import dotenv from "dotenv";
|
|
dotenv.config();
|
|
import fs from "fs";
|
|
import dateFormat from "dateformat"
|
|
import cmd from "cmd-promise";
|
|
import generator from "generate-password"
|
|
import jsonfile from "jsonfile"
|
|
import date from "date-and-time";
|
|
import Dockerode from 'simple-dockerode';
|
|
var docker = new Dockerode({ socketPath: '/var/run/docker.sock' });
|
|
let finished
|
|
let commandToRun
|
|
let ram
|
|
let vram
|
|
let cpus
|
|
let ifApt
|
|
let end = "<=================================END===========================>"
|
|
|
|
|
|
/*################################## TWITTER API #########################################*/
|
|
const config = {
|
|
consumer_key: process.env.TWITTER_API_KEY,
|
|
consumer_secret: process.env.TWITTER_API_SECRET_KEY,
|
|
access_token: process.env.TWITTER_ACCESS_TOKEN,
|
|
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
|
|
timeout_ms: 60 * 1000000,
|
|
strictSSL: true,
|
|
};
|
|
const T = new Twit(config);
|
|
|
|
const client = new Client(process.env.TWITTER_BEARER_TOKEN); //twitter api client
|
|
|
|
const botName = process.env.BOT_USERNAME; //Use the same Twitter username whose API key and token are being used.
|
|
|
|
/*############################# REPLY TO TWITTER API #################################*/
|
|
async function replyToTweet(joke, author_id, id) {
|
|
const data = {
|
|
status: `${joke}`, //the joke
|
|
in_reply_to_user_id: author_id, //the id of the user who tweeted
|
|
in_reply_to_status_id: id, //the id of the tweet
|
|
auto_populate_reply_metadata: true, //auto populate the reply metadata
|
|
};
|
|
try {
|
|
const resp = await T.post("statuses/update", data);
|
|
if (resp) {
|
|
console.log("replied");
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
|
|
/*############################# GET THE TWEETS FROM TWITTER API ##########################*/
|
|
|
|
async function getExitingRule() { //get the existing rules
|
|
try {
|
|
const rules = await client.tweets.getRules();
|
|
return rules;
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
async function deleteAndSetNewRules() { //delete the existing rules and set new rules
|
|
|
|
try {
|
|
const rules = await getExitingRule();
|
|
// if rules includes id in data then delete the rules
|
|
if (rules.data) {
|
|
console.log("rule exists, now deleting");
|
|
const ids = rules.data.map((rule) => rule.id);
|
|
await client.tweets.addOrDeleteRules({
|
|
delete: {
|
|
ids: ids,
|
|
}
|
|
});
|
|
}
|
|
console.log("setting new rules");
|
|
await client.tweets.addOrDeleteRules({
|
|
add: [
|
|
{
|
|
value: `@${botName} has:mentions`
|
|
}
|
|
]
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
|
|
async function getMentionedTweet() {
|
|
try {
|
|
console.log("running");
|
|
await deleteAndSetNewRules();
|
|
const stream = await client.tweets.searchStream({
|
|
"tweet.fields": [
|
|
"author_id", // The ID of the user who posted the tweet
|
|
"id", // The ID of the tweet
|
|
"in_reply_to_user_id" // The ID of the user the tweet is replying to
|
|
],
|
|
"expansions": [
|
|
"referenced_tweets.id.author_id" // The ID of the user who posted the referenced tweet
|
|
]
|
|
});
|
|
|
|
for await (const response of stream) {
|
|
if (response.data.text.includes(`@${botName}`)) { //check if the tweet contains the bot's username
|
|
|
|
/* IF BOT IS MENTIONED **IN** THE TWEET */
|
|
if (response.includes.tweets === undefined) { //check if the tweet is a reply to another tweet
|
|
const tweet = JSON.stringify(response.data.text, null, 2).replace(/(https?:\/\/[^\s]+)/g, '').replace(/"/g, '').trim(); r
|
|
|
|
console.log(response.data)
|
|
const reply = "works"
|
|
await replyToTweet(reply, response.data.author_id, response.data.id);
|
|
} else {
|
|
/* IF BOT IS MENTIONED **UNDER** THE TWEET THEN IT WILL REPLY TO WHOEVER MENTIONED
|
|
THE BOT BUT WILL TAKE QUESTIONS FROM THE ORIGINAL AUTHORS TWEET */
|
|
let userID = response.data.author_id
|
|
|
|
console.log("User ID: " + userID)
|
|
|
|
if (userID == "1600528742396399616") return
|
|
/////////////////////////////GENERATE
|
|
if (response.data.text.includes(`generate`)) {
|
|
cmd(`node /home/opc/genmulti_twit.js` + " " + userID + " " + userID + " " + userID + " ubuntu " + userID).then(out => {
|
|
console.log('out =', out)
|
|
const tweet = JSON.stringify(response.includes.tweets[0].text, null, 2).replace(/(https?:\/\/[^\s]+)/g, '').replace(/"/g, '').trim(); //remove the urls and double quotes from the tweet and trim the spaces
|
|
|
|
const now = new Date();
|
|
|
|
var password = generator.generate({
|
|
length: 10,
|
|
numbers: true
|
|
});
|
|
|
|
let rootPass = password
|
|
|
|
cmd("node /exec/dockerexec.js " + userID + " " + "/home" + " " + "\"" + "echo \'root:" + rootPass + "\' | chpasswd" + "\"").then(out => {
|
|
(async () => {
|
|
|
|
console.log('out =', out.stdout)
|
|
|
|
const reply = "Generated!\n The container will be removed in 7 days!" //get the joke from the openai api
|
|
return await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})();
|
|
|
|
}).catch(err => {
|
|
console.log('err=', err)
|
|
if (err.toString().includes("Conflict")) {
|
|
return
|
|
}
|
|
}).catch(err => {
|
|
console.log('err =', err)
|
|
})
|
|
}).catch(err => {
|
|
(async () => {
|
|
(async () => {
|
|
const reply = "You have a container!" //get the joke from the openai api
|
|
return await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})(); console.log(end)
|
|
})();
|
|
console.log(err)
|
|
return
|
|
})
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
if (response.data.text.includes(`destroy`)) {
|
|
cmd('docker stop ' + userID + " && docker rm " + userID).then(out => {
|
|
console.log('out =', out)
|
|
const netConfig = '/home/opc/netcache/' + userID + ".network"
|
|
try {
|
|
fs.unlinkSync(netConfig)
|
|
console.log("Network Config Removed!")
|
|
} catch(err) {
|
|
console.log("No Config to remove")
|
|
|
|
}
|
|
|
|
const now = new Date();
|
|
|
|
(async () => {
|
|
const reply = "The container was destroyed.\n Come back again!" //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
return console.log(end)
|
|
})();
|
|
}).catch(err => {
|
|
if (err.toString().includes("such")) {
|
|
(async () => {
|
|
const reply = "No Container can be destroyed." //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
return console.log(end)
|
|
})();
|
|
}
|
|
console.log('err =', err)
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (response.data.text.includes(`exec`)) {
|
|
const tweet = JSON.stringify(response.includes.tweets[0].text, null, 2).replace("exec ", "").replace("@twit-linux ", ""); //remove the urls and double quotes from the tweet and trim the spaces
|
|
|
|
console.log("RUN")
|
|
if (tweet.includes("destroy")) return
|
|
if (tweet.includes("generate")) return
|
|
await cmd('bash /home/opc/check_exist.sh ' + userID).then(out => {
|
|
console.log('out =', out)
|
|
if (out.stdout != 1) {
|
|
(async () => {
|
|
finished = 1
|
|
console.log(end)
|
|
const reply = "You do not have a container! Use the generate command to make one." //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})();
|
|
|
|
}
|
|
|
|
}).catch(err => {
|
|
console.log('err =', err)
|
|
})
|
|
console.log("Begin Done")
|
|
|
|
if (finished == 1) {
|
|
finished = 0
|
|
return
|
|
} else {
|
|
|
|
const path = 'cache/' + userID
|
|
|
|
|
|
let test = tweet.replace("@twit_liux ", "").replace("exec ", "").replace(/['"]+/g, '').split(" ")
|
|
|
|
const result = test.filter(word => !word.startsWith("@"));
|
|
let final = result.join(" ")
|
|
|
|
let code = final
|
|
|
|
console.log("F: " + final)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (code.startsWith("apt install") || code.startsWith("yum install")) {
|
|
if (!code.includes("-y")) {
|
|
code = code + " -y"
|
|
console.log(code)
|
|
}
|
|
}
|
|
|
|
if (code.startsWith("pacman install")) {
|
|
if (!code.includes("--noconfirm")) {
|
|
code = code + " --noconfirm"
|
|
console.log(code)
|
|
}
|
|
}
|
|
|
|
|
|
if (code.startsWith("neofetch")) {
|
|
code = "neofetch --stdout"
|
|
}
|
|
|
|
if (fs.existsSync(path)) {
|
|
console.log("")
|
|
}
|
|
else {
|
|
console.log("No Channel PWD Found! Generating!")
|
|
fs.writeFile('./cache/' + userID, "{\"pwd\":\"/\"}", function (err) {
|
|
});
|
|
}
|
|
commandToRun = code.replace("@twit_linux ", "").replace("exec ", "").replace(/['"]+/g, '')
|
|
console.log("Running: " + commandToRun)
|
|
if (commandToRun == "yes") return console.log("yes Blocked")
|
|
|
|
/**
|
|
*
|
|
* Start of Print Working Directory
|
|
*
|
|
*/
|
|
if (commandToRun == "pwd") {
|
|
goNoFurther = true
|
|
// check for channel pwd support file
|
|
if (fs.existsSync(path)) {
|
|
console.log("Channel PWD is active")
|
|
jsonfile = require('jsonfile')
|
|
jsonfile.readFile(path, function (err, pwdata) {
|
|
// console.log(pwdata)
|
|
(async () => {
|
|
|
|
|
|
const reply = pwdata.pwd //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})();
|
|
goNoFurther = false;
|
|
if (err) console.error(err)
|
|
})
|
|
}
|
|
function escapeDoubleQuotes(str) {
|
|
return str.replace(/\\([\s\S])|(")/g, "\\$1$2"); // thanks @slevithan!
|
|
}
|
|
}
|
|
/**
|
|
*
|
|
* Main
|
|
*
|
|
*/
|
|
if (commandToRun == "pwd") return
|
|
|
|
|
|
/**
|
|
*
|
|
* Start of CD
|
|
*
|
|
*/
|
|
if (commandToRun.startsWith("cd")) {
|
|
console.log("test")
|
|
argscmd = tweet
|
|
|
|
|
|
// check for channel pwd support file
|
|
|
|
if (fs.existsSync(path)) {
|
|
console.log("Channel PWD is active")
|
|
jsonfile = require('jsonfile')
|
|
jsonfile.readFile(path, function (err, pwdata) {
|
|
let argscmd = commandToRun.replace("cd ", "")
|
|
let dir = argscmd; // yes, start at 0, not 1. I hate that too.
|
|
|
|
|
|
if (startsWith(argscmd, "/") == false) {
|
|
const cmd = require('cmd-promise')
|
|
if (!argscmd) {
|
|
(async () => {
|
|
|
|
const reply = "Give my Syntax Please" //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id);
|
|
})();
|
|
return
|
|
}
|
|
|
|
let dir = commandToRun; // yes, start at 0, not 1. I hate that too.
|
|
let data
|
|
jsonfile.readFile(path, function (err, pwdata) {
|
|
if (err) console.error(err)
|
|
console.log(dir)
|
|
data = pwdata.pwd + "/" + argscmd
|
|
if (pwdata.pwd == "/") {
|
|
data = "/" + argscmd
|
|
}
|
|
if (argscmd == "~") {
|
|
data = "/root"
|
|
}
|
|
if (argscmd.includes("~") && argscmd.includes("/")) {
|
|
data = "/root" + "/" + argscmd.replace("~", "")
|
|
}
|
|
|
|
if (argscmd.includes("..") || argscmd.includes("../")) { // check if the user is trying to go back a directory
|
|
|
|
console.log(argscmd.split("../"))
|
|
console.log("user wants to go back " + argscmd.split("../").length + " directories")
|
|
|
|
function RemoveLastDirectoryPartOf(the_url, num) {
|
|
var the_arr = the_url.split('/');
|
|
the_arr.splice(-num, num)
|
|
return (the_arr.join('/'));
|
|
}
|
|
data = RemoveLastDirectoryPartOf(pwdata.pwd, argscmd.split("../").length - 1)
|
|
}
|
|
|
|
let final = data.replace(/([^:]\/)\/+/g, "$1")
|
|
console.log(final)
|
|
|
|
const obj = {
|
|
pwd: final
|
|
}
|
|
jsonfile.writeFile(path, obj, function (err) {
|
|
(async () => {
|
|
|
|
const reply = "Directory Changed to: " + final
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})();
|
|
if (err) console.error(err)
|
|
})
|
|
|
|
});
|
|
|
|
} else {
|
|
jsonfile.readFile(path, function (err, pwdata) {
|
|
if (err) console.error(err)
|
|
console.log('dir:' + dir)
|
|
//onsole.log(dir)
|
|
|
|
const obj = {
|
|
pwd: dir.replace(/([^:]\/)\/+/g, "$1")
|
|
}
|
|
jsonfile.writeFile(path, obj, function (err) {
|
|
if (err) console.error(err)
|
|
})
|
|
goNoFurther = false;
|
|
});
|
|
(async () => {
|
|
const reply = "Directory Changed to: " + dir.replace(/([^:]\/)\/+/g, "$1")
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
})();
|
|
}
|
|
function RemoveLastDirectoryPartOf(the_url) {
|
|
var the_arr = the_url.split('/');
|
|
the_arr.pop();
|
|
return (the_arr.join('/'));
|
|
}
|
|
function startsWith(str, word) {
|
|
return str.lastIndexOf(word, 0) === 0;
|
|
}
|
|
})
|
|
}
|
|
}
|
|
/**
|
|
*
|
|
* End of CD
|
|
*
|
|
*/
|
|
|
|
if (commandToRun.startsWith("destroy")) return
|
|
if (commandToRun.startsWith("generate")) return
|
|
|
|
|
|
if (commandToRun.startsWith("cd")) return console.log("Skipped At Main")
|
|
if (commandToRun.startsWith("write")) return
|
|
if (commandToRun == "gobk") return
|
|
|
|
if (fs.existsSync(path)) {
|
|
function RemoveLastDirectoryPartOf(the_url) {
|
|
var the_arr = the_url.split('/');
|
|
the_arr.pop();
|
|
return (the_arr.join('/'));
|
|
}
|
|
console.log("Channel PWD is active")
|
|
jsonfile.readFile(path, function (err, pwdata) {
|
|
console.log(pwdata)
|
|
if (code == "neofetch") {
|
|
code = "neofetch --stdout --color_blocks off"
|
|
}
|
|
if (code.startsWith("apt")) {
|
|
ifApt = "-y"
|
|
} else if (code.startsWith("yum")) {
|
|
ifApt = "-y"
|
|
}
|
|
else if (code.startsWith("pacman")) {
|
|
ifApt = "--noconfirm"
|
|
} else if (code.startsWith("apt-get")) {
|
|
ifApt = "-y"
|
|
}
|
|
else {
|
|
ifApt = ""
|
|
}
|
|
|
|
if (code.includes("~")) {
|
|
code = code.replace("~", "/root")
|
|
}
|
|
if (code.includes("..")) {
|
|
pwdata.pwd = RemoveLastDirectoryPartOf(pwdata.pwd)
|
|
}
|
|
|
|
|
|
// if (code.includes("../")) { // check if the user is trying to go back a directory
|
|
|
|
// function RemoveLastDirectoryPartOf(the_url, num) {
|
|
// var the_arr = the_url.split('/');
|
|
// the_arr.splice(-num, num)
|
|
// return (the_arr.join('/'));
|
|
// }
|
|
// console.log(argscmd.split("../"))
|
|
// console.log("user wants to go back " + argscmd.split("../").length -1 + " directories in their command")
|
|
|
|
// pwddata.pwd = RemoveLastDirectoryPartOf(pwdata.pwd, argscmd.split("../").length - 1)
|
|
// }
|
|
|
|
const customerContainer = docker.getContainer(userID);
|
|
// Simple to grab the stdout and stderr.
|
|
customerContainer.exec(['/bin/bash', '-c', 'cd ' + pwdata.pwd + ' && ' + commandToRun], { stdout: true, stderr: true }, (err, out) => {
|
|
if (typeof (out) !== 'undefined') {
|
|
console.log(out.stdout)
|
|
|
|
if (out.inspect.ExitCode !== 0) {
|
|
if (out.stderr.includes("syntax error")) {
|
|
(async () => {
|
|
const reply = "There is an error in your syntax, please try again."
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
console.log(end)
|
|
|
|
})();
|
|
} else {
|
|
(async () => {
|
|
const reply = out.stderr
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
|
|
console.log(end)
|
|
|
|
})();
|
|
}
|
|
}
|
|
if (out.inspect.ExitCode == 0) {
|
|
if (!out.stdout) {
|
|
(async () => {
|
|
const reply = 'Command Executed Successfully!'
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
|
|
})();
|
|
} else {
|
|
if (out.stdout.length > 230) {
|
|
fs.writeFile('/tmp/paste', "Command: " + code.replace("--stdout --color_blocks off", "") + " | Container Owner: " + userID + "\n" + out.stdout, err => {
|
|
if (err) {
|
|
console.error(err)
|
|
return
|
|
}
|
|
})
|
|
cmd("sleep 2; cat /tmp/paste | dpaste").then(pasteout => {
|
|
|
|
(async () => {
|
|
console.log(end)
|
|
const reply = "Too Large, Check: " + pasteout.stdout.replace("paste.discord-linux.com", "twit-log.ssh.surf").replace("Pro tip: you can password protect your paste just by typing a username and password after your paste command.", "").replace("Paste Saved: ", "").replace("-------------------------------------------------------", "") //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
|
|
})();
|
|
|
|
})
|
|
}
|
|
else {
|
|
|
|
|
|
//<@UserID NUMBER>
|
|
(async () => {
|
|
const reply = out.stdout //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
console.log("<=================================END===========================>")
|
|
})();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
(async () => {
|
|
const reply = "Your container either needs to be generated or is not running." //get the joke from the openai api
|
|
await replyToTweet(reply, response.data.author_id, response.data.id); // reply to the
|
|
return console.log(end)
|
|
})();
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////// END OF X
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
|
|
}
|
|
|
|
getMentionedTweet();
|