Skip to content

Instantly share code, notes, and snippets.

@daniel-j
Created February 5, 2013 02:02
Show Gist options
  • Save daniel-j/4711506 to your computer and use it in GitHub Desktop.
Save daniel-j/4711506 to your computer and use it in GitHub Desktop.
SGIP BOT
'use strict';
var net = require('net');
var dgram = require('dgram');
var sqlite3 = require('sqlite3').verbose();
function openDb () {
var db = new sqlite3.Database('bot.sqlite', function (err) {
if (err) {
console.log("Error opening database", err);
}
});
return db;
}
var BOT_NAME = "[sgip]";
var listservers = ['list1.digiex.net', 'list2.digiex.net'];
var connections = {};
var servers = [];
var serverLookup = [];
var database = {};
//db.run("DROP TABLE serverinfo");
//db.run("CREATE TABLE IF NOT EXISTS serverinfo (address TEXT NOT NULL UNIQUE, name TEXT, password TEXT, adminpassword TEXT, blacklistlevel INTEGER)");
console.log('all ok');
refreshDb(function () {
startApiServer();
scanServerlist();
});
function refreshDb (cb) {
function checkCb () {
var currentBlacklisted = [];
for (var i in database) {
if (database[i].blacklistlevel > 0) {
currentBlacklisted.push(i);
}
}
if (--cbcounter === 0) {
console.log("Checking database...");
for (var i in database) {
var address = i;
var serverinfo = database[i];
var index = serverLookup.indexOf(address);
if (currentBlacklisted.indexOf(address) !== -1 && database[i].blacklistlevel === 0) {
console.log("Whitelisted", address);
} else if (currentBlacklisted.indexOf(address) === -1 && database[i].blacklistlevel > 0) {
console.log("Blacklisted", address);
}
if (index !== -1 && database[i].blacklistlevel > 0) {
var server = servers[index];
console.log("Closing connection to", address);
var conn = connections[address];
server.isConnected = false;
conn.udp && conn.udp._handle && conn.udp.close();
conn.client && conn.client._handle && conn.client.destroy();
detachServer(index);
}
}
if (typeof cb === 'function') {cb();}
}
}
console.log("Refreshing database...");
var cbcounter = 0;
cbcounter++;
var db = openDb();
db.all("SELECT * FROM serverinfo", function (err, list) {
for (var i = 0; i < list.length; i++) {
database[list[i].address] = list[i];
}
checkCb();
});
db.close();
};
// Zero fill
function zfs(v) {v=v+'';if(v.length == 1) return "0"+v; return v;};
function Server (config) {
if(!config) config = {};
this.ip = config.ip;
this.port = parseInt(config.port, 10) || 0;
this.address = this.ip+":"+this.port;
this['private'] = !!(config['private'] || false);
this.gametype = parseInt(config.gametype, 10) || 0;
this.version = new Buffer(4);
if(Buffer.isBuffer(config.version)) {
config.version.copy(this.version, 0, 0, 4);
}
else if(typeof config.version === 'string') {
this.version.write(config.version, 0, 4, 'binary');
}
if(!config.capacity) config.capacity = [0, 0];
this.capacity = [+config.capacity[0] || 0, +config.capacity[1] || 0];
this.servername = config.servername || '';
};
Server.prototype.toJSON = function () {
return {
ip: this.ip,
port: this.port,
address: this.address,
'private': this['private'],
gametype: this.gametype,
version: this.version.toString('binary'),
capacity: this.capacity,
servername: this.servername
};
};
function udpchecksum (buf) {
var x = 1, y = 1, size = buf.length;
for(var i = 2; i < size; i+=1) {
x += buf[i];
y += x;
}
buf[0] = x % 251;
buf[1] = y % 251;
return buf;
};
var disconnectMessages = {
1: "Server is full",
2: "Version different",
3: "Server is full",
4: "Error during handshaking",
5: "Feature not supported in shareware",
6: "Error downloading level",
7: "Connection lost",
8: "Winsock error",
9: "Connection timed out",
10:"Server stopped",
11:"Kicked off",
12:"Banned",
17:"Unauthorized file request",
18:"No splitscreeners allowed"
};
var actionSizes = {
0x01: 3,
0x02: 3,
0x03: 3,
0x04: 4,
0x05: 1,
0x06: 2,
0x07: 15,
0x08: 12,
0x09: 1,
0x0A: 3,
0x0B: 4,
0x0C: 4,
0x0D: 1,
0x0E: 10,
0x0F: 2,
0x15: 3,
0x19: 4,
0x1E: 21,
0x1A: 3
}
function attachServer (info) {
var server = {
info: new Server(info),
client: {},
isConnected: false
};
console.log('Add server '+server.info.address+' '+server.info.servername);
var udpPort = 0;
var udpCounter = 0;
function connectFailed () {
//console.log('CONNECT FAILED');
server.isConnected = false;
udp._handle && udp.close();
detachServer(servers.indexOf(server));
};
function udpSend (data) {
data[3] = (udpCounter++) % 256;
data = udpchecksum(data);
udp._handle && udp.send(data, 0, data.length, server.info.port, server.info.ip);
};
function joinServer () {
/*if (server.info.address !== "80.78.216.229:10052") {
connectFailed();
return;
}*/
//connectFailed();
//return;
server.client.socketId = 0;
server.client.playerId = 0;
server.client.levelName = "";
server.client.isPlus = false;
server.client.players = [];
server.client.game = {
gamemode: 0,
maxscore: 0,
customMode: 0,
ctf: {
teams: [
{score: 0, holder: -1},
{score: 0, holder: -1}
]
},
time: {
started: false,
inPregame: false,
inOvertime: false,
timeLeft: 0,
time: 0,
autoCycle: false
},
isIdleserver: false,
};
var game = server.client.game;
server.client.lastTimeUpdate = Date.now();
// TODO: Get password from database
var password = (database[server.info.address] && database[server.info.address].password) || "";
var toSend = udpchecksum(new Buffer("yy"+"\x0A"+String.fromCharCode(password.length)+password));
udp.send(toSend, 0, toSend.length, server.info.port, server.info.ip);
udp.on('message', function (data, rinfo) {
if (connections[rinfo.address+":"+rinfo.port] === conn) {
var packetId = data[2];
if (packetId === 0x02) {
} else if (packetId === 0x07) { // Subpacket/action
var i = 4;
var packets = [];
var ids = [];
while (i < data.length) {
var id = data[i];
//console.log(id);
if (!actionSizes[id] || i+actionSizes[id]+1 > data.length) break;
packets.push(data.slice(i, i+actionSizes[id]+1));
i += actionSizes[id] + 1;
ids.push(id);
}
/*if (Array.prototype.indexOf.call(data.slice(4), 0x0E) > -1) {
console.log("UDP ACTION: ", Array.prototype.indexOf.call(data.slice(4), 0x0E), data.slice(4));
console.log(ids);
}*/
for (var key = 0; key < packets.length; key++) {
var data = packets[key];
//console.log(data);
var subPacketId = data[0];
//console.log(subPacketId);
if (subPacketId === 0x03) { // Object destroyed/despawn
} else if (subPacketId === 0x04) { // Player hit
//sendChat("unknown packet");
} else if (subPacketId === 0x07) { // Bullet
} else if (subPacketId === 0x0E) { // Roast/kill/suicide
//console.log("ROAST");
var i = 1;
var victimId = data[i++];
var victimPoints = data.readUInt32LE(i); i+=4;
var killerId = data[i++];
var killerPoints = data.readUInt32LE(i); i+=4;
var victim = server.client.players[victimId];
var killer = server.client.players[killerId];
if (victim && killer) {
//sendChat(killerPoints+", "+victimPoints);
if (victimId !== killerId) {
killer.points = killerPoints;
victim.points = victimPoints;
//sendChat(killer.name+" roasted "+victim.name);
//sendChat(killer.name+' got '+killer.points+' points');
//sendChat(victim.name+' got '+victim.points+' points');
} else {
killer.points = killerPoints;
//sendChat(killer.name+" ate it");
//sendChat(killer.name+' got '+killer.points+' points');
}
} else {
//sendChat("Unknown killer/victim player.", killerId, victimId);
}
} else if (subPacketId === 0x0F) { // Streetfightad
var victimId = data[1];
var killerId = data[2];
var victim = server.client.players[victimId];
var killer = server.client.players[killerId];
if (victim && killer) {
//sendChat(killer.name+" streetfighted "+victim.name);
}
} else if (subPacketId === 0x15) {
} else if (subPacketId === 0x1E) {
//console.log(data);
var bluescore = data[5];
var redscore = data[10];
var blueHolder = data[20] > 0 ? data[21] : -1;
var redHolder = data[17] > 0 ? data[18] : -1;
game.ctf.teams[0].score = bluescore;
game.ctf.teams[1].score = redscore;
game.ctf.teams[0].holder = blueHolder;
game.ctf.teams[1].holder = redHolder;
//console.log('score: ', bluescore, redscore, 'holder: ', blueHolder, redHolder);
} else {
//console.log("GOT ACTION UDP", "0x"+subPacketId.toString(16), data);
}
}
} else if (packetId === 0x09) { // Keep alive (JJ2+)
var toSend = data;
udpSend(toSend);
} else if (packetId === 0x0B) {
if (data[3] > 0) {
startTCP();
} else if (password) {
//console.log("Wrong password '"+password+"' for "+server.info.servername);
}
} else {
//console.log("UDP", data)
}
}
});
var extraPlusData = new Buffer(0);
var sendChat = function (msg) {
if(server.client.socketId) {
var toSend = "\x1B"+String.fromCharCode(server.client.socketId)+"\x20"+msg;
toSend = String.fromCharCode(toSend.length+1)+toSend;
if(conn.client._handle) {
conn.client.write(new Buffer(toSend, "binary"));
return true;
}
}
return false;
};
var getPlayerId = function (sock) {
var result = [];
for(var i=0; i < server.client.players.length; i+=1) {
if(server.client.players[i] !== undefined && server.client.players[i].socketId === sock) {
result.push(i);
}
}
return result;
};
function startTCP () {
var client = net.connect(server.info.port, server.info.ip);
conn.client = client;
client.on('connect', function () {
clearTimeout(clientTimer);
console.log('connected to '+server.info.address);
var buf = new Buffer(9);
buf.write("\x09\x0F", 0, 'binary');
buf.writeUInt16LE(udpPort, 2);
server.info.version.copy(buf, 4);
buf.write("\x01", 8, 'binary');
client.write(buf);
});
client.on('data', function (res) {
// TODO: Clean up the code!
var p = 0, j = res.length, res_a = [], l = 0;
var special = false;
while (p < j) {
l = res[p];
if (l === 0 && ++p < j) {
l = res[p];
var buf = new Buffer(l+1);
buf[0] = l;
res.copy(buf, 1, p+2, p+2+l);
res_a.push(buf);
p += 2;
} else {
if (p+l > j) {
//console.log('oob', p, l, j, res);
break;
}
res_a.push(res.slice(p, p+l));
}
p += l;
}
for (var key = 0; key < res_a.length; key++) { // Loops through packet array
var data = res_a[key];
//console.log(data);
var packetId = data[1];
if (packetId === 0x0D) { // Disconnect
//console.log(data);
var type = data[2];
var message = disconnectMessages[type] || ("Unknown error |"+type);
var playerid = getPlayerId(data[3]);
var reason = data.length > 10 ? data.slice(10).toString('binary') : "";
//console.log("Disconnected:", data[3], type, message, reason && "("+reason+")");
for(var i = 0; i < playerid.length; i++) {
if(type !== 7) {
sendChat("§1"+server.client.players[playerid[i]].name+" left: |"+message +" |"+(reason && "("+reason+")"));
}
if (playerid[i] === server.client.playerId) {
console.log("The bot was disconnected from", server.info.address, server.info.servername, message, reason && "("+reason+")");
}
delete server.client.players[playerid[i]];
}
} else if (packetId === 0x10) { // Server info
var i = 2;
server.client.socketId = data[i++];
server.client.playerId = data[i++];
var l = data[i++];
server.client.levelName = data.slice(i, i + l).toString('binary');
i += l;
i+=8; // Skip CRC stuff
server.client.game.gamemode = data[i++];
server.client.game.maxscore = data[i++];
if (data.length > i) {
extraPlusData = data.slice(i);
} else {
client.destroy();
connectFailed();
return;
}
client.write("\x08\x3F\x20\x01\x00\x00\x03\x00"); // JJ2+ New
//console.log("info?!1+", data.slice(i));
var toSend = "\x0E\x01"+String.fromCharCode(server.client.playerId)+"\x01\x00"+"SGIP"+BOT_NAME+"\x00";
toSend = String.fromCharCode(toSend.length+1)+toSend;
client.write(toSend, 'binary');
} else if(packetId === 0x11) { // Someone joins...
var packetLength = data.length;
var i=4; // Skip player amount
var sockID = data[2];
var playerid;
var pname = "";
var fur;
var charTeam;
while(packetLength>i) {
playerid = data[i++];
charTeam = data[i++];
i++;
fur = [data[i++], data[i++], data[i++], data[i++]];
pname = "";
while(data[i] != undefined) {pname+=String.fromCharCode(data[i++]);if(data[i]==0) break;}
i+=1;
server.client.players[playerid] = {
charTeam: charTeam,
fur: fur,
name: pname,
socketId: sockID,
spectating: false,
points: 0,
deaths: 0,
ping: -1
};
}
} else if(packetId === 0x12) { // Playerlist
var packetLength = data.length;
var totalplayers = 0;
var i = 3;
while (packetLength>i) {
var psock = data[i++];
var pplayer = data[i++];
var pcharTeam = data[i++];
i++;
var fur = [data[i++], data[i++], data[i++], data[i++]];
var pname = "";
while(data[i] != undefined) {pname+=String.fromCharCode(data[i++]);if(data[i]==0) break;}
i += 1;
totalplayers += 1;
if (!server.client.players[pplayer]) {
server.client.players[pplayer] = {
spectating: false,
points: 0,
deaths: 0,
ping: -1
};
}
var player = server.client.players[pplayer];
player.name = pname;
player.fur = fur;
player.charTeam = pcharTeam;
player.socketId = psock;
//roomBroadcast(JSON.stringify({'console': [(pplayer+1)+". "+pname, 1]}), roomId);
}
//console.log(server.client.players);
//roomBroadcast(JSON.stringify({'console': [Array.prototype.slice.call(data, 2).join(" "), 1]}), roomId);
} else if (packetId === 0x13) {
if (server.isConnected) {
continue;
}
console.log("Game init", server.info.address, server.info.servername);
// ??
//udp.send(new Buffer([0x0A, 0x15, 0x09, 0x00 ]), 0, 4, server.info.port, server.info.ip);
var toSend = new Buffer(8);
toSend[2] = 0x09;
toSend[3] = server.client.socketId;
extraPlusData.copy(toSend, 4, 4, 8);
toSend = udpchecksum(toSend);
udpSend(toSend);
toSend = new Buffer(6);
toSend[0] = 6;
toSend[1] = 0x1A;
extraPlusData.copy(toSend, 2, 0, 4);
client.write(toSend);
client.write("\x03\x42\x21", 'binary'); // Make bot spectate
server.isConnected = true; // Important
var startTime = Date.now();
var udpTimer = setInterval(function () {
var toSend = new Buffer([0, 0, 0x01, 0, server.client.playerId, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
udpSend(toSend);
toSend = new Buffer(5+7);
toSend.fill(0);
toSend[2] = 0x09;
toSend[4] = 0x07;
toSend[5] = server.client.playerId;
toSend[6] = 0x0C;
toSend[7] = 0x20;
toSend[8] = 0xA0;
toSend[9] = 0x01;
toSend[10] = 0x00;
toSend[11] = 0x02;
toSend = udpchecksum(toSend);
udpSend(toSend);
}, 1000);
} else if(packetId === 0x16) { // Level cycle
//console.log("CYCLE", data.slice(2));
toSend = new Buffer(6);
toSend[0] = 6;
toSend[1] = 0x1A;
data.copy(toSend, 2, data.length-10, data.length-10+4);
//console.log("CYCLE RESPONSE", toSend);
client.write(toSend);
for (var i = 0; i < server.client.players.length; i++) {
var player = server.client.players[i];
if (player) {
player.points = 0;
player.deaths = 0;
//console.log("Reset points/deaths for "+player.name);
}
}
} else if (packetId === 0x17) { // End of level
} else if (packetId === 0x18) { // Events update
} else if (packetId === 0x1B) { // Chat
} else if (packetId === 0x3F) { // Plus packet
game.customMode = data[6];
} else if (packetId === 0x40) { // Console message
//console.log("Console: "+data.slice(3).toString('binary'));
} else if (packetId === 0x41) {
//console.log("SPECTATE", data.slice(2));
//sendChat('got spectate packet: '+data[2].toString(2)+' ['+Array.prototype.slice.call(data, 2).join(", ")+']');
var i = 2;
var spectatePacketType = data[i++];
if (spectatePacketType === 0) {
//sendChat("zepectate: "+data[i++].toString(2)+" "+data[i++].toString(2)+" ["+Array.prototype.slice.call(data, 2).join(", ")+']');
var unknown = data[i++];
var binary = data[i++];
for (var i = 0; i < server.client.players.length; i++) {
var player = server.client.players[i];
if (player) {
var isSpec = ((binary >> player.socketId) & 1) === 1;
if (isSpec !== player.spectating) {
if (isSpec) {
//sendChat(player.name+" is now spectating");
player.points = 0;
player.deaths = 0;
//console.log("Reset points/deaths for "+player.name);
} else {
//sendChat(player.name+" is no longer spectating");
}
player.spectating = isSpec;
}
}
}
} else if (spectatePacketType === 1) {
var spectateType = data[i++];
var clientId = data[i++];
var spectateId = data[i++];
var playerIds = getPlayerId(clientId);
//console.log("someone changed spec", data);
var isSpec = spectateId !== 0xFE;
for (var i = 0; i < playerIds.length; i++) {
var player = server.client.players[playerIds[i]];
if (player && isSpec !== player.spectating) {
if (isSpec) {
//sendChat(player.name+" is spectating");
player.points = 0;
player.deaths = 0;
} else {
//sendChat(player.name+" is no longer spectating");
}
player.spectating = isSpec;
}
}
}
/*if(data[0] === 5) {
console.log("got spec list: "+data[2].toString(2), data.slice(3));
//sendChat('got spec list: '+data[2].toString(2)+' ['+Array.prototype.slice.call(data, 2)+']');
var binary = data[2];
for (var i = 0; i < server.client.players.length; i++) {
var player = server.client.players[i];
if (player) {
var isSpec = ((binary >> player.socketId) & 1) === 1;
console.log(isSpec, player.spectating)
if (isSpec !== player.spectating) {
if (isSpec) {
sendChat(player.name+" is spectating");
} else {
sendChat(player.name+" is no longer spectating");
}
player.spectating = isSpec;
}
}
}
}
else {
var playerIds = getPlayerId(data[2]);
//console.log("someone changed spec", data);
var isSpec = data[3] !== 0xFE;
for (var i = 0; i < playerIds.length; i++) {
var player = server.client.players[playerIds[i]];
if (player && isSpec !== player.spectating) {
if (isSpec) {
sendChat(player.name+" is spectating");
} else {
sendChat(player.name+" is no longer spectating");
}
player.spectating = isSpec;
}
}
}*/
} else if (packetId === 0x45) { // Time
var gameState = data[2];
var gameStarted = !!(gameState & 1);
var inPregame = !((gameState >> 1) & 1) && ((gameState >> 2) & 1);
var inOvertime = !!(((gameState >> 1) & 1) && ((gameState >> 2) & 1));
var timeLeft = data.readUInt32LE(3)/1000;
var mins = Math.floor(timeLeft / 60);
var secs = Math.floor(timeLeft) % 60;
game.time.started = gameStarted;
game.time.autoCycle = !!((gameState >> 1) & 1);
game.time.inPregame = inPregame;
game.time.inOvertime = inOvertime;
game.time.timeLeft = timeLeft;
server.client.lastTimeUpdate = Date.now();
//console.log(timeLeft);
//sendChat("§0|"+(gameStarted?(inPregame?"|||":"")+(inOvertime?"||":""):"|")+zfs(mins)+":"+zfs(secs)+" left");
} else if (packetId === 0x49) { // Pings
//sendChat("Pings: "+Array.prototype.slice.call(data, 2).join(", "));
var i = 2;
while (i < data.length) {
var playerId = data[i++];
var ping = data.readUInt16LE(i); i+=2;
var player = server.client.players[playerId];
if (player) {
player.ping = ping;
}
}
} else if (packetId === 0x4A) { // Gamemode and maxscore
var gamemode = data[2];
var customGamemode = data[3];
var maxscore = data[4];
game.gamemode = gamemode;
game.maxscore = maxscore;
game.customMode = customGamemode;
//console.log(customGamemode > 0 ? "Custom gamemode: "+customGamemode : "Gamemode: "+gamemode, "maxscore: "+maxscore)
} else if (packetId === 0x4C) { // Player stats
var i = 2, len = data.length;
while (i < len) {
var playerId = data[i++];
var points = data.readUInt32LE(i); i += 4;
var deaths = data.readUInt32LE(i); i += 4;
var player = server.client.players[playerId];
if (player) {
player.points = points;
player.deaths = deaths;
//sendChat(player.name+' got '+player.points+' points and '+player.deaths+' deaths');
} else {
sendChat("Unknown player "+playerId);
}
}
} else if (packetId === 0x4D) { // Deaths
//sendChat(Array.prototype.slice.call(data, 2).join(", "));
var i = 2, len = data.length;
while (i < len) {
var playerId = data[i++];
var deaths = data.readUInt32LE(i); i += 4;
var player = server.client.players[playerId];
if (player) {
player.deaths = deaths;
//sendChat(player.name+' got '+player.deaths+' deaths');
} else {
sendChat("Unknown player "+playerId);
}
}
} else if (packetId === 0x50) { // TCP_SC_MISC
} else if (packetId === 0x52) { // Idleserver
game.isIdleserver = !!data[2];
//sendChat("IDLESERVER IS "+(isIdleserver? "|ENABLED" : "||DISABLED"));
} else {
//console.log("TCP: 0x"+packetId.toString(16), data.slice(2));
}
//console.log("0x"+packetId.toString(16));
}
});
client.on('error', function (err) {
console.log("client "+err);
});
client.on('close', function () {
console.log('Disconnected from', server.info.address, server.info.servername);
connectFailed();
});
var clientTimer = setTimeout(function () {
client.destroy();
}, 3000);
}
};
var conn = {};
var query = udpchecksum(new Buffer("yy\x05\x00"));
conn.udp = dgram.createSocket("udp4");
var udp = conn.udp;
var isFirst = true;
udp.on('listening', function () {
var rinfo = udp.address();
//console.log("Listening on "+rinfo.address+":"+rinfo.port);
udpPort = rinfo.port;
udp.send(query, 0, query.length, server.info.port, server.info.ip);
});
udp.on('message', function (data, rinfo) {
if (rinfo.address === server.info.ip && rinfo.port === server.info.port && isFirst) {
isFirst = false;
clearTimeout(queryTimer);
server.info.version = data.slice(8, 8+4);
server.info.capacity = [data[12], data[15]];
server.info.gametype = data[14];
server.info.servername = data.slice(17, 17+data[16]).toString('binary');
joinServer();
}
});
udp.on('error', function (err) {
console.log('UDP '+err)
});
udp.bind();
var queryTimer = setTimeout(function () {
conn.udp.close();
connectFailed();
}, 3000);
connections[server.info.address] = conn;
servers.push(server);
serverLookup.push(server.info.address);
};
function detachServer (index) {
if (index > -1) {
console.log('Remove server '+servers[index].info.address);
var lookupIndex = serverLookup.indexOf(servers[index].info.address);
//console.log("indices should be same:", index, lookupIndex);
delete connections[servers[index].info.address];
servers.splice(index, 1);
serverLookup.splice(lookupIndex, 1);
}
};
function handleServerlist (list, addresses) {
for (var i = 0; i < servers.length; i++) {
var server = servers[i];
if(addresses.indexOf(server.info.address) === -1 && !connections[server.info.address]) {
// remove/disconnect from server
detachServer(i);
} else {
// server exists, do nothing?
}
}
for (var i = 0; i < list.length; i++) {
if (serverLookup.indexOf(addresses[i]) === -1 && !connections[addresses[i]]) {
// add/connect to server
attachServer(list[i]);
} else {
// server exists, do nothing?
}
}
};
function scanServerlist() {
console.log(new Date()+" Scanning listservers...")
var counter = 0;
var list = [];
var addresses = [];
function handleListserver (listserver) {
var buffers = "";
var ls = net.connect(10053, listserver);
var timeout = setTimeout(function () {
console.log(listserver, "timeout");
ls.destroy();
}, 5*1000);
ls.on('connect', function () {
console.log(listserver, "connected");
});
ls.on('data', function (data) {
clearTimeout(timeout);
buffers += data.toString('binary');
});
ls.on('error', function (err) {
clearTimeout(timeout);
console.log(listserver, err);
});
ls.on('close', function () {
console.log(listserver, "closed");
clearTimeout(timeout);
var buffer = new Buffer(buffers, 'binary');
var i = 7;
var len = buffer.length;
while (i < len) {
var l = buffer[i];
var part = buffer.slice(i, i+l);
i += l;
var ip = [part[4], part[3], part[2], part[1]].join(".");
var port = part.readUInt16LE(5);
var address = ip+":"+port;
var isBlacklisted = !(!database[address] || (database[address] && database[address].blacklistlevel === 0));
if (addresses.indexOf(ip+":"+port) === -1 && !isBlacklisted) {
var name = part.slice(7, l).toString('binary');
addresses.push(address);
list.push({ip: ip, port: port, servername: name});
} else if (isBlacklisted) {
console.log("Access to "+address+" was denied.");
}
}
if (--counter === 0) {
console.log("Found "+list.length+" servers");
handleServerlist(list, addresses);
setTimeout(function () {
refreshDb(function () {
scanServerlist();
})
}, 15*60*1000);
}
});
};
for (var i = 0; i < listservers.length; i++) {
counter++;
handleListserver(listservers[i]);
}
};
function startApiServer () {
var apiServer = net.createServer(function (client) {
client.on('data', function (data) {
try {
var message = JSON.parse(data.toString('utf8'));
} catch (e) {
client.end("Invalid JSON");
return;
}
var toSend = {error: 0};
if (message.ip !== undefined && message.port !== undefined) {
//console.log("Got API request");
var index = serverLookup.indexOf(message.ip+":"+message.port);
if (index !== -1) {
var server = servers[index];
if (server.isConnected) {
server.client.game.time.time = server.client.game.time.timeLeft - (server.client.game.time.started? (Date.now() - server.client.lastTimeUpdate)/1000 : 0);
toSend.players = server.client.players;
toSend.game = server.client.game;
} else {
toSend.error = 2;
}
} else {
//console.log("No such server: ", message.ip+":"+message.port, serverLookup);
toSend.error = 1;
}
} else if (message.update !== undefined) {
refreshDb();
} else {
toSend.error = 3;
}
client.end(JSON.stringify(toSend));
});
client.on('close', function () {
//console.log('api client left');
});
client.on('error', function () {
});
});
apiServer.listen(8007, 'localhost', function () {
console.log('SGIP bot API server listening on localhost:8007');
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment