Ssh mengobrol

Hai, Habr. Obrolan konsol adalah hal yang hebat, tetapi untuk front-end, tetapi bagaimana jika Anda menginginkan hal yang sama, tetapi untuk backend. Jika ya, maka artikel ini untuk Anda. Tapi alat apa yang sering digunakan di backend? Itu benar ssh, jadi saya mewakili sshchat.


Bagaimana kelihatannya


Di suatu tempat di server, program pada simpul berputar.
Segera setelah seseorang ingin terhubung ke obrolan, ia masuk:


ssh server -p 8022 

Setelah itu, sistem meminta kata sandi dan memverifikasinya dengan kata sandi dalam file khusus. Jika kata sandi cocok, maka kami terhubung ke obrolan (pengguna menerima 100 pesan sebelumnya dan semua orang melihat bahwa ia terhubung).


Kemudian dia menerima pesan dari orang lain, dan bisa menulis sendiri.


Di sini dengan pesan yang lebih menarik:


 @box{@color(red){Red text in box}} 

Kirim teks merah dalam kotak.


Mari kita mulai


Untuk bekerja dengan ssh, kami akan menggunakan https://www.npmjs.com/package/ssh2 .
Untuk memformat kami menggunakan kapur dan boxen.
Jadi instal:


 npm i ssh2 chalk boxen 

Sekarang kode itu sendiri adalah salah satu bagian terpenting dari parser pesan ini ( GitHub ):


 //  chalk  boxen const chalk = require('chalk'); const boxen = require('boxen'); //         @ //   2           let methods = { color: function(args, text) { return chalk.keyword(args)(text); }, bold: function(args, text) { return chalk.bold(text); }, underline: function(args, text) { return chalk.underline(text); }, hex: function(args, text) { return chalk.hex(args)(text); }, box: function(args, text) { return boxen(text, { borderStyle: 'round', padding: 1, borderColor: 'blueBright' }); } }; //   function parseAndExecute(str) { let pos = 0; let stage = 0; let nS = ''; let bufs = ['', '', '', '']; let level = 0; while (pos < str.length) { let symbol = str[pos]; pos++; if (symbol == '\\' && '(){}@'.indexOf(str[pos]) !== -1) { bufs[stage] += str[pos]; pos++; continue; } if (stage == 0 && symbol == '@') { stage++; nS += bufs[0]; bufs[0] = ''; continue; } else if (stage >= 1) { if (symbol == '(') if (stage < 2) { stage = 2; } else { level++; } if (symbol == ')' && stage >= 2 && level > 0) level--; if (symbol == '{') if (stage != 3) { stage = 3; } else { level++; } if (symbol == '}') { if (level == 0) { bufs[3] += '}'; nS += methods[bufs[1]](bufs[2].slice(1, -1), parseAndExecute(bufs[3].slice(1, -1))); bufs = ['', '', '', '']; stage = 0; continue; } else { level--; } } } bufs[stage] += symbol; } return nS + bufs[0]; } module.exports.parseAndExecute = parseAndExecute; 

Pemformatan ( GitHub ):


 const chalk = require('chalk'); const { parseAndExecute } = require('./parserExec') //  (    ) function getNick(nick) { let hash = 0; for (var i = 0; i < nick.length; i++) hash += nick.charCodeAt(i) - 32; return chalk.hsv((hash + 160) % 360, 90, 90)(chalk.bold(nick)); } module.exports.format = function(nick, message) { const nickSpace = '\r ' + ' '.repeat(nick.length); nick = getNick(nick) + ': '; message = message.replace(/\\n/gm, '\n'); //  \n   message = parseAndExecute(message) //  //       message = message .split('\n') .map((e, i) => '' + (i !== 0 ? nickSpace : '') + e) .join('\n'); return nick + message; }; 

Metode untuk mengirim pesan ke semua pengguna dan menyimpan 100 pesan ( GitHub ):


 let listeners = []; //   let cache = new Array(100).fill('') //  //     module.exports.addListener = write => listeners.push(write) - 1; module.exports.delListener = id => listeners.splice(id, 1); //   module.exports.broadcast = msg => { cache.shift() cache.push(msg) process.stdout.write(msg) listeners.forEach(wr => wr(msg)); } //   module.exports.getCache = ()=>cache.join('\r\033[1K') 

Lobi, pembuatan dan otorisasi server ( GitHub ):


 const { Server } = require('ssh2'); const { readFileSync } = require('fs'); const hostKey = readFileSync('./ssh'); //   const users = JSON.parse(readFileSync('./users.json')); //  let connectionCallback = () => {}; module.exports.createServer = function createServer({ lobby }) { //   const server = new Server( { banner: lobby, //      hostKeys: [hostKey] }, function(client) { nick = ''; client .on('authentication', ctx => { //  if (ctx.method !== 'password') return ctx.reject(); if (ctx.password !== users[ctx.username]) ctx.reject(); nick = ctx.username; ctx.accept(); }) .on('ready', function() { connectionCallback(client, nick); }); } ); return server }; module.exports.setConnectCallback = callback => { //     connectionCallback = callback; }; 

Berbagai metode ( GitHub ):


 const { createInterface } = require('readline'); module.exports.getStream = function(client, onStream, onEnd){ client //     .on('session', function(accept, reject) { accept() .on('pty', accept => accept & accept()) .on('shell', accept => onStream(accept())); }) .on('end', () => onEnd()); } //   module.exports.getCommunicator = function(stream, onMessage, onEnd){ let readline = createInterface({ //     input: stream, output: stream, prompt: '> ', historySize: 0, terminal: true }) readline.prompt() readline.on('close', ()=>{ radline = null; onEnd() stream.end() }) readline.on('line', (msg)=>{ stream.write('\033[s\033[1A\033[1K\r') onMessage(msg) readline.prompt() }) //     return msg=>{ stream.write('\033[1K\r' + msg) readline.prompt() } } 

Sekarang gabungkan ( GitHub ):


 const { createServer, setConnectCallback } = require('./lobby'); const { getStream, getCommunicator } = require('./utils'); const { addListener, delListener, broadcast, getCache } = require('./broadcaster'); const { format, getNick } = require('./format'); //    module.exports = function({ lobby = 'Hi' } = {}) { const server = createServer({ lobby }); setConnectCallback((client, nick) => { //   console.log('Client authenticated!'); let id = null; getStream( //   client, stream => { const write = getCommunicator( //   stream, msg => { if (msg == '') return; try { broadcast(format(nick, msg) + '\n'); //    ,    } catch (e) {} }, () => {} ); id = addListener(write); //   write('\033c' + getCache()); //   broadcast(getNick(nick) + ' connected\n'); //    }, () => { delListener(id); broadcast(getNick(nick) + ' disconnected\n') //    } ); }); server.listen(8022); }; 

Dan langkah terakhir adalah contoh server:


 const chat = require('.') chat({}) 

File users.json juga menjelaskan pengguna dan kata sandi mereka.


Kesimpulan


Ini adalah bagaimana Anda dapat menulis bukan obrolan termudah di ssh.
Untuk obrolan seperti itu, klien tidak perlu menulis, ia memiliki kemampuan desain, dan siapa pun dapat menggunakannya.


Apa lagi yang bisa dilakukan:


  • Tambahkan kemampuan untuk membuat fitur desain Anda sendiri
  • Tambahkan dukungan penurunan harga
  • Tambahkan dukungan bot
  • Tingkatkan keamanan kata sandi (hash dan garam)

Repositori terakhir

Source: https://habr.com/ru/post/id466633/


All Articles