const http = require("http"); const { WebSocketServer } = require("ws"); var fplay = {}; fplay.PORT = 3030; fplay.COMMAND_TIMEOUT = 5000; fplay.PASSWORD = "cnc"; const { EventEmitter } = require("events"); fplay.event = new EventEmitter(); fplay.server = http.createServer(function(req, res){ switch(req.url){ case "/" + fplay.PASSWORD: res.writeHead(426, { "Content-Type": "application/json" }); res.end(JSON.stringify({"status": "No websocket upgrade received"})); break; default: res.writeHead(404, { "Content-Type": "application/json" }); res.end(JSON.stringify({ "status": "Invalid endpoint" })); } }); fplay.wss = new WebSocketServer({ server: fplay.server, path: "/" + fplay.PASSWORD }); fplay.seqid = 0; fplay.pending = new Map(); // promise map fplay.pending_dom_ready = new Map(); // helper functions fplay.send = async function(ws, action, msg = {}){ const seqid = ++fplay.seqid; msg.action = action; msg.seqid = seqid; return new Promise(function(resolve){ const timer = setTimeout(function(){ fplay.pending.delete(seqid); resolve(false); }, fplay.COMMAND_TIMEOUT); fplay.pending.set(seqid, { resolve: function(data){ clearTimeout(timer); resolve(data); }, reject: function(){ clearTimeout(timer); resolve(false); } }); ws.send(JSON.stringify(msg)); }); } fplay.wait_random = async function(min, max){ return new Promise(function(resolve){ setTimeout(function(){ resolve(true); }, min + Math.round(Math.random() * (max - min))) }); } fplay.parse_cookies = function(headers){ var cookies = {}; headers.forEach(function(header){ var cookie = header.split(":") var header_name = cookie.shift(); if(header_name.toLowerCase() != "cookie"){ return; } // continue; cookie = cookie.join(":").split(";"); cookie.forEach(function(c){ c = c.split("="); var key = c.shift().trim(); var value = c.join("="); cookies[key] = value; }); }); return cookies; } // // Misc protocol functions // fplay.get_ua = async function(ws){ var ua = await fplay.send(ws, "get_ua"); if(typeof ua.ua == "string"){ return ua.ua; } return false; } // // Tab functions // fplay.get_tab_list = async function(ws){ var tabs = await fplay.send(ws, "get_tabs"); if(typeof tabs.tabs == "object"){ return tabs.tabs; } return false; } fplay.tab_open = async function(ws, url, await_dom_ready = false, container = null){ var data = { url: url }; if(container !== null){ if( typeof container == "object" && typeof container.id != "undefined" ){ data.container = container.id; } if(typeof container == "string"){ data.container = container; } } var newtab = await fplay.send(ws, "tab_open", data); if(typeof newtab.data == "object"){ if(await_dom_ready){ var data = await fplay.wait_for_dom_ready(newtab.data.id); return data; } return newtab.data; } return false; } // @ tab_ids: number, array or tab object fplay.tab_close = async function(ws, tab_ids){ if( typeof tab_ids == "object" && typeof tab_ids.id == "number" ){ tab_ids = tab_ids.id; } var closed_tab_count = await fplay.send(ws, "tab_close", {"tabid": tab_ids}); if(typeof closed_tab_count.closed_tab_count == "number"){ return closed_tab_count.closed_tab_count; } return false; } fplay.close_all_tabs = async function(ws){ const tabs = await fplay.get_tab_list(ws); const newtab = await fplay.tab_open(ws, "about:blank"); // clean up useless tabs var tabs_to_close = []; for(var i=0; i