|
@@ -0,0 +1,103 @@
|
|
|
|
|
+const net = require('net');
|
|
|
|
|
+const readline = require('readline');
|
|
|
|
|
+
|
|
|
|
|
+const HOST = 'localhost';
|
|
|
|
|
+const PORT = 6667;
|
|
|
|
|
+
|
|
|
|
|
+const sessions = new Set();
|
|
|
|
|
+
|
|
|
|
|
+function randomNick(len = 8) {
|
|
|
|
|
+ let nick = '';
|
|
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
|
|
+ nick += String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
|
|
|
+ }
|
|
|
|
|
+ return nick;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function createSession() {
|
|
|
|
|
+ const nick = randomNick();
|
|
|
|
|
+ const socket = net.createConnection({ host: HOST, port: PORT });
|
|
|
|
|
+ let buffer = '';
|
|
|
|
|
+
|
|
|
|
|
+ const session = { socket, nick };
|
|
|
|
|
+
|
|
|
|
|
+ socket.on('connect', () => {
|
|
|
|
|
+ socket.write(`NICK ${nick}\r\n`);
|
|
|
|
|
+ socket.write(`USER ${nick} 0 * :${nick}\r\n`);
|
|
|
|
|
+ console.log(`[+] Connected: ${nick}`);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ socket.on('data', (data) => {
|
|
|
|
|
+ buffer += data.toString();
|
|
|
|
|
+ let lines = buffer.split('\r\n');
|
|
|
|
|
+ buffer = lines.pop();
|
|
|
|
|
+ for (const line of lines) {
|
|
|
|
|
+ if (line.startsWith('PING')) {
|
|
|
|
|
+ const token = line.slice(5);
|
|
|
|
|
+ socket.write(`PONG ${token}\r\n`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ socket.on('close', () => {
|
|
|
|
|
+ console.log(`[-] Disconnected: ${nick}`);
|
|
|
|
|
+ sessions.delete(session);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ socket.on('error', (err) => {
|
|
|
|
|
+ console.log(`[!] Error (${nick}): ${err.message}`);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ sessions.add(session);
|
|
|
|
|
+ return session;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function destroySession(session) {
|
|
|
|
|
+ session.socket.destroy();
|
|
|
|
|
+ sessions.delete(session);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function setCount(target) {
|
|
|
|
|
+ const current = sessions.size;
|
|
|
|
|
+ if (target > current) {
|
|
|
|
|
+ for (let i = 0; i < target - current; i++) createSession();
|
|
|
|
|
+ } else if (target < current) {
|
|
|
|
|
+ const toRemove = [...sessions].slice(target);
|
|
|
|
|
+ for (const s of toRemove) destroySession(s);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function sendAll(message) {
|
|
|
|
|
+ for (const s of sessions) {
|
|
|
|
|
+ s.socket.write(`${message}\r\n`);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Start with one connection
|
|
|
|
|
+createSession();
|
|
|
|
|
+
|
|
|
|
|
+const rl = readline.createInterface({ input: process.stdin });
|
|
|
|
|
+
|
|
|
|
|
+rl.on('line', (line) => {
|
|
|
|
|
+ line = line.trim();
|
|
|
|
|
+ if (!line) return;
|
|
|
|
|
+
|
|
|
|
|
+ if (line === 'exit') {
|
|
|
|
|
+ for (const s of [...sessions]) destroySession(s);
|
|
|
|
|
+ process.exit(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const num = Number(line);
|
|
|
|
|
+ if (!isNaN(num) && line !== '') {
|
|
|
|
|
+ setCount(Math.max(0, Math.floor(num)));
|
|
|
|
|
+ console.log(`[*] Sessions: ${sessions.size}`);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ sendAll(line);
|
|
|
|
|
+ console.log(`[>] Sent to ${sessions.size} session(s): ${line}`);
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+rl.on('close', () => {
|
|
|
|
|
+ for (const s of [...sessions]) destroySession(s);
|
|
|
|
|
+ process.exit(0);
|
|
|
|
|
+});
|