mirror of
https://github.com/lan-tianxiang/JS_TOOL.git
synced 2025-07-19 12:53:49 +08:00
1045 lines
32 KiB
JavaScript
Executable File
1045 lines
32 KiB
JavaScript
Executable File
|
||
/*
|
||
* @Author: Jerrykuku https://github.com/jerrykuku
|
||
* @Date: 2021-1-8
|
||
* @Version: v0.0.2
|
||
* @thanks: FanchangWang https://github.com/FanchangWang
|
||
*/
|
||
|
||
var express = require('express');
|
||
var session = require('express-session');
|
||
var compression = require('compression');
|
||
var bodyParser = require('body-parser');
|
||
var got = require('got');
|
||
var path = require('path');
|
||
var fs = require('fs');
|
||
var { execSync, exec } = require('child_process');
|
||
const crypto = require('crypto');
|
||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||
|
||
|
||
var rootPath = path.resolve(__dirname, '..');
|
||
// cookie.sh 文件所在目录
|
||
var ckFile = path.join(rootPath, 'config/cookie.sh');
|
||
// config.sh 文件所在目录
|
||
var confFile = path.join(rootPath, 'config/config.sh');
|
||
// config.sh.sample 文件所在目录
|
||
var sampleFile = path.join(rootPath, 'sample/config.sh.sample');
|
||
// crontab.list 文件所在目录
|
||
var crontabFile = path.join(rootPath, 'config/crontab.list');
|
||
// config.sh 文件备份目录
|
||
var confBakDir = path.join(rootPath, 'config/bak/');
|
||
// auth.json 文件目录
|
||
var authConfigFile = path.join(rootPath, 'config/auth.json');
|
||
// 限制文件
|
||
var autoConfigFile = path.join(rootPath, '.AutoConfig/config.sh');
|
||
// Share Code 文件目录
|
||
var shareCodeDir = path.join(rootPath, 'log/jd_get_share_code/');
|
||
// diy.sh 文件目录
|
||
var diyFile = path.join(rootPath, 'config/diy.sh');
|
||
// 日志目录
|
||
var logPath = path.join(rootPath, 'log/');
|
||
// 脚本目录
|
||
var ScriptsPath = path.join(rootPath, 'scripts/');
|
||
|
||
var authError = "错误的用户名密码,请重试";
|
||
var loginFaild = "请先登录!";
|
||
|
||
var configString = "config usrconfig sample crontab shareCode diy";
|
||
|
||
var s_token, cookies, guid, lsid, lstoken, okl_token, token, userCookie = "";
|
||
|
||
var ErrorTimes = 0;
|
||
|
||
function praseSetCookies(response) {
|
||
s_token = response.body.s_token
|
||
guid = response.headers['set-cookie'][0]
|
||
guid = guid.substring(guid.indexOf("=") + 1, guid.indexOf(";"))
|
||
lsid = response.headers['set-cookie'][2]
|
||
lsid = lsid.substring(lsid.indexOf("=") + 1, lsid.indexOf(";"))
|
||
lstoken = response.headers['set-cookie'][3]
|
||
lstoken = lstoken.substring(lstoken.indexOf("=") + 1, lstoken.indexOf(";"))
|
||
cookies = "guid=" + guid + "; lang=chs; lsid=" + lsid + "; lstoken=" + lstoken + "; "
|
||
}
|
||
|
||
function getCookie(response) {
|
||
var TrackerID = response.headers['set-cookie'][0]
|
||
TrackerID = TrackerID.substring(TrackerID.indexOf("=") + 1, TrackerID.indexOf(";"))
|
||
var pt_key = response.headers['set-cookie'][1]
|
||
pt_key = pt_key.substring(pt_key.indexOf("=") + 1, pt_key.indexOf(";"))
|
||
var pt_pin = response.headers['set-cookie'][2]
|
||
pt_pin = pt_pin.substring(pt_pin.indexOf("=") + 1, pt_pin.indexOf(";"))
|
||
var pt_token = response.headers['set-cookie'][3]
|
||
pt_token = pt_token.substring(pt_token.indexOf("=") + 1, pt_token.indexOf(";"))
|
||
var pwdt_id = response.headers['set-cookie'][4]
|
||
pwdt_id = pwdt_id.substring(pwdt_id.indexOf("=") + 1, pwdt_id.indexOf(";"))
|
||
var s_key = response.headers['set-cookie'][5]
|
||
s_key = s_key.substring(s_key.indexOf("=") + 1, s_key.indexOf(";"))
|
||
var s_pin = response.headers['set-cookie'][6]
|
||
s_pin = s_pin.substring(s_pin.indexOf("=") + 1, s_pin.indexOf(";"))
|
||
cookies = "TrackerID=" + TrackerID + "; pt_key=" + pt_key + "; pt_pin=" + pt_pin + "; pt_token=" + pt_token + "; pwdt_id=" + pwdt_id + "; s_key=" + s_key + "; s_pin=" + s_pin + "; wq_skey="
|
||
var userCookie = "pt_key=" + pt_key + ";pt_pin=" + pt_pin + ";";
|
||
return userCookie;
|
||
}
|
||
|
||
async function step1() {
|
||
try {
|
||
s_token, cookies, guid, lsid, lstoken, okl_token, token = ""
|
||
let timeStamp = (new Date()).getTime()
|
||
let url = 'https://plogin.m.jd.com/cgi-bin/mm/new_login_entrance?lang=chs&appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport'
|
||
const response = await got(url, {
|
||
responseType: 'json',
|
||
headers: {
|
||
'Connection': 'Keep-Alive',
|
||
'Content-Type': 'application/x-www-form-urlencoded',
|
||
'Accept': 'application/json, text/plain, */*',
|
||
'Accept-Language': 'zh-cn',
|
||
'Referer': 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
|
||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0',
|
||
'Host': 'plogin.m.jd.com'
|
||
}
|
||
});
|
||
|
||
praseSetCookies(response)
|
||
} catch (error) {
|
||
cookies = "";
|
||
console.log(error.response.body);
|
||
}
|
||
};
|
||
|
||
async function step2() {
|
||
try {
|
||
if (cookies == "") {
|
||
return 0
|
||
}
|
||
let timeStamp = (new Date()).getTime()
|
||
let url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthreflogurl?s_token=' + s_token + '&v=' + timeStamp + '&remember=true'
|
||
const response = await got.post(url, {
|
||
responseType: 'json',
|
||
json: {
|
||
'lang': 'chs',
|
||
'appid': 300,
|
||
'source': 'wq_passport',
|
||
'returnurl': 'https://wqlogin2.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action'
|
||
},
|
||
headers: {
|
||
'Connection': 'Keep-Alive',
|
||
'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8',
|
||
'Accept': 'application/json, text/plain, */*',
|
||
'Cookie': cookies,
|
||
'Referer': 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
|
||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0',
|
||
'Host': 'plogin.m.jd.com',
|
||
}
|
||
});
|
||
token = response.body.token
|
||
okl_token = response.headers['set-cookie'][0]
|
||
okl_token = okl_token.substring(okl_token.indexOf("=") + 1, okl_token.indexOf(";"))
|
||
var qrUrl = 'https://plogin.m.jd.com/cgi-bin/m/tmauth?appid=300&client_type=m&token=' + token;
|
||
return qrUrl;
|
||
} catch (error) {
|
||
console.log(error.response.body);
|
||
return 0
|
||
}
|
||
}
|
||
|
||
var i = 0;
|
||
|
||
async function checkLogin() {
|
||
try {
|
||
if (cookies == "") {
|
||
return 0
|
||
}
|
||
let timeStamp = (new Date()).getTime()
|
||
let url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=' + token + '&ou_state=0&okl_token=' + okl_token;
|
||
const response = await got.post(url, {
|
||
responseType: 'json',
|
||
form: {
|
||
lang: 'chs',
|
||
appid: 300,
|
||
source: 'wq_passport',
|
||
returnurl: 'https://wqlogin2.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action'
|
||
},
|
||
headers: {
|
||
'Referer': 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=' + timeStamp + '&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
|
||
'Cookie': cookies,
|
||
'Connection': 'Keep-Alive',
|
||
'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8',
|
||
'Accept': 'application/json, text/plain, */*',
|
||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0',
|
||
}
|
||
});
|
||
|
||
return response;
|
||
} catch (error) {
|
||
console.log(error.response.body);
|
||
let res = {}
|
||
res.body = { check_ip: 0, errcode: 222, message: '出错' }
|
||
res.headers = {}
|
||
return res;
|
||
}
|
||
}
|
||
|
||
function TotalBean() {
|
||
return new Promise(async resolve => {
|
||
const options = {
|
||
url: "https://me-api.jd.com/user_new/info/GetJDUserInfoUnion",
|
||
headers: {
|
||
Host: "me-api.jd.com",
|
||
Accept: "*/*",
|
||
Connection: "keep-alive",
|
||
Cookie: cookies,
|
||
'User-Agent': 'jdapp;iPhone;10.0.2;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1',
|
||
"Accept-Language": "zh-cn",
|
||
"Referer": "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&",
|
||
"Accept-Encoding": "gzip, deflate, br"
|
||
}
|
||
}
|
||
$.get(options, (err, resp, data) => {
|
||
try {
|
||
if (err) {
|
||
$.logErr(err)
|
||
} else {
|
||
if (data) {
|
||
data = JSON.parse(data);
|
||
if (data['retcode'] === "1001") {
|
||
$.isLogin = false; //cookie过期
|
||
return;
|
||
}
|
||
if (data['retcode'] === "0" && data.data && data.data.hasOwnProperty("userInfo")) {
|
||
$.nickName = data.data.userInfo.baseInfo.nickname;
|
||
}
|
||
} else {
|
||
$.log('京东服务器返回空数据');
|
||
}
|
||
}
|
||
} catch (e) {
|
||
$.logErr(e)
|
||
} finally {
|
||
resolve();
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
function AutoAddCK(cookie, msg) {
|
||
const content = getFileContentByName(ckFile);
|
||
const lines = content.split('\n');
|
||
const pt_pin = cookie.match(/pt_pin=.+?;/)[0];
|
||
let updateFlag = false;
|
||
let lastIndex = 0;
|
||
let maxCookieCount = 0;
|
||
for (var i = 0; i < lines.length; i++) {
|
||
var line = lines[i];
|
||
if (line.startsWith('Cookie')) {
|
||
maxCookieCount = line.split('=')[0].split('Cookie')[1];
|
||
lastIndex = i;
|
||
if (
|
||
line.match(/pt_pin=.+?;/) &&
|
||
line.match(/pt_pin=.+?;/)[0] == pt_pin
|
||
) {
|
||
const head = line.split('=')[0];
|
||
const newLine = [head, '=', '"', cookie, '"', ' #', msg].join('');
|
||
lines[i] = newLine;
|
||
updateFlag = true;
|
||
}
|
||
}
|
||
}
|
||
if (!updateFlag) {
|
||
const newLine = [
|
||
'Cookie',
|
||
Number(maxCookieCount) + 1,
|
||
'=',
|
||
'"',
|
||
cookie,
|
||
'"',
|
||
' #',
|
||
msg,
|
||
].join('');
|
||
lines.splice(lastIndex + 1, 0, newLine);
|
||
}
|
||
saveNewConf('cookie.sh', lines.join('\n'));
|
||
}
|
||
|
||
/**
|
||
* hash方法
|
||
*
|
||
* @param {String} e.g.: 'md5', 'sha1'
|
||
* @param {String|Buffer} s
|
||
* @param {String} [format] 'hex','base64'. default is 'hex'.
|
||
* @return {String} 编码值
|
||
* @private
|
||
*/
|
||
const hash = (method, s, format) => {
|
||
var sum = crypto.createHash(method);
|
||
var isBuffer = Buffer.isBuffer(s);
|
||
if (!isBuffer && typeof s === 'object') {
|
||
s = JSON.stringify(sortObject(s));
|
||
}
|
||
sum.update(s, isBuffer ? 'binary' : 'utf8');
|
||
return sum.digest(format || 'hex');
|
||
};
|
||
|
||
/**
|
||
- md5 编码
|
||
- 3. @param {String|Buffer} s
|
||
- @param {String} [format] 'hex','base64'. default is 'hex'.
|
||
- @return {String} md5 hash string
|
||
- @public
|
||
*/
|
||
const md5 = (s, format) => {
|
||
return hash('md5', s, format);
|
||
};
|
||
|
||
function CountUser() {
|
||
const content = getFileContentByName(ckFile);
|
||
const lines = content.split('\n');
|
||
let maxCookieCount = 0;
|
||
let UserCount;
|
||
for (var i = 0; i < lines.length; i++) {
|
||
var line = lines[i];
|
||
if (line.startsWith('Cookie')) {
|
||
maxCookieCount = line.split('=')[0].split('Cookie')[1];
|
||
UserCount = Number(maxCookieCount);
|
||
}
|
||
}
|
||
return UserCount;
|
||
}
|
||
/**
|
||
* @getClientIP
|
||
* @desc 获取用户 ip 地址
|
||
* @param {Object} req - 请求
|
||
*/
|
||
function getClientIP(req) {
|
||
return req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || req.connection.socket.remoteAddress;
|
||
};
|
||
|
||
/**
|
||
* 检查 config.sh 以及 config.sh.sample 文件是否存在
|
||
*/
|
||
function checkConfigFile() {
|
||
if (!fs.existsSync(ckFile)) {
|
||
console.error('脚本启动失败,cookie.sh 文件不存在!');
|
||
process.exit(1);
|
||
}
|
||
if (!fs.existsSync(sampleFile)) {
|
||
console.error('脚本启动失败,config.sh.sample 文件不存在!');
|
||
process.exit(1);
|
||
}
|
||
if (!fs.existsSync(autoConfigFile)) {
|
||
console.error('脚本启动失败,此面板只适用于JSTOOL!');
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查 config/bak/ 备份目录是否存在,不存在则创建
|
||
*/
|
||
function mkdirConfigBakDir() {
|
||
if (!fs.existsSync(confBakDir)) {
|
||
fs.mkdirSync(confBakDir);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 备份 config.sh 文件
|
||
*/
|
||
function bakConfFile(file) {
|
||
mkdirConfigBakDir();
|
||
let date = new Date();
|
||
let bakConfFile = confBakDir + file + '_' + date.getFullYear() + '-' + date.getMonth() + '-' + date.getDay() + '-' + date.getHours() + '-' + date.getMinutes() + '-' + date.getMilliseconds();
|
||
let oldConfContent = "";
|
||
switch (file) {
|
||
case "cookie.sh":
|
||
oldConfContent = getFileContentByName(ckFile);
|
||
fs.writeFileSync(bakConfFile, oldConfContent);
|
||
break;
|
||
case "config.sh":
|
||
oldConfContent = getFileContentByName(confFile);
|
||
fs.writeFileSync(bakConfFile, oldConfContent);
|
||
break;
|
||
case "crontab.list":
|
||
oldConfContent = getFileContentByName(crontabFile);
|
||
fs.writeFileSync(bakConfFile, oldConfContent);
|
||
break;
|
||
case "diy.sh":
|
||
oldConfContent = getFileContentByName(diyFile);
|
||
fs.writeFileSync(bakConfFile, oldConfContent);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
/**
|
||
* 将 post 提交内容写入 config.sh 文件(同时备份旧的 config.sh 文件到 bak 目录)
|
||
* @param content
|
||
*/
|
||
function saveNewConf(file, content) {
|
||
bakConfFile(file);
|
||
switch (file) {
|
||
case "cookie.sh":
|
||
fs.writeFileSync(ckFile, content);
|
||
break;
|
||
case "config.sh":
|
||
fs.writeFileSync(confFile, content);
|
||
break;
|
||
case "crontab.list":
|
||
fs.writeFileSync(crontabFile, content);
|
||
execSync('crontab ' + crontabFile);
|
||
break;
|
||
case "diy.sh":
|
||
fs.writeFileSync(diyFile, content);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取文件内容
|
||
* @param fileName 文件路径
|
||
* @returns {string}
|
||
*/
|
||
function getFileContentByName(fileName) {
|
||
if (fs.existsSync(fileName)) {
|
||
return fs.readFileSync(fileName, 'utf8');
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* 获取目录中最后修改的文件的路径
|
||
* @param dir 目录路径
|
||
* @returns {string} 最新文件路径
|
||
*/
|
||
function getLastModifyFilePath(dir) {
|
||
var filePath = '';
|
||
|
||
if (fs.existsSync(dir)) {
|
||
var lastmtime = 0;
|
||
|
||
var arr = fs.readdirSync(dir);
|
||
|
||
arr.forEach(function (item) {
|
||
var fullpath = path.join(dir, item);
|
||
var stats = fs.statSync(fullpath);
|
||
if (stats.isFile()) {
|
||
if (stats.mtimeMs >= lastmtime) {
|
||
filePath = fullpath;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
return filePath;
|
||
}
|
||
|
||
|
||
var app = express();
|
||
// gzip压缩
|
||
app.use(compression({ level: 6, filter: shouldCompress }));
|
||
|
||
function shouldCompress(req, res) {
|
||
if (req.headers['x-no-compression']) {
|
||
// don't compress responses with this request header
|
||
return false;
|
||
}
|
||
|
||
// fallback to standard filter function
|
||
return compression.filter(req, res);
|
||
}
|
||
|
||
app.use(session({
|
||
secret: 'secret',
|
||
name: `connect.${Math.random()}`,
|
||
resave: true,
|
||
saveUninitialized: true
|
||
}));
|
||
app.use(bodyParser.json({ limit: '50mb' }));
|
||
app.use(bodyParser.urlencoded({ limit: '50mb', extended: true }));
|
||
app.use(express.static(path.join(__dirname, 'public')));
|
||
|
||
|
||
/**
|
||
* 首页
|
||
*/
|
||
app.get('/', function (request, response) {
|
||
let OldIPContent = getFileContentByName(logPath + 'panel.txt');
|
||
let date = new Date();
|
||
let bakConfFile = '时间为:' + date.getFullYear() + '-' + date.getMonth() + '-' + date.getDay() + '-' + date.getHours() + '-' + date.getMinutes() + '-' + date.getMilliseconds();
|
||
OldIPContent = OldIPContent + '\n' + '访问您【首页】的IP为' + getClientIP(request) + bakConfFile + '\n';
|
||
fs.writeFileSync(logPath + 'panel.txt', OldIPContent);
|
||
if (request.session.loggedin) {
|
||
response.redirect('./usrconfig');
|
||
} else {
|
||
response.sendFile(path.join(__dirname + '/public/index1.html'));
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 登录页面
|
||
*/
|
||
app.get('/login', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.redirect('./usrconfig');
|
||
} else {
|
||
response.sendFile(path.join(__dirname + '/public/login.html'));
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 用户名密码
|
||
*/
|
||
app.get('/changepwd', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/pwd.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
});
|
||
|
||
/**
|
||
* terminal
|
||
*/
|
||
app.get('/terminal', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/terminal.html'));
|
||
} else {
|
||
response.redirect('/');
|
||
}
|
||
});
|
||
|
||
|
||
/**
|
||
* 获取二维码链接
|
||
*/
|
||
|
||
app.get('/qrcode', function (request, response) {
|
||
(async () => {
|
||
try {
|
||
await step1();
|
||
const qrurl = await step2();
|
||
if (qrurl != 0) {
|
||
response.send({ err: 0, qrcode: qrurl });
|
||
} else {
|
||
response.send({ err: 1, msg: "错误" });
|
||
}
|
||
} catch (err) {
|
||
response.send({ err: 1, msg: err });
|
||
}
|
||
})();
|
||
})
|
||
|
||
/**
|
||
* 发送用户数
|
||
*/
|
||
|
||
app.get('/GetUserCount', function (request, response) {
|
||
let SendNum = '当前有' + CountUser() + '名用户';
|
||
response.send({ err: 0, msg: SendNum });
|
||
})
|
||
|
||
/**
|
||
* 获取返回的cookie信息
|
||
*/
|
||
|
||
app.get('/cookie', function (request, response) {
|
||
if (request.session.loggedin && cookies != "") {
|
||
(async () => {
|
||
try {
|
||
const cookie = await checkLogin();
|
||
if (cookie.body.errcode == 0) {
|
||
let ucookie = getCookie(cookie);
|
||
response.send({ err: 0, cookie: ucookie });
|
||
} else {
|
||
response.send({ err: cookie.body.errcode, msg: cookie.body.message });
|
||
}
|
||
} catch (err) {
|
||
response.send({ err: 1, msg: err });
|
||
}
|
||
})();
|
||
} else {
|
||
response.send({ err: 1, msg: loginFaild });
|
||
}
|
||
})
|
||
|
||
/**
|
||
* 获取返回的cookie信息
|
||
*/
|
||
|
||
app.post('/cookie', function (request, response) {
|
||
(async () => {
|
||
try {
|
||
const cookie = await checkLogin();
|
||
if (cookie.body.errcode == 0) {
|
||
let ucookie = getCookie(cookie);
|
||
let adddata = ucookie;
|
||
AutoAddCK(adddata, request.body.msg);
|
||
response.send({ err: 0, cookie: ucookie });
|
||
} else {
|
||
response.send({ err: cookie.body.errcode, msg: cookie.body.message });
|
||
}
|
||
} catch (err) {
|
||
response.send({ err: 1, msg: err });
|
||
}
|
||
})();
|
||
})
|
||
|
||
/**
|
||
* 获取各种配置文件api
|
||
*/
|
||
|
||
app.get('/api/config/:key', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
if (configString.indexOf(request.params.key) > -1) {
|
||
switch (request.params.key) {
|
||
case 'config':
|
||
content = getFileContentByName(confFile);
|
||
break;
|
||
case 'usrconfig':
|
||
content = getFileContentByName(ckFile);
|
||
break;
|
||
case 'sample':
|
||
content = getFileContentByName(sampleFile);
|
||
break;
|
||
case 'crontab':
|
||
content = getFileContentByName(crontabFile);
|
||
break;
|
||
case 'shareCode':
|
||
let shareCodeFile = getLastModifyFilePath(shareCodeDir);
|
||
content = getFileContentByName(shareCodeFile);
|
||
break;
|
||
case 'diy':
|
||
content = getFileContentByName(diyFile);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
response.setHeader("Content-Type", "text/plain");
|
||
response.send(content);
|
||
} else {
|
||
response.send("no config");
|
||
}
|
||
} else {
|
||
response.send(loginFaild);
|
||
}
|
||
})
|
||
|
||
/**
|
||
* 首页
|
||
*/
|
||
app.get('/home', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/home.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 配置页面
|
||
*/
|
||
app.get('/usrconfig', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/usrconfig.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 对比 配置页面
|
||
*/
|
||
app.get('/diff', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/diff.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* Share Code 页面
|
||
*/
|
||
app.get('/shareCode', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/shareCode.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* crontab 配置页面
|
||
*/
|
||
app.get('/crontab', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/crontab.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 自定义脚本 页面
|
||
*/
|
||
app.get('/diy', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/diy.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 手动执行脚本 页面
|
||
*/
|
||
app.get('/run', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/run.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
});
|
||
|
||
app.post('/runCmd', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
const cmd = `cd ${rootPath};` + request.body.cmd;
|
||
const delay = request.body.delay || 0;
|
||
// console.log('before exec');
|
||
// exec maxBuffer 20MB
|
||
exec(cmd, { maxBuffer: 1024 * 1024 * 20 }, (error, stdout, stderr) => {
|
||
// console.log(error, stdout, stderr);
|
||
// 根据传入延时返回数据,有时太快会出问题
|
||
setTimeout(() => {
|
||
if (error) {
|
||
console.error(`执行的错误: ${error}`);
|
||
response.send({ err: 1, msg: stdout ? `${stdout}${error}` : `${error}` });
|
||
return;
|
||
|
||
}
|
||
|
||
if (stdout) {
|
||
// console.log(`stdout: ${stdout}`)
|
||
response.send({ err: 0, msg: `${stdout}` });
|
||
return;
|
||
|
||
}
|
||
|
||
if (stderr) {
|
||
console.error(`stderr: ${stderr}`);
|
||
response.send({ err: 1, msg: `${stderr}` });
|
||
return;
|
||
}
|
||
|
||
response.send({ err: 0, msg: '执行结束,无结果返回。' });
|
||
}, delay);
|
||
});
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 使用jsName获取最新的日志
|
||
*/
|
||
app.get('/runLog/:jsName', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
const jsName = request.params.jsName;
|
||
let shareCodeFile = getLastModifyFilePath(path.join(rootPath, `log/${jsName}/`));
|
||
if (jsName === 'rm_log') {
|
||
shareCodeFile = path.join(rootPath, `log/${jsName}.log`)
|
||
}
|
||
|
||
if (shareCodeFile) {
|
||
const content = getFileContentByName(shareCodeFile);
|
||
response.setHeader("Content-Type", "text/plain");
|
||
response.send(content);
|
||
} else {
|
||
response.send("no logs");
|
||
}
|
||
} else {
|
||
response.send(loginFaild);
|
||
}
|
||
})
|
||
|
||
/**
|
||
* login
|
||
*/
|
||
app.post('/login', function (request, response) {
|
||
let username = md5(request.body.username);
|
||
let password = md5(request.body.password);
|
||
let OldIPContent = getFileContentByName(logPath + 'panel.txt');
|
||
let UserTicket;
|
||
if (ErrorTimes > 30) {
|
||
response.send({ err: 1, msg: "面板检测到有暴力破解的行为,已关闭登入系统" });
|
||
}
|
||
fs.readFile(authConfigFile, 'utf8', function (err, data) {
|
||
if (err) console.log(err);
|
||
var con = JSON.parse(data);
|
||
if (con.entry !== '1') {
|
||
let AuthData = {
|
||
UserTicket: md5(con.user) + md5(con.password),
|
||
entry: '1'
|
||
}
|
||
UserTicket = md5(con.user) + md5(con.password);
|
||
fs.writeFileSync(authConfigFile, JSON.stringify(AuthData));
|
||
}
|
||
if (username && password) {
|
||
let GetTicket = username + password;
|
||
if (GetTicket == con.UserTicket) {
|
||
ErrorTimes = 0;
|
||
request.session.loggedin = true;
|
||
request.session.UserTicket = GetTicket;
|
||
response.send({ err: 0 });
|
||
}
|
||
else if (GetTicket == UserTicket) {
|
||
ErrorTimes = 0;
|
||
request.session.loggedin = true;
|
||
request.session.UserTicket = GetTicket;
|
||
response.send({ err: 0 });
|
||
}
|
||
else {
|
||
response.send({ err: 1, msg: authError });
|
||
//setTimeout(function() { callback(null); }, 8000);
|
||
ErrorTimes = ErrorTimes + 1;
|
||
let date = new Date();
|
||
let bakConfFile = '时间为:' + date.getFullYear() + '-' + date.getMonth() + '-' + date.getDay() + '-' + date.getHours() + '-' + date.getMinutes() + '-' + date.getMilliseconds();
|
||
OldIPContent = OldIPContent + '\n' + '【输入密码错误】,访问IP为' + getClientIP(request) + bakConfFile + '\n';
|
||
if (ErrorTimes > 29) {
|
||
OldIPContent = OldIPContent + '面板检测到有暴力破解的行为,已关闭登入系统' + '\n';
|
||
}
|
||
fs.writeFileSync(logPath + 'panel.txt', OldIPContent);
|
||
}
|
||
} else {
|
||
response.send({ err: 1, msg: "请输入用户名密码!" });
|
||
}
|
||
});
|
||
|
||
});
|
||
|
||
/**
|
||
* change pwd
|
||
*/
|
||
app.post('/changepass', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
let username = request.body.username;
|
||
let password = request.body.password;
|
||
let config = {
|
||
user: username,
|
||
password: password
|
||
}
|
||
if (username && password) {
|
||
fs.writeFile(authConfigFile, JSON.stringify(config), function (err) {
|
||
if (err) {
|
||
response.send({ err: 1, msg: "写入错误请重试!" });
|
||
} else {
|
||
response.send({ err: 0, msg: "更新成功!" });
|
||
}
|
||
});
|
||
} else {
|
||
response.send({ err: 1, msg: "请输入用户名密码!" });
|
||
}
|
||
|
||
} else {
|
||
response.send(loginFaild);
|
||
|
||
}
|
||
});
|
||
|
||
/**
|
||
* change pwd
|
||
*/
|
||
app.get('/logout', function (request, response) {
|
||
request.session.destroy()
|
||
response.redirect('/login');
|
||
|
||
});
|
||
|
||
|
||
/**
|
||
* save config
|
||
*/
|
||
|
||
app.post('/api/save', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
let postContent = request.body.content;
|
||
let postfile = request.body.name;
|
||
saveNewConf(postfile, postContent);
|
||
response.send({ err: 0, title: "保存成功! ", msg: "将自动刷新页面查看修改后的 " + postfile + " 文件" });
|
||
} else {
|
||
response.send({ err: 1, title: "保存失败! ", msg: loginFaild });
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 日志查询 页面
|
||
*/
|
||
app.get('/log', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/tasklog.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 日志列表
|
||
*/
|
||
app.get('/api/logs', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
var fileList = fs.readdirSync(logPath, 'utf-8');
|
||
var dirs = [];
|
||
var rootFiles = [];
|
||
for (var i = 0; i < fileList.length; i++) {
|
||
var stat = fs.lstatSync(logPath + fileList[i]);
|
||
// 是目录,需要继续
|
||
if (stat.isDirectory()) {
|
||
var fileListTmp = fs.readdirSync(logPath + '/' + fileList[i], 'utf-8');
|
||
fileListTmp.reverse();
|
||
var dirMap = {
|
||
dirName: fileList[i],
|
||
files: fileListTmp
|
||
}
|
||
dirs.push(dirMap);
|
||
} else {
|
||
rootFiles.push(fileList[i]);
|
||
}
|
||
}
|
||
|
||
dirs.push({
|
||
dirName: '@',
|
||
files: rootFiles
|
||
});
|
||
var result = { dirs };
|
||
response.send(result);
|
||
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 日志文件
|
||
*/
|
||
app.get('/api/logs/:dir/:file', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
let filePath;
|
||
if (request.params.dir === '@') {
|
||
filePath = logPath + request.params.file;
|
||
} else {
|
||
filePath = logPath + request.params.dir + '/' + request.params.file;
|
||
}
|
||
var content = getFileContentByName(filePath);
|
||
response.setHeader("Content-Type", "text/plain");
|
||
response.send(content);
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
|
||
/**
|
||
* 查看脚本 页面
|
||
*/
|
||
app.get('/viewScripts', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
response.sendFile(path.join(__dirname + '/public/viewScripts.html'));
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
});
|
||
|
||
/**
|
||
* 脚本列表
|
||
*/
|
||
app.get('/api/scripts', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
var fileList = fs.readdirSync(ScriptsPath, 'utf-8');
|
||
var dirs = [];
|
||
var rootFiles = [];
|
||
var excludeRegExp = /(git)|(node_modules)|(icon)/;
|
||
for (var i = 0; i < fileList.length; i++) {
|
||
var stat = fs.lstatSync(ScriptsPath + fileList[i]);
|
||
// 是目录,需要继续
|
||
if (stat.isDirectory()) {
|
||
var fileListTmp = fs.readdirSync(ScriptsPath + '/' + fileList[i], 'utf-8');
|
||
fileListTmp.reverse();
|
||
|
||
if (excludeRegExp.test(fileList[i])) {
|
||
continue;
|
||
}
|
||
|
||
var dirMap = {
|
||
dirName: fileList[i],
|
||
files: fileListTmp
|
||
}
|
||
dirs.push(dirMap);
|
||
} else {
|
||
if (excludeRegExp.test(fileList[i])) {
|
||
continue;
|
||
}
|
||
|
||
rootFiles.push(fileList[i]);
|
||
}
|
||
}
|
||
|
||
dirs.push({
|
||
dirName: '@',
|
||
files: rootFiles
|
||
});
|
||
var result = { dirs };
|
||
response.send(result);
|
||
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
/**
|
||
* 脚本文件
|
||
*/
|
||
app.get('/api/scripts/:dir/:file', function (request, response) {
|
||
if (request.session.loggedin) {
|
||
let filePath;
|
||
if (request.params.dir === '@') {
|
||
filePath = ScriptsPath + request.params.file;
|
||
} else {
|
||
filePath = ScriptsPath + request.params.dir + '/' + request.params.file;
|
||
}
|
||
var content = getFileContentByName(filePath);
|
||
response.setHeader("Content-Type", "text/plain");
|
||
response.send(content);
|
||
} else {
|
||
response.redirect('/login');
|
||
}
|
||
|
||
});
|
||
|
||
checkConfigFile();
|
||
|
||
// ttyd proxy
|
||
app.use('/RandomShellEntry', createProxyMiddleware({
|
||
target: 'http://localhost:9999',
|
||
ws: true,
|
||
changeOrigin: true,
|
||
pathRewrite: {
|
||
'^/RandomShellEntry': '/',
|
||
},
|
||
}));
|
||
|
||
app.listen(5678, () => {
|
||
console.log('应用正在监听 5678 端口!');
|
||
});
|