andrade-soulseek-downloader
Version:
Simple, safe Soulseek download library with built-in rate limiting to prevent bans
223 lines • 9.42 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Server = void 0;
const events_1 = require("events");
const net = __importStar(require("net"));
const crypto = __importStar(require("crypto"));
const messages_1 = require("./messages");
const message_factory_1 = require("./message-factory");
const stack_1 = __importDefault(require("./stack"));
const debug = (msg) => {
if (process.env.DEBUG?.includes('slsk:server')) {
console.log(`[slsk:server] ${msg}`);
}
};
class Server extends events_1.EventEmitter {
conn;
constructor(serverAddress, cb) {
super();
this.conn = net.createConnection(serverAddress, cb);
const msgs = new messages_1.Messages();
this.conn.on('error', err => {
cb(new Error(err.message));
});
this.conn.on('data', data => {
msgs.write(data);
});
msgs.on('message', (msg) => {
const size = msg.int32();
if (size < 4)
return;
const code = msg.int32();
switch (code) {
case 1: {
debug('Login Response');
if (!stack_1.default.login)
return;
const success = msg.int8();
if (success === 1) {
stack_1.default.login(undefined);
delete stack_1.default.login;
const greet = msg.str();
debug(`Login succeed: ${greet}`);
debug('send SharedFoldersFiles');
this.conn.write(message_factory_1.MessageFactory.to.server.sharedFoldersFiles(1, 1).getBuff());
debug('send Have No Parents 1');
this.conn.write(message_factory_1.MessageFactory.to.server.haveNoParents(1).getBuff());
debug('send SetStatus online');
this.conn.write(message_factory_1.MessageFactory.to.server.setStatus(2).getBuff());
}
else {
const reason = msg.str();
stack_1.default.login(new Error(reason));
delete stack_1.default.login;
}
break;
}
case 3: {
const user = msg.str();
const ip = [];
for (let i = 0; i < 4; i++) {
ip.push(msg.int8());
}
const host = ip[3] + '.' + ip[2] + '.' + ip[1] + '.' + ip[0];
const port = msg.int32();
this.emit('get-peer-address', { user, host, port });
break;
}
case 7: {
const user = msg.str();
const status = msg.int32();
debug(`recv GetUserStatus for ${user}: ${status}`);
break;
}
case 18: {
const user = msg.str();
const type = msg.str();
const ip = [];
for (let i = 0; i < 4; i++) {
ip.push(msg.int8());
}
const host = ip[3] + '.' + ip[2] + '.' + ip[1] + '.' + ip[0];
const port = msg.int32();
const token = msg.rawHexStr(4);
this.emit('connect-to-peer', { user, type, ip, host, port, token });
break;
}
case 36: {
const user = msg.str();
const avgSpeed = msg.int32();
const downloadNum = msg.int32();
const something = msg.int32();
const files = msg.int32();
const folders = msg.int32();
debug(`recv GetUserStats user: ${user}, avgSpeed ${avgSpeed}, files ${files}, folders ${folders}. downloadNum ${downloadNum}. something... ${something}`);
break;
}
case 64: {
debug(`recv RoomList ${msg.data.length}`);
const nbRooms = msg.int32();
const rooms = [];
for (let i = 0; i < nbRooms; i++) {
rooms.push({
name: msg.str(),
users: 0
});
}
for (let i = 0; i < nbRooms; i++) {
rooms[i].users = msg.int32();
}
break;
}
case 69: {
const number = msg.int32();
debug(`there are ${number} PrivilegedUsers. msg length: ${msg.data.length}`);
break;
}
case 83: {
const number = msg.int32();
debug(`ParentMinSpeed is ${number}. msg length: ${msg.data.length}`);
break;
}
case 84: {
const number = msg.int32();
debug(`ParentSpeedRatio is ${number}. msg length: ${msg.data.length}`);
break;
}
case 102: {
const numberOfParents = msg.int32();
debug(`recv NetInfo, number of search parents: ${numberOfParents}`);
for (let i = 0; i < numberOfParents; i++) {
const user = msg.str();
const ip = [];
for (let j = 0; j < 4; j++) {
ip.push(msg.int8());
}
const host = ip[3] + '.' + ip[2] + '.' + ip[1] + '.' + ip[0];
const port = msg.int32();
debug(`Parent ${user} ${host} ${port}`);
this.conn.write(message_factory_1.MessageFactory.to.server.parentIp(ip).getBuff());
this.emit('connect-to-peer', {
user,
type: 'D',
ip,
host,
port,
token: crypto.randomBytes(4).toString('hex')
});
}
break;
}
case 104: {
const number = msg.int32();
debug(`Whishlist interval is ${number}. msg length: ${msg.data.length}`);
break;
}
case 1001: {
const token = msg.rawHexStr(4);
debug(`Cannot connect to peer, token ${token}`);
break;
}
default: {
debug(`unknown srv message code: ${code} length: ${msg.data.length}`);
}
}
});
}
login(credentials) {
this.conn.write(message_factory_1.MessageFactory.to.server.login(credentials).getBuff());
}
fileSearch(query, token) {
debug(`send FileSearch: ${query}`);
this.conn.write(message_factory_1.MessageFactory.to.server.fileSearch(query, token).getBuff());
}
setWaitPort(port) {
debug(`send SetWaitPort ${port}`);
this.conn.write(message_factory_1.MessageFactory.to.server.setWaitPort(port).getBuff());
}
getPeerAddress(username) {
debug(`send GetPeerAddress ${username}`);
this.conn.write(message_factory_1.MessageFactory.to.server.getPeerAddress(username).getBuff());
}
destroy() {
this.conn.destroy();
}
}
exports.Server = Server;
//# sourceMappingURL=server.js.map