рдПрд╕рдПрд╕рдПрдЪ-рдЪреИрдЯ, рднрд╛рдЧ 2

рдирдорд╕реНрддреЗ, рд╣рдмрд░ред рдпрд╣ ssh-рдЪреИрдЯ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рджреВрд╕рд░рд╛ рд▓реЗрдЦ рд╣реИред

рд╣рдо рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗ:

  • рдЖрдЗрдП рдЖрдкрдХреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдбрд┐рдЬрд╝рд╛рдЗрди рдлрд╝рдВрдХреНрд╢рдВрд╕ рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝реЗрдВ
  • рдЖрдЗрдП рдорд╛рд░реНрдХрдбрд╛рдЙрди рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВ
  • рдЖрдЗрдП рдмреЙрдЯ рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВ
  • рдкрд╛рд╕рд╡рд░реНрдб рд╕реБрд░рдХреНрд╖рд╛ рдмрдврд╝рд╛рдПрдБ (рд╣реИрд╢ рдФрд░ рдирдордХ)
    рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдлрд╝рд╛рдЗрд▓реЗрдВ рдирд╣реАрдВ рднреЗрдЬреА рдЬрд╛рдПрдВрдЧреАред

рдХрд╕реНрдЯрдо рдбрд┐рдЬрд╝рд╛рдЗрди рд╕реБрд╡рд┐рдзрд╛рдПрдБ

рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбрд┐рдЬрд╝рд╛рдЗрди рдлрд╝рдВрдХреНрд╢рди рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ:

  • @color
  • @bold
  • @underline
  • @hex
  • @box
    рд▓реЗрдХрд┐рди рдпрд╣ рдЖрдкрдХреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝рдиреЗ рд▓рд╛рдпрдХ рд╣реИ:
    рд╕рднреА рдлрд╝рдВрдХреНрд╢рди рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИрдВ ╨╛╨▒╤К╨╡╨║╤В╨╡ ╨┐╨╛╨┤ ╨╜╨░╨╖╨▓╨░╨╜╨╕╨╡╨╝ methods
    рддреЛ рдпрд╣ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ registerMethod:

// parserExec.js at end
module.exports.registerMethod  =  function(name, func) {
  methods[name] =  func
}

рд╕рд░реНрд╡рд░ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж рдЖрдкрдХреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

// index.js at require part
const { registerMethod } = require('./parserExec')

// index.js at end
module.exports.registerMethod  =  registerMethod

рдЕрдм, рд╕рд░реНрд╡рд░ рдмрдирд╛рддреЗ рд╕рдордп, рд╣рдо рдлрд╝реЙрд░реНрдореЗрдЯрд┐рдВрдЧ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг:

const  chat  =  require('.')
const { formatNick } =  require('./format')

chat({})

chat.registerMethod('hello', function(p, name){
  return  'Hi, '  +  formatNick(name) +  '!'
})

рдПрд╕рдПрд╕рдПрдЪ-рдЪреИрдЯ, рднрд╛рдЧ 2

рдорд╛рд░реНрдХрдбрд╛рдЙрди рд╕рдорд░реНрдерди

рдорд╛рд░реНрдХрдбрд╛рдЙрди рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рддреЛ рдЖрдЗрдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬреЛрдбрд╝реЗрдВ рдЯрд░реНрдорд┐рдирд▓ рдЪрд┐рд╣реНрдирд┐рдд

// format.js near require
const marked = require('marked');
const TerminalRenderer = require('marked-terminal');

marked.setOptions({
  renderer: new TerminalRenderer()
});

// format.js line 23
message = marked(message)

рдПрд╕рдПрд╕рдПрдЪ-рдЪреИрдЯ, рднрд╛рдЧ 2

рдмреЙрдЯ

рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛

