You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
813 lines
22 KiB
813 lines
22 KiB
const mysql = require('mysql')
|
|
const Spawner = require('child_process');
|
|
const crypto = require('crypto');
|
|
const request = require('request');
|
|
const cheerio = require('cheerio');
|
|
|
|
|
|
class Child
|
|
{
|
|
/**
|
|
*
|
|
* @param {String} userID -User's Hash
|
|
*/
|
|
constructor(userID)
|
|
{
|
|
this.ID = userID;
|
|
this.child = Spawner.fork('./worker.js',[this.ID]);
|
|
this.birth = process.uptime();
|
|
this.timeOut = setTimeout(() => {
|
|
this.child.kill('SIGINT');
|
|
},2*60*60*1000);
|
|
}
|
|
get EOL()
|
|
{
|
|
const EOL = Math.trunc((this.timeOut._idleTimeout - ((process.uptime()*1000)-this.birth))/1000);
|
|
return EOL>0?EOL:0;
|
|
}
|
|
getMapData()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.child.send('MapData');
|
|
this.child.on('message', m=>
|
|
{
|
|
if(typeof m == Object)
|
|
{
|
|
resolve(m.name);
|
|
}
|
|
})
|
|
})
|
|
}
|
|
waitStart()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
var status = setInterval(() => {
|
|
if(this.isOpen)
|
|
{
|
|
clearInterval(status);
|
|
resolve(true)
|
|
}
|
|
}, 100);
|
|
})
|
|
}
|
|
createMapImage()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.child.send('MapImage')
|
|
this.child.on('message', m=>
|
|
{
|
|
if(typeof m == String && m === 'Done')
|
|
{
|
|
resolve(m);
|
|
}
|
|
})
|
|
})
|
|
}
|
|
getConsole()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.child.send('Console')
|
|
this.child.on('message', m=>
|
|
{
|
|
resolve(m);
|
|
})
|
|
})
|
|
}
|
|
|
|
}module.exports.Child = Child;
|
|
|
|
|
|
class playerCache
|
|
{
|
|
/**
|
|
*
|
|
* @param {String} Name
|
|
* @param {String} SteamID
|
|
* @param {Number} Ping
|
|
* @param {String} Address IP
|
|
* @param {Number} ConnectedSeconds
|
|
* @param {Number} Health
|
|
* @param {Object} Teammates ??'Not in a team'
|
|
* @param {String} Position ??'Not spawned yet'
|
|
*/
|
|
constructor(Name, SteamID, Ping, Address,ConnectedSeconds, Health, Teammates, Position)
|
|
{
|
|
this.Displayname = Name;
|
|
this.SteamID = SteamID;
|
|
this.Address = Address;
|
|
this.Health = Health;
|
|
this.Teammates = Teammates??'NOT IN A TEAM';
|
|
this.Position = Position??'NOT SPAWNED YET';
|
|
this.Ping = Ping;
|
|
this.ConnectedSeconds = ConnectedSeconds;
|
|
}
|
|
|
|
|
|
|
|
|
|
}module.exports.playerCache = playerCache;
|
|
|
|
|
|
class ServerCache
|
|
{
|
|
constructor(ID,Hostname,MaxPlayers, GameTime, Framerate, NetworkIn, NetworkOut, Seed, WorldSize)
|
|
{
|
|
this.ID = ID;
|
|
this.Hostname=Hostname;
|
|
this.MaxPlayers =MaxPlayers;
|
|
this.GameTime = GameTime;
|
|
this.Framerate = Framerate;
|
|
this.NetworkIn = NetworkIn;
|
|
this.NetworkOut = NetworkOut;
|
|
this.Seed = Seed;
|
|
this.WorldSize = WorldSize;
|
|
this.Console = [];
|
|
}
|
|
|
|
get WorldData ()
|
|
{
|
|
return {
|
|
Seed:this.Seed,
|
|
Size:this.WorldSize,
|
|
Time:this.GameTime
|
|
}
|
|
}
|
|
get NetWorkData ()
|
|
{
|
|
return {
|
|
Framerate:this.Framerate,
|
|
In:this.NetworkIn,
|
|
Out:this.NetworkIn
|
|
}
|
|
}
|
|
get ConsoleData ()
|
|
{
|
|
return this.Console;
|
|
}
|
|
get BasicData ()
|
|
{
|
|
return {
|
|
HostName:this.Hostname,
|
|
MaxPlayers:this.MaxPlayers,
|
|
GameTime:this.GameTime
|
|
}
|
|
}
|
|
}module.exports.ServerCache = ServerCache;
|
|
|
|
|
|
class pChild
|
|
{
|
|
|
|
constructor(ip, port, pw)
|
|
{
|
|
this.ip = ip;
|
|
this.port = port;
|
|
this.pw = pw;
|
|
this.child = Spawner.fork('./pWorker.js');
|
|
}
|
|
/**
|
|
* @argument {*} - Anything
|
|
*/
|
|
sendData()
|
|
{
|
|
for (var i = 0; i < arguments.length; i++)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* To be used with programmed commands
|
|
* @param {String} command - Command to be sent
|
|
*/
|
|
send(command)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.child.send({'command':command, 'ip':this.ip, 'port':this.port, 'pw':this.pw});
|
|
this.child.on('message', (m)=>
|
|
{
|
|
if(typeof m=='string')
|
|
{
|
|
if(m ==='end')
|
|
{
|
|
resolve();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reject("Worker didn't respond to querry.")
|
|
}
|
|
})
|
|
})
|
|
}
|
|
close ()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
resolve(this.child.disconnect());
|
|
})
|
|
}
|
|
|
|
}module.exports.pChild = pChild;
|
|
class rustChild
|
|
{
|
|
constructor(size, seed)
|
|
{
|
|
this.child = Spawner.exec(`cmd /c updateServer.bat ${size} ${seed}`)
|
|
}
|
|
}module.exports.rustChild = rustChild;
|
|
|
|
|
|
class DBConnection
|
|
{
|
|
constructor()
|
|
{
|
|
this.connection = mysql.createConnection(
|
|
{
|
|
host:'localhost',
|
|
user:'root',
|
|
password:'root',
|
|
database:'legendary'
|
|
})
|
|
this.connection.connect();
|
|
|
|
}
|
|
close()
|
|
{
|
|
setTimeout(() =>
|
|
{
|
|
this.connection.destroy();
|
|
}, 2000);
|
|
}
|
|
//User
|
|
get Users()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.connection.query('Select * from administrator', (e, r, f)=>
|
|
{
|
|
if(!e)
|
|
{
|
|
let aux = JSON.parse(JSON.stringify(r))
|
|
var payload =[];
|
|
|
|
for( var i = 0; i<aux.length; i++)
|
|
{
|
|
payload.push(aux[i].Hash)
|
|
}
|
|
resolve(payload);
|
|
this.close();
|
|
}
|
|
else
|
|
{
|
|
reject(e)
|
|
this.close();
|
|
}
|
|
});
|
|
})
|
|
}
|
|
hasSVData(Hash)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.UData(Hash).then(
|
|
m=>
|
|
{
|
|
|
|
if(m.Server=='No server')
|
|
{
|
|
reject(false)
|
|
}
|
|
else
|
|
{
|
|
resolve(true)
|
|
}
|
|
}
|
|
)
|
|
})
|
|
}
|
|
UData(HASH)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.connection.query(`SELECT * FROM administrator WHERE Hash = '${HASH}' `, (e, r, f)=>
|
|
{
|
|
if(e)reject(e);
|
|
r = JSON.parse(JSON.stringify(r))[0];
|
|
resolve({
|
|
id:r.A_ID,
|
|
Hash:r.Hash,
|
|
Email:r.EHash,
|
|
Server:r.IP || 'No server',
|
|
Port: JSON.stringify(r.Port) || 'No server',
|
|
SPW:r.sv_pw,
|
|
Epoch:r.Epoch
|
|
})
|
|
this.close();
|
|
})
|
|
})
|
|
}
|
|
|
|
get_ID(hash)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
|
|
//User
|
|
this.Users.then((x)=>
|
|
{
|
|
for(var i =0; i<x.length; i++)
|
|
{
|
|
if(x[i]==hash)
|
|
{
|
|
|
|
this.UData(hash).then((m)=>
|
|
{
|
|
resolve(m.id);
|
|
})
|
|
.catch(()=>reject('no ID for this hash'))
|
|
}
|
|
}
|
|
}).catch(m=>
|
|
{
|
|
console.log(m);
|
|
reject('no ID for this HASH');
|
|
});
|
|
})
|
|
}
|
|
|
|
getCommands(Hash)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.get_ID(Hash).then(id=>
|
|
{
|
|
this.connection.query(`Select * from legendary.timed_com where administrator_A_ID = '${id}'`, (e, r, f)=>
|
|
{
|
|
if(e)reject(e);
|
|
resolve(JSON.parse(JSON.stringify(r)));
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
addCommand(Hash, Command, Loop, Send, tz)
|
|
{
|
|
this.get_ID(Hash).then(id=>
|
|
{
|
|
|
|
this.connection.query(`INSERT INTO legendary.timed_com (\`Command\`, \`Loop\`, \`Send\`, \`administrator_A_ID\`) VALUES ('${Command}', '${Loop}', '${Send}', '${id}')`);
|
|
this.close();
|
|
})
|
|
}
|
|
|
|
removeCommand(id)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.connection.query(`DELETE FROM legendary.timed_com WHERE (T_ID = ${id});`, (e, r, f)=>
|
|
{
|
|
if(e)reject(e)
|
|
if(r.affectedRows>0)resolve()
|
|
})
|
|
this.close()
|
|
})
|
|
|
|
}
|
|
|
|
editCommand(id, Command, Loop, Send, tz)
|
|
{
|
|
this.connection.query(`UPDATE legendary.timed_com SET \`Command\` = '${Command}', \`Loop\` = '${Loop}',\`Send\` = '${Send}' WHERE (T_ID = '${id}')`)
|
|
this.close()
|
|
}
|
|
|
|
addUser(Hash, EHash, Epoch)
|
|
{
|
|
if(Hash||EHash||Epoch)
|
|
{
|
|
this.connection.query(`INSERT INTO legendary.administrator (Hash, EHash, Epoch) VALUES ('${Hash}', '${EHash}', '${Epoch}')`)
|
|
this.close()
|
|
}
|
|
}
|
|
|
|
updateUser(HASH, NewHASH)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.get_ID(HASH).then((m)=>
|
|
{
|
|
this.connection.query(`UPDATE administrator SET Hash='${NewHASH}' WHERE A_ID = ${m}`);
|
|
this.close();
|
|
resolve(NewHASH);
|
|
}).catch((err)=>reject(err));
|
|
})
|
|
}
|
|
|
|
addServer(HASH, IP, PW, PORT)
|
|
{
|
|
//needs to know what user should it be connected to
|
|
this.connection.query(`INSERT INTO adminsitrator (ServerIP, ServerPW, ServerPort) VALUES ('${HASH}', '${IP}','${PW}', '${PORT}')`)
|
|
this.close();
|
|
}
|
|
|
|
updateServer(Hash, IP, PW, PORT)
|
|
{
|
|
this.get_ID(Hash).then((id)=>
|
|
{
|
|
this.connection.query(`UPDATE administrator SET IP = '${IP}', sv_pw = '${PW}', port='${PORT}' WHERE A_ID = ${id}`);
|
|
this.close();
|
|
}).catch(e=>console.log('error',e))
|
|
}
|
|
get_Players(Hash)
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.connection.query(`SELECT * FROM player INNER JOIN time ON player.p_id = time.player_p_id
|
|
where administrator_a_id = (SELECT A_ID FROM administrator WHERE Hash = '${Hash}')
|
|
order by player_p_id asc;`,(e,r,f)=>
|
|
{
|
|
if(e)reject(e);this.close;
|
|
try
|
|
{
|
|
// console.log('Classes: DBConnection: Get_Players: r: ', r);
|
|
r = JSON.parse(JSON.stringify(r));
|
|
resolve(r)
|
|
|
|
} catch (err)
|
|
{
|
|
reject(err)
|
|
}
|
|
this.close;
|
|
})
|
|
})
|
|
}
|
|
}module.exports.DBConnection = DBConnection;
|
|
|
|
class _Crypto
|
|
{
|
|
constructor(User, Password)
|
|
{
|
|
this.salt = 'H$44Q3RVCd9X8Ef63tB4';
|
|
this.secret = 'mYFUZX9NSx7K74r7Jh@O';
|
|
this.pepper = String.fromCharCode(this.getRandomInt(65, 90));
|
|
this.password = Password;
|
|
this.user = User;
|
|
this.algorithm = 'aes-192-cbc';
|
|
|
|
}
|
|
get Hash() // to use on register
|
|
{
|
|
return this.hash()
|
|
}
|
|
hash(p)
|
|
{
|
|
if(!p)
|
|
{
|
|
return crypto.createHmac('sha256', this.secret).update(this.user+this.password+this.salt+this.pepper).digest('hex');
|
|
}
|
|
else
|
|
{
|
|
return crypto.createHmac('sha256', this.secret).update(this.user+this.password+this.salt+p).digest('hex');
|
|
}
|
|
}
|
|
eHash(Email)
|
|
{
|
|
return new Buffer.from(Email).toString('base64');
|
|
}
|
|
|
|
decrypt(eHash)
|
|
{
|
|
return new Buffer.from(eHash, 'base64').toString('utf8');
|
|
}
|
|
getRandomInt(min, max)
|
|
{
|
|
min = Math.ceil(min);
|
|
max = Math.floor(max);
|
|
return Math.floor(Math.random() * (max - min)) + min;
|
|
}
|
|
compare() // to use on login
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
new DBConnection().Users
|
|
.then((Users)=>
|
|
{
|
|
for(var i=0; i<26;i++)
|
|
{
|
|
const nPepper = String.fromCharCode(65+i);
|
|
const hash = this.hash(nPepper);
|
|
for(var j = 0; j<Users.length; j++)
|
|
{
|
|
if(Users[j]==hash) resolve(hash);
|
|
}
|
|
}
|
|
reject(false);
|
|
})
|
|
.catch((m)=>
|
|
{
|
|
console.log('error'+m);
|
|
})
|
|
|
|
});
|
|
}
|
|
}module.exports._Crypto = _Crypto;
|
|
|
|
|
|
class Epoch
|
|
{
|
|
/**
|
|
*
|
|
* @param {Number} Days - Must be and integer.
|
|
*/
|
|
constructor(Days)
|
|
{
|
|
this.Days = (Days*(24*60*60));
|
|
this.epoch = this.epocher();
|
|
}
|
|
epocher()
|
|
{
|
|
return Math.floor(this.Days + Date.now()/1000)
|
|
}
|
|
/**
|
|
* @param {String} time - Must follow the format of '18:12'.
|
|
*/
|
|
sEpoch(time)
|
|
{
|
|
let hours = time.split(':')[0];
|
|
let minutes = time.split(':')[1];
|
|
return Math.floor(this.next(hours, minutes)/1000);
|
|
}
|
|
/**
|
|
* @param {Number} time - Must be and integer.
|
|
*/
|
|
toDate(time)
|
|
{
|
|
//console.log('classes:toDate:', time)
|
|
const d = new Date(time*1000);
|
|
return d.getHours()+':'+ d.getMinutes();
|
|
}
|
|
/**
|
|
* Returns the next possible time for the command to be sent. Meaning if the hours inputed by the user
|
|
* have already gone past this day then the epoch will be set for the next.
|
|
* If not the epoch will be created like usual.
|
|
*
|
|
* @param {Number} hours
|
|
* @param {Number} minutes
|
|
*/
|
|
next(hours, minutes)
|
|
{
|
|
var d= new Date();
|
|
var payload = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), hours, minutes, 0, 0).getTime();
|
|
//console.log('Classes:Next:',hours, minutes, payload)
|
|
return payload;
|
|
}
|
|
}module.exports.Epoch = Epoch;
|
|
|
|
class IPTranslator
|
|
{
|
|
constructor(IP)
|
|
{
|
|
this.IP = IP;
|
|
}
|
|
translate()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
request(`http://ip-api.com/json/${this.IP}`, (e,r,b)=>
|
|
{
|
|
var body
|
|
if(!e)
|
|
{
|
|
try {
|
|
body = JSON.parse(b);
|
|
} catch (error) {
|
|
console.log('IP Transalator: Bad Parse.');
|
|
resolve('Err')
|
|
}
|
|
resolve(body);
|
|
}
|
|
else
|
|
{
|
|
resolve( {'status':'error'});
|
|
}
|
|
})
|
|
})
|
|
}
|
|
CC()
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
this.translate().then(m=>resolve(m.countryCode)).catch(e=>
|
|
{
|
|
console.log('IP Translator: CountryCode:'+e);
|
|
reject(e);
|
|
})
|
|
})
|
|
}
|
|
}module.exports.IPTranslator = IPTranslator;
|
|
|
|
class VAC
|
|
{
|
|
constructor(SteamID)
|
|
{
|
|
this.SteamID = SteamID;
|
|
}
|
|
get ban()
|
|
{
|
|
return new Promise((resolve,reject)=>
|
|
{
|
|
request(`http://vacbanned.com/engine/check?qsearch=${this.SteamID}`, (e,r,b)=>
|
|
{
|
|
if(e)reject('VAC: Request:'+e)
|
|
const $ = cheerio.load(b);
|
|
// console.log('Worker: VAC: body: ', $('td').text());
|
|
$('.strong').remove()
|
|
request(`http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=DCA47FAA9F3D1485FA8C1F4FA15A5266&steamid=${this.SteamID}&format=json`, (e,r,steamb)=>
|
|
{
|
|
if(e)reject('VAC: FS: Request:'+e)
|
|
var fs;
|
|
let aux
|
|
//console.log('Vac class: SteamAPI', steamb)
|
|
try
|
|
{
|
|
aux = JSON.parse(steamb)['response'].games;
|
|
} catch (error)
|
|
{
|
|
console.log('JSON parse error: ',error);
|
|
}
|
|
if(aux)
|
|
{
|
|
for (let i = 0; i < aux.length; i++)
|
|
{
|
|
// console.log('VAC: FS: Request2: '+aux[i].appid, '252490');
|
|
if(aux[i].appid)
|
|
{
|
|
if(aux[i].appid=='252490')
|
|
{
|
|
i = aux.length;
|
|
fs = 'NO'
|
|
}
|
|
else
|
|
{
|
|
fs='Yes'
|
|
}
|
|
}
|
|
}
|
|
var vac;
|
|
try {
|
|
vac = $('td').text().replace(/ /g, '').split('Hex)')[1].replace(/\n/g, 'SPLIT').split('SPLIT')[1];
|
|
} catch (error) {
|
|
vac = 'Error';
|
|
}
|
|
let payload = {
|
|
'vac':vac,
|
|
'fs':fs
|
|
}
|
|
|
|
// console.log('VAC: Payload: ', payload)
|
|
resolve(payload);
|
|
}
|
|
else
|
|
{
|
|
var vac;
|
|
try {
|
|
vac = $('td').text().replace(/ /g, '').split('Hex)')[1].replace(/\n/g, 'SPLIT').split('SPLIT')[1];
|
|
} catch (error) {
|
|
vac = 'Error';
|
|
}
|
|
let payload = {
|
|
'vac':vac,
|
|
'fs':fs
|
|
}
|
|
resolve(payload);
|
|
}
|
|
})
|
|
});
|
|
})
|
|
}
|
|
}module.exports.VAC = VAC;
|
|
|
|
|
|
|
|
/**
|
|
* Use it to transform an hour value into miliseconds.
|
|
* @param {Number} Hours - Hours to transform
|
|
*/
|
|
function hours(Hours)
|
|
{
|
|
return Hours*60*60*1000;
|
|
}
|
|
/**
|
|
* This function writes a cookie on the client side.
|
|
* Primary use: Store users Hash for every other page.
|
|
* @argument {Response} res - Response: express response object.
|
|
* @argument {String} name - Name of the cookie.
|
|
* @argument {*} value - Value of the cookie.
|
|
*/
|
|
exports.baker = (res, name, value) =>
|
|
{
|
|
return new Promise((resolve,reject)=>
|
|
{
|
|
try
|
|
{
|
|
res.cookie(name, '',{maxAge:0});
|
|
res.cookie(name, value, {maxAge:hours(2),path:'/',secure:false,httpOnly:false});
|
|
resolve();
|
|
}
|
|
catch (e)
|
|
{
|
|
reject(e)
|
|
}
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Hash used on register to check if there is already a user with the same credentials.
|
|
* @param {String} user - User's email
|
|
* @param {String} password - User's Password
|
|
* @param {String} hash - User's identifying hash
|
|
*/
|
|
exports.bouncer = (user, password, hash) =>
|
|
{
|
|
return new Promise((resolve, reject)=>
|
|
{
|
|
new _Crypto(user, password).compare().then(m=>
|
|
{
|
|
if(hash)
|
|
{
|
|
if(m==hash)
|
|
{
|
|
resolve(m)
|
|
}
|
|
else
|
|
{
|
|
reject('You are on a different account.')
|
|
}
|
|
}
|
|
else
|
|
{
|
|
resolve(m)
|
|
}
|
|
}).catch(m=>
|
|
{
|
|
reject(m)
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Reduces the number of decimal cases to the required value.
|
|
|
|
* @param {Number} num - The number you want to cut to size.
|
|
* @param {Number} decimal - Ammount of decimal cases.
|
|
*/
|
|
exports.toFixed = (num, decimal)=>
|
|
{
|
|
decimal = decimal || 0;
|
|
decimal = Math.pow(10, decimal);
|
|
return Math.floor(num * decimal) / decimal;
|
|
}
|
|
/**
|
|
* Transforms a value into a 0-1 value given the max value it could take.
|
|
* @param {Number} val - Value to transform to percentage
|
|
* @param {Number} max - Maximum the value could be
|
|
*/
|
|
exports.toPercent = (val, max)=>
|
|
{
|
|
return val/max;
|
|
}
|
|
|
|
/**
|
|
* Removes the timezone difference to a time.
|
|
* @param {String} time - Must follow 'HH:MM' format.
|
|
* @param {Number} offSet - Number of minutes from gmt+0.
|
|
*/
|
|
exports.removeTZ = (time, offSet)=>
|
|
{
|
|
var h = parseInt(time.split(':')[0]);
|
|
var maux = parseInt(time.split(':')[1]);
|
|
var m = maux - offSet;
|
|
var d = new Date();
|
|
var payload = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), h, m, 0, 0).toString().split(' ')[4].split(' ')[0].slice(0,-3);
|
|
return payload;
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds timezone difference to a time.
|
|
* @param {String} time - Must follow 'HH:MM' format.
|
|
* @param {Number} offset - Number of minutes from gmt+0.
|
|
*/
|
|
exports.addTZ = (time, offset) =>
|
|
{
|
|
offset = parseInt(offset);
|
|
let h = parseInt(time.split(':')[0]);
|
|
let m = parseInt(time.split(':')[1])+offset;
|
|
var d= new Date();
|
|
return payload = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDay(), h, m, 0, 0).toString().split(' ')[4].split(' ')[0].slice(0,-3);
|
|
} |