UNPKG

andrade-soulseek-downloader

Version:

Simple, safe Soulseek download library with built-in rate limiting to prevent bans

193 lines 9.03 kB
"use strict"; 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.DefaultPeer = void 0; const zlib = __importStar(require("zlib")); const peer_1 = require("./peer"); const messages_1 = require("../messages"); const message_factory_1 = require("../message-factory"); const download_peer_file_1 = require("./download-peer-file"); const stack_1 = __importDefault(require("../stack")); const debug = (msg) => { if (process.env.DEBUG?.includes('slsk:peer:default')) { console.log(`[slsk:peer:default] ${msg}`); } }; class DefaultPeer extends peer_1.Peer { constructor(socket, peer) { super(socket, peer); this.conn.on('connect', () => { if (peer.token) { const buf = Buffer.from('05000000' + '00' + peer.token, 'hex'); this.conn.write(buf); } }); const msgs = new messages_1.Messages(); 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 4: { debug(`${peer.user} recv GetSharedFileList ${size}`); const res = message_factory_1.MessageFactory.to.peer.sharedFileList(1, 'test', 1, '@@abcde\\test\\test-test.mp3'); debug(`${peer.user} sending SharedFileList`); this.conn.write(res.getBuff()); break; } case 9: { debug(`${peer.user} recv FileSearchResult size ${size}`); const content = msg.data.slice(msg.pointer, size + 4); zlib.unzip(content, (err, buffer) => { if (err) { debug(err.toString()); return; } const result = message_factory_1.MessageFactory.from.peer.fileSearchResult(buffer); if (stack_1.default.search[result.currentToken]) { result.files.forEach(file => { stack_1.default.search[result.currentToken].cb({ user: file.user, file: file.file, size: file.size, slots: result.slots === 1, bitrate: file.attribs ? file.attribs[0] : undefined, speed: result.speed, queue: 0 }); }); } }); break; } case 36: { const numberOfFiles = msg.int32(); debug(`${peer.user} recv FolderContentsRequest, files: ${numberOfFiles}`); break; } case 40: { const dir = msg.int32(); const token = msg.rawHexStr(4); const file = msg.str(); debug(`${peer.user} recv TransferRequest ${file}`); // Don't overwrite if token already exists (preserve progressEmitter) if (!stack_1.default.downloadTokens[token]) { stack_1.default.downloadTokens[token] = { user: peer.user, file }; } else { // Update fields but preserve existing properties like progressEmitter stack_1.default.downloadTokens[token].user = peer.user; stack_1.default.downloadTokens[token].file = file; } if (dir === 1) { stack_1.default.downloadTokens[token].size = msg.int32(); } const res = message_factory_1.MessageFactory.to.peer.transferResponse(token); setTimeout(() => { debug(`${peer.user} sending TransferResponse`); this.conn.write(res.getBuff()); }, 200); break; } case 41: { const token = msg.rawHexStr(4); const allowed = msg.int8(); debug(`${peer.user} recv TransferResponse token: ${token} allowed: ${allowed}`); if (allowed === 0) { const reason = msg.str(); debug(`reason: ${reason}, I will receive TransferRequest soon...`); delete stack_1.default.downloadTokens[token]; } else if (allowed === 1) { debug(`Directly allowed. Connecting to peer with PeerInit + ${token}`); const downloader = (0, download_peer_file_1.downloadPeerFile)(peer.host, peer.port, token, peer.user, true); // Link the progress emitters if (stack_1.default.downloadTokens[token] && stack_1.default.downloadTokens[token].progressEmitter) { debug(`Found progressEmitter for token ${token}, linking events`); const mainEmitter = stack_1.default.downloadTokens[token].progressEmitter; downloader.on('start', (data) => { debug(`Forwarding start event`); mainEmitter.emit('start', data); }); downloader.on('progress', (data) => { debug(`Forwarding progress: ${data.percentage}%`); mainEmitter.emit('progress', data); }); downloader.on('complete', (data) => mainEmitter.emit('complete', data)); downloader.on('error', (err) => mainEmitter.emit('error', err)); } else { debug(`No progressEmitter found for token ${token}`); } } break; } case 46: { const filename = msg.str(); debug(`${peer.user} UploadFailed ${filename}`); const down = stack_1.default.download[peer.user + '_' + filename]; if (down && typeof down.cb === 'function') { down.cb(new Error('Peer error')); } else { debug(`Cannot cb for ${peer.user} ${filename}`); } break; } case 50: { const filename = msg.str(); const reason = msg.str(); debug(`${peer.user} QueueFailed ${filename} reason ${reason}`); break; } default: { debug(`${peer.user} unknown peer message code ${code}`); } } }); } } exports.DefaultPeer = DefaultPeer; //# sourceMappingURL=default-peer.js.map