let writeBotBob = chat.registerBot({
  name: 'botBob',

  onConnect(nick, write){
    write('@hello{' + nick + '}')
  },

  onDisconnect(nick, write){},

  onMessage(nick, message, write) {
    if(message == 'botBob!') write('I'm here')
  },

  onCommand(command, write) {
    write('Doing ' + command)
  }
})

onCommand рдХреЗ рд╕рд╛рде рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ @bot(botBob){Command}

рдмреЙрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ:

let bots = []; // ╨Т╤Б╨╡ ╨▒╨╛╤В╤Л

let onWrite = () => {}; 

function getWrite(bot) { // ╨У╨╡╨╜╨╡╤А╨╕╤А╤Г╨╡╤В ╨╝╨╡╤В╨╛╨┤ ╨╛╤В╨┐╤А╨░╨▓╨║╨╕ ╤Б╨╛╨╛╨▒╤Й╨╡╨╜╨╕╤П ╨┤╨╗╤П ╨▒╨╛╤В╨░
  return msg => {
    onWrite(bot.name, msg);
  };
}

module.exports.message = function message(nick, message) { // index.js ╨▓╤Л╨┐╨╛╨╗╨╜╨╕╤В ╤Н╤В╤Г ╤Д╤Г╨╜╨║╤Ж╨╕╤О ╨┐╨╛╤Б╨╗╨╡ ╨╛╤В╨┐╤А╨░╨▓╨║╨╕ ╤Б╨╛╨╛╨▒╤Й╨╡╨╜╨╕╤П
  bots.forEach(bot => {
    try {
      bot.onMessage(nick, message, getWrite(bot));
    } catch (e) {
      console.error(e);
    }
  });
};

module.exports.connect = function message(nick) { // ╨Я╤А╨╕ ╤Б╨╛╨╡╨┤╨╕╨╜╨╡╨╜╨╕╨╕
  bots.forEach(bot => {
    try {
      bot.onConnect(nick, getWrite(bot));
    } catch (e) {
      console.error(e);
    }
  });
};

module.exports.disConnect = function message(nick) { // ╨Я╤А╨╕ ╨╛╤В╤Б╨╛╨╡╨┤╨╕╨╜╨╡╨╜╨╕╨╕
  bots.forEach(bot => {
    try {
      bot.onDisconnect(nick, message, getWrite(bot));
    } catch (e) {
      console.error(e);
    }
  });
};

module.exports.command = function message(name, message) { // ╨Я╤А╨╕ ╨▓╤Л╨┐╨╛╨╗╨╜╨╡╨╜╨╕╨╕ ╨║╨╛╨╝╨░╨╜╨┤╤Л
  bots.forEach(bot => {
    if (bot.name == name) {
      try {
        bot.onCommand(message, getWrite(bot));
      } catch (e) {
        console.error(e);
      }
    }
  });
};

module.exports.registerBot = function(bot) {
  bots.push(bot);
  return  getWrite(bot)
};

module.exports.onMessage = func => {
  onWrite = func;
};

рдПрд╕рдПрд╕рдПрдЪ-рдЪреИрдЯ, рднрд╛рдЧ 2

рдЖрдк рдмреЙрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

  • рдореЙрдирд┐рдЯрд░ рд▓реЛрдб рдХрд░реЗрдВ
  • рддреИрдирд╛рддреА
  • рдЯрд╛рд╕реНрдХ рдмреЛрд░реНрдб

рд╣реИрд╢ рдФрд░ рдирдордХ

рдПрд╕рдПрд╕рдПрдЪ рдХреБрдВрдЬреА рдХреНрдпреЛрдВ рдирд╣реАрдВ? рдХреНрдпреЛрдВрдХрд┐ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбрд┐рд╡рд╛рдЗрд╕ рдкрд░ ssh рдХреБрдВрдЬреА рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣реЛрдВрдЧреА
рдЖрдЗрдП рдПрдХ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ рдЬреЛ рдкрд╛рд╕рд╡рд░реНрдб рдХреА рдЬрд╛рдБрдЪ рдФрд░ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдЬрд╝рд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧреА

// crypto.js
const crypto = require('crypto');

function genRandomString(length) {
  return crypto
    .randomBytes(Math.ceil(length / 2))
    .toString('hex')
    .slice(0, length);
}

function sha512(password, salt){
  const hash = crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */
  hash.update(password);
  const value = hash.digest('hex');
  return value
};

function checkPass(pass, obj){
  return obj.password == sha512(pass, obj.salt)
}

function encodePass(pass){
  const salt = genRandomString(16)
  return JSON.stringify({
    salt,
    password: sha512(pass, salt)
  })
}

module.exports.encodePass = encodePass
module.exports.checkPass = checkPass

рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рд╕реЙрд▓реНрдЯ рдХрд░рдиреЗ рдФрд░ рд╣реИрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рднреА

// To generate password run node ./encryptPassword password
const { encodePass } =require('./crypto')
console.log(encodePass(process.argv[2]))

рд╣рдо Users.json рдореЗрдВ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд▓реЙрдмреА.js рдореЗрдВ рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╣рдо checkPassword рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ

рд╕рдВрдкреВрд░реНрдг

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдо рдбрд┐рдЬрд╝рд╛рдЗрди рдХреНрд╖рдорддрд╛рдУрдВ рдФрд░ рдмреЙрдЯреНрд╕ рдХреЗ рд╕рд╛рде ssh рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЪреИрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдЕрдВрддрд┐рдо рднрдВрдбрд╛рд░

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