Files
2026-01-07 21:21:28 +08:00

297 lines
11 KiB
JavaScript

const http = require('http');
const net = require('net');
const { postLog } = require('./logger.js');
const server_main_addr = 'localhost';
const tcpPort = 50011;
const httpPort = 8766;
let ipAddr_server_main = "";
let ipAddr_service_fileTransfer = "";
let port_server_main = 0;
let port_service_fileTransfer = 0;
let openlist_host = '';
let openlist_host_port = 0;
let openlist_username = '';
let openlist_passwd_hash = '';
let openlist_token = '';
let tcpServ_connected = false;
let appinfo_version = '0.0.0.1';
let appinfo_name = 'globalLinkTransfer Module';
let appinfo_buildType = 'debug';
let appinfo_developer = 'MadobiNanami';
let appinfo_buildDate = '2025-11-18';
postLog.info(`${appinfo_name} Ver.${appinfo_version}.${appinfo_buildType}`);
postLog.info(`Developed by ${appinfo_developer} on ${appinfo_buildDate}`);
postLog.info(`Attempting TCP connect to ${server_main_addr}:${tcpPort}`);
const tcpClient = net.createConnection({ // 创建 TCP 客户端
port: tcpPort,
host: `${server_main_addr}`,
family: 4
}, () => {
postLog.info('Connected to TCP server');
postLog.info('Try to verify connection...');
tcpClient.write('[Dial] Are you really a SoulSim Main Server?'); // 发送验证请求
});
tcpClient.on('data', (data) => { // 监听来自服务器的数据
postLog.debug('Received from TCP server: ' + data.toString(), 1);
if(tcpServ_connected == false){ // 如果尚未验证连接
if(data.toString().includes('Yes, I am SoulSim Main Server.')) { // 验证成功
postLog.info('Connection verified successfully.');
tcpServ_connected = true;
// 发送配置 Openlist 请求
tcpClient.write('[getConfig] <type>openlist</type>');
return;
} else {
postLog.error('Connection verification failed. Closing connection.'); // 验证失败,关闭连接
tcpClient.end();
return;
}
}
let content = JSON.parse(data.toString());
if(content.cmdType=='getOneDriveLink'){ // 处理获取 OneDrive 链接请求
postLog.debug(`Get OneDrive link converte request: ${content.link}`);
processOneDriveLink(`${content.link}`)
.then(link => {
postLog.debug('Processed OneDrive link: ' + link);
tcpClient.write(JSON.stringify({
cmdType: 'oneDriveLinkResult',
link: link
}));
})
.catch(err => {
postLog.error('Error processing OneDrive link: ' + err);
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>error</status> <message>${err}</message>`);
});
}
if(content.cmdType=='configOpenlist'){ // 处理配置 Openlist 请求
openlist_host = content.openlist_host;
openlist_host_port = content.openlist_host_port;
openlist_username = content.openlist_username;
openlist_passwd_hash = content.openlist_passwd_hash;
postLog.info('Configured Openlist with host: ' + openlist_host + ', port: ' + openlist_host_port + ', username: ' + openlist_username+', passwd_hash: '+openlist_passwd_hash);
}
});
tcpClient.on('end', () => { // 监听 TCP 连接关闭事件
postLog.warn('Disconnected from TCP server');
});
tcpClient.on('error', (err) => { // 监听错误事件
postLog.fatal('TCP Client Error: ' + err);
});
const server = http.createServer((req, res) => { // 创建 HTTP 服务器
if (req.method === 'PUT') { // 处理 PUT 请求
let body = '';
req.on('data', chunk => { // 接收数据块
body += chunk.toString();
});
req.on('end', () => { // 数据接收完毕
try {
const data = JSON.parse(body);
postLog.debug('Recev Data: ' + JSON.stringify(data));
if(data.cmdType=='modifyAddr'){
if(data.token!=='mM2aF1aQ5dW3hA1cE5jL6hM4tN9jA0'){ // 简单的令牌验证
res.writeHead(403, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
errorType: '1',
message: 'Invalid token'
}));
return;
}
if(data.serverType=='server.main'&&data.ruleName!=='service_SoulSim-Server'){ // 验证规则名称
res.writeHead(403, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
errorType: '2',
message: 'Invalid rule name'
}));
return;
}
if(data.serverType=='service.fileTransfer'&&data.ruleName!=='service_SoulSim-FileTransfer'){ // 验证规则名称
res.writeHead(403, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
errorType: '3',
message: 'Invalid rule name'
}));
return;
}
if(data.serverType=='server.main'){ // 更新主服务器地址
ipAddr_server_main = data.ipAddr;
port_server_main = data.port;
postLog.info('Updated main server address to ' + data.ipAddr + ':' + data.port);
} else if(data.serverType=='service.fileTransfer'){ // 更新文件传输服务地址
ipAddr_service_fileTransfer = data.ipAddr;
port_service_fileTransfer = data.port;
postLog.info('Updated file transfer server address to ' + data.ipAddr + ':' + data.port);
}
try {
tcpClient.write('[modifyAddr] <ipAddr>' + data.ipAddr + '</ipAddr><port>' + data.port + '</port><addrType>' + data.serverType + '</addrType><ruleName>' + data.ruleName + '</ruleName>'); // 发送地址修改请求
res.writeHead(200, { 'Content-Type': 'application/json' }); // 返回成功响应
res.end(JSON.stringify({
errorType: '0',
message: 'NicePush!'
}));
} catch (tcpErr) { // 处理 TCP 写入错误
postLog.error('Failed to write to TCP server: ' + tcpErr);
res.writeHead(500, { 'Content-Type': 'application/json' }); // 返回错误响应
res.end(JSON.stringify({
errorType: '4',
message: 'Failed to write to TCP server'
}));
}
}
if(data.cmdType=='getAddr'){ // 处理获取地址请求
if(data.addrType=='server.main'){
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
addrType: 'server.main',
ipAddr: ipAddr_server_main,
port: port_server_main
}));
} else if(data.addrType=='service.fileTransfer'){
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
addrType: 'service.fileTransfer',
ipAddr: ipAddr_service_fileTransfer,
port: port_service_fileTransfer
}));
}
}
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid JSON data' }));
}
});
req.on('error', () => {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Internal Server Error' }));
});
} else {
res.writeHead(405, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Method not allowed' }));
}
});
server.listen(httpPort, () => {
postLog.info(`Server is running at http://localhost:${httpPort}`);
});
function processOneDriveLink(filePath) {
return new Promise((resolve, reject) => {
const body = {
username: `${openlist_username}`,
password: `${openlist_passwd_hash}`,
otp_code: ''
};
const bodyString = JSON.stringify(body);
const options = {
hostname: openlist_host,
port: openlist_host_port,
path: '/api/auth/login/hash',
method: 'POST',
headers: {
'Host': openlist_host + ":" + openlist_host_port,
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.9',
'Sec-Ch-Ua-Platform': '"Windows.Server"',
'Sec-Ch-Ua-Mobile': '?0',
'User-Agent': 'SoulSim-Server/1.0',
'Content-Type': 'application/json'
}
};
const req = http.request(options, (res) => {
const chunks = [];
res.on('data', (chunk) => {
chunks.push(chunk);
});
res.on('end', () => {
const data = Buffer.concat(chunks);
let parsed;
try{
parsed = JSON.parse(data);
// postLog.info('Response data: ' + data.toString());
} catch (e){
postLog.error('Failed to convert response to JSON: ' + e);
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>error</status> <message>Failed to convert response to JSON: ${e}</message>`);
postLog.info('Response data: ' + data.toString());
reject(e);
return;
}
openlist_token = parsed.data.token;
postLog.info('Got token: ' + openlist_token);
const options2 = {
hostname: openlist_host,
port: openlist_host_port,
path: '/api/fs/get',
method: 'POST',
headers: {
'Host': openlist_host + ":" + openlist_host_port,
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.9',
'Sec-Ch-Ua-Platform': '"Windows"',
'Sec-Ch-Ua-Mobile': '?0',
'User-Agent': 'SoulSim-Server/1.0',
'Content-Type': 'application/json',
'Authorization': `${openlist_token}`
}
}
const body2 = {
path: `${filePath}`,
password: ''
};
const body2String = JSON.stringify(body2);
const req2 = http.request(options2, (res2) => {
const chunks2 = [];
res2.on('data', (chunk2) => {
chunks2.push(chunk2);
});
res2.on('end', () => {
const data2 = Buffer.concat(chunks2);
try{
const parsed = JSON.parse(data2);
postLog.debug('Response data: ' + data2.toString());
const openlist_getAddr = parsed.data.raw_url;
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>success</status> <link>${openlist_getAddr}</link>`);
// postLog.info(`Get Onedrive Link: ${openlist_getAddr}`);
resolve(openlist_getAddr);
} catch(e) {
postLog.error('Failed to convert response to JSON: ' + e);
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>error</status> <message>Failed to convert response to JSON: ${e}</message>`);
postLog.info('Response data: ' + data2.toString());
reject(e);
}
});
});
req2.on('error',(err) =>{
postLog.error('HTTP request error: ' + err);
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>error</status> <message>${err}</message>`);
reject(err);
});
req2.write(body2String);
req2.end();
});
});
req.on('error', (err) => {
postLog.error('HTTP request error: ' + err);
tcpClient.write(`[userSet] <method>userGetLink</method> <type>onedrive</type> <status>error</status> <message>${err}</message>`);
reject(err);
});
req.write(bodyString);
req.end();
});
}