Guest User

RCON

a guest
Mar 2nd, 2016
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/js
  2.  
  3. var ANSI_COLORS = {
  4.     'normal':   '\x1B[0m',
  5.     'black':    '\x1B[0;30m',
  6.     'hblack':   '\x1B[1;30m',
  7.     'red':      '\x1B[0;31m',
  8.     'hred':     '\x1B[1;31m',
  9.     'green':    '\x1B[0;32m',
  10.     'hgreen':   '\x1B[1;32m',
  11.     'yellow':   '\x1B[0;33m',
  12.     'hyellow':  '\x1B[1;33m',
  13.     'blue':     '\x1B[0;34m',
  14.     'hblue':    '\x1B[1;34m',
  15.     'magenta':  '\x1B[0;35m',
  16.     'hmagenta': '\x1B[1;35m',
  17.     'cyan':     '\x1B[0;36m',
  18.     'hcyan':    '\x1B[1;36m',
  19.     'white':    '\x1B[0;37m',
  20.     'hwhite':   '\x1B[1;37m',
  21. };
  22.  
  23. function log(msg, color) {
  24.     var date = new Date().toISOString()
  25.                             .replace(/T/, ' ').
  26.                             .replace(/\..+/, '');
  27.     var text = msg;
  28.     if(color != null  && color in ANSI_COLORS) {
  29.         text = ANSI_COLORS[color] + text + ANSI_COLORS['normal'] ;
  30.     }
  31.    
  32.     process.stdout.write('['+date+'] ' + text + '\n');
  33. }
  34.  
  35. function RconService(rconData) {
  36.     var me = this;
  37.     var WebSocket = require('ws');
  38.    
  39.     var States = {
  40.         eCLOSED:0,
  41.         eOPENED:1,
  42.         eCONNECTING:2
  43.     };
  44.    
  45.     this.rconData = rconData;
  46.    
  47.     this.state = States.eCLOSED;
  48.     this.identifier = 0;
  49.     this.listeners = {};
  50.     this.commandQueue = [];
  51.    
  52.     this.Connect = function() {
  53.         log("Connecting");
  54.         this.state = States.eCONNECTING;
  55.        
  56.         this.ws = new WebSocket( "ws://" + this.rconData.addr + ":" + this.rconData.port + "/" + this.rconData.pass );
  57.        
  58.         this.ws.on('open', function () {
  59.             log("Connected", 'green');
  60.             me.state = States.eOPENED;
  61.             while(command = me.commandQueue.shift()) {
  62.                 me.Command(command.msg, command.callBack)
  63.             }
  64.         });
  65.        
  66.         this.ws.on('close', function () {
  67.             if(me.rconData.noRetry) {
  68.                 log("Disconnected", 'red');
  69.                 process.exit(1);
  70.             } else {
  71.                 log("Disconnected, retrying in 2s", 'red');
  72.                 me.state = States.eCLOSED;
  73.                 setTimeout(function() { me.Connect() }, 2000);
  74.             }
  75.         });
  76.        
  77.         this.ws.on('message', function (data, flags) {
  78.             me.OnMessage( JSON.parse( data ) );
  79.         });
  80.        
  81.         this.ws.on('error', function (err) {
  82.             if(me.rconData.noRetry) {
  83.                 log(err, 'hred');
  84.                 process.exit(1);
  85.             } else {
  86.                 log(err+" retrying in 10s", 'hred');
  87.                 me.state = States.eCLOSED;
  88.                 setTimeout(function() { me.Connect() }, 10000);
  89.             }
  90.         });
  91.     };
  92.    
  93.     this.Command = function(msg, callBack) {
  94.        
  95.         if(this.state == States.eCLOSED)
  96.             this.Connect();
  97.        
  98.         if(this.state == States.eOPENED) {
  99.             var packet = {
  100.                     Identifier: this.identifier,
  101.                     Message: msg,
  102.                     Type: "3"
  103.                 };
  104.            
  105.             if(callBack != null)
  106.                 this.listeners[this.identifier] = callBack
  107.            
  108.             this.identifier += 1;
  109.        
  110.             this.ws.send( JSON.stringify( packet ) );
  111.         } else {
  112.             this.commandQueue.push({msg:msg, callBack:callBack});
  113.         }
  114.     };
  115.    
  116.     this.OnMessage = function(data) {
  117.         if(data.Identifier in me.listeners && me.listeners[data.Identifier] != null) {
  118.             me.listeners[data.Identifier](data.Message);
  119.             me.listeners[data.Identifier] = null;
  120.         } else if(this.defaultListener != null) {
  121.             this.defaultListener(data.Message);
  122.         }
  123.     };
  124. }
  125.  
  126. var rcon = null;
  127.  
  128. function RunCommand(command, callback)
  129. {  
  130.     if(rcon == null) {
  131.         rcon = new RconService(rconData);
  132.     }
  133.    
  134.     if(callback != null)
  135.         rcon.Command(command, callback);
  136.     else
  137.         rcon.Command(command, function(response) {log(response)});
  138. }
  139.  
  140. function RunCommandOnce(command)
  141. {
  142.     if(rcon == null) {
  143.         rcon = new RconService(rconData);
  144.     }
  145.    
  146.     rcon.Command(command, function(response) {log(response); process.exit()});
  147. }
  148.  
  149. clientdataRE  = new RegExp(/^([0-9.]{7,15})\:([0-9]*)\/([0-9]*)\/(.*)/);
  150. killedRE      = new RegExp(/^(.+?)\[[0-9]+\/[0-9]+\] was killed by (.+?)\[[0-9]+\/[0-9]+\]/);
  151. killedNpcRE   = new RegExp(/^(.+?)\[[0-9]+\/[0-9]+\] was killed by (.+?)\.prefab \((\w+)\)/);
  152. diedRE        = new RegExp(/^(.+?)\[[0-9]+\/[0-9]+\] died \((\w+)\)/);
  153. diedRE2       = new RegExp(/^(.+?)\[[0-9]+\/[0-9]+\] was killed by (\w+)/);
  154.  
  155. function logRconData(msg) {
  156.    
  157.     if((data = clientdataRE.exec(msg))) {
  158.         var remainder = data[4];
  159.        
  160.         if(/.* joined \[.*\//.test(remainder)) {
  161.             log(msg, 'hgreen');
  162.            
  163.         } else if (/.* kicked\: .*/.test(remainder)) {
  164.             log(msg, 'yellow');
  165.            
  166.         } else if (/.* Rejecting connection \- .*/.test(remainder)) {
  167.             log(msg, 'yellow');
  168.            
  169.         } else if (/.* disconnecting\: {0,1}.*/.test(remainder)) {
  170.             log(msg, 'green');
  171.        
  172.         } else {
  173.             log(msg, 'hblue');
  174.         }
  175.     } else if (/^\[CHAT\]/.test(msg)) {
  176.         log(msg, 'hcyan');
  177.        
  178.     } else if (/^\[event\]/.test(msg)) {
  179.         log(msg, 'magenta');
  180.        
  181.     } else if((names = killedRE.exec(msg))) {
  182.         log(msg, 'hyellow');
  183.        
  184.         if(rconData.killFeed) {
  185.             log('ECHOED KILL ' + names[2] + ' a butté ' + names[1], 'yellow');
  186.             rcon.Command('say <color=red>' + names[2] + '</color><color=green> a butté </color><color=red>' + names[1] + '</color> ');
  187.         }
  188.        
  189.     } else if((names = killedNpcRE.exec(msg))) {
  190.         log(msg, 'yellow');
  191.        
  192.         if(rconData.killFeed) {
  193.             var entity = names[2];
  194.             var npc = names[3];
  195.            
  196.             var reason = ' a butté ';
  197.            
  198.             if(npc == 'wolf') {
  199.                 npc = 'Un loup';
  200.                 reason = ' a bouffé ';
  201.                
  202.             } else if(npc == 'bear') {
  203.                 npc = 'Un ours';
  204.                 reason = ' a bouffé ';
  205.                
  206.             } else if(npc == 'entity') {
  207.                 if(
  208.                     entity == 'barricade.wood'          ||
  209.                     entity == 'barricade.woodwire'      ||
  210.                     entity == 'wall.external.high.wood' ||
  211.                     entity == 'wall.external.high.stone'||
  212.                     entity == 'gate.external.high.wood' ||
  213.                     entity == 'gate.external.high.stone'
  214.                 ) {
  215.                     npc = 'Des fils barbelés';
  216.                     reason = ' ont déchiré ';
  217.                    
  218.                 } else if(entity == 'beartrap') {
  219.                     npc = 'Un piège à ours';
  220.                     reason = ' a broyé ';
  221.                    
  222.                 } else if(entity == 'landmine') {
  223.                     npc = 'Une mine';
  224.                     reason = ' a explosé '
  225.                    
  226.                 } else if(entity == 'spikes.floor') {
  227.                     npc = 'Des pieux';
  228.                     reason = ' ont empalé ';
  229.                    
  230.                 } else if(entity == 'patrolhelicopter') {
  231.                     npc = 'L\'hélicoptère';
  232.                     reason = ' a éclaté ';
  233.                    
  234.                 } else if(entity == 'lock.code') {
  235.                     npc = 'Un verrou';
  236.                     reason = ' a electrocuté ';
  237.                    
  238.                 } else if(entity == 'autoturret') {
  239.                     npc = 'Une tourelle';
  240.                     reason = ' a mitraillé ';
  241.                    
  242.                 } else {
  243.                     npc = entity;
  244.                 }
  245.                
  246.                
  247.             }
  248.            
  249.             log('ECHOED KILL ' + npc + reason + names[1], 'yellow');
  250.             rcon.Command('say <color=green>' + npc + reason + '</color> <color=red>' + names[1] + '</color>');
  251.         }
  252.     } else if ((names = diedRE.exec(msg)) || (names = diedRE2.exec(msg))) {
  253.         log(msg, 'yellow');
  254.        
  255.         if(rconData.killFeed) {
  256.             var reason = names[2];
  257.             if(reason == 'Bite') {
  258.                 reason = ' s\'est fait bouffé';
  259.                
  260.             } else if (reason == 'Cold') {
  261.                 reason = ' est devenu un glaçon';
  262.                
  263.             } else if (reason == 'Bullet') {
  264.                 reason = ' a pris une balle et en est mort';
  265.                
  266.             } else if (reason == 'Blunt') {
  267.                 reason = ' a explosé';
  268.                
  269.             } else if (reason == 'Fall') {
  270.                 reason = ' a sauté d\'un peu trop haut';
  271.                
  272.             } else if (reason == 'Drowned') {
  273.                 reason = ' s\'est noyé';
  274.                
  275.             } else if (reason == 'Bleeding') {
  276.                 reason = ' s\'est vidé de son sang';
  277.                
  278.             } else if (reason == 'Poison') {
  279.                 reason = ' aurait du passer chez le pharmacien avant de manger';
  280.                
  281.             } else if (reason == 'Thirst' || reason == 'Hunger') {
  282.                 reason = ' a oublié de manger';
  283.                
  284.             } else if (reason == 'Radiation') {
  285.                 reason = ' a pris trop de Becquerel';
  286.                
  287.             } else if (reason == 'Suicide') {
  288.                 return;
  289.                
  290.             } else {
  291.                 reason = ' et mort de ' + names[2];
  292.             }
  293.            
  294.             log('ECHOED KILL ' + names[1] + reason, 'yellow');
  295.             rcon.Command('say <color=red>' + names[1] + '</color><color=green>' + reason + '</color>');
  296.         }
  297.        
  298.     } else {
  299.         log(msg);
  300.     }
  301. }
  302.  
  303. function autoCompleterQuery(line, callback) {
  304.     autoCompleterCurrentLinePartial = line;
  305.     autoCompleterCurrentCallBack = callback;
  306.     var findItem = null;
  307.     var findFunction = null;
  308.    
  309.     if(/^\s*$/.test(line)) {
  310.         autoCompleterCurrentRegExp      = '\\n ((?:[\\w]+\\.)?'+autoCompleterCurrentLinePartial+'[\\w\\.]*)';
  311.         findFunction    = 'find ';
  312.         findItem        = '.';
  313.    
  314.     } else if(/^[\w\.]+$/.test(line)) {
  315.         autoCompleterCurrentRegExp      = '\\n ((?:[\\w]+\\.)?'+autoCompleterCurrentLinePartial+'[\\w\\.]*)';
  316.         findFunction    = 'find ';
  317.         findItem        = line;
  318.    
  319.     } else if(matches = /^([\w\.]+)\s*("\.*)$/.exec(line)) {
  320.         autoCompleterCurrentRegExp      = '\\n\\d+ ('+matches[2]+'\\.*")';
  321.         autoCompleterCurrentLinePartial = matches[2];
  322.         findFunction    = 'status';
  323.         findItem        = '';
  324.     } else if(matches = /^([\w\.]+)\s*(\d*)$/.exec(line)) {
  325.         autoCompleterCurrentRegExp      = '\\n('+matches[2]+'\\d*)\\s';
  326.         autoCompleterCurrentLinePartial = matches[2];
  327.         findFunction    = 'status';
  328.         findItem        = '';
  329.     }
  330.    
  331.     if(findFunction)
  332.         RunCommand(findFunction + findItem, autoCompleterQueryCallback);
  333.     else
  334.         callback(null, [[], line]);
  335. }
  336.  
  337. function autoCompleterQueryCallback(msg) {
  338.     var re = new RegExp(autoCompleterCurrentRegExp, 'gi');
  339.     var result = msg.match(re);
  340.     autoCompleterCurrentCallBack(null, [result, autoCompleterCurrentLinePartial]);
  341. }
  342.  
  343. var program = require('commander');
  344. program
  345.     .usage('[command]')
  346.     .option('-a, --address <address>', 'The the RCON server address')
  347.     .option('-p, --port <port>', 'The the RCON server port')
  348.     .option('-P, --password <password>', 'The RCON server password')
  349.     .option('-k, --kill-feed', 'Kill Feed')
  350.     .option('-x, --no-retry', 'Disable retry')
  351.     .parse(process.argv);
  352.  
  353. if (!program.address || !program.port || !program.password) {
  354.   program.outputHelp();
  355.   process.exit(1);
  356. }
  357.  
  358. rconData = {};
  359. rconData.addr       = program.address;
  360. rconData.port       = program.port;
  361. rconData.pass       = program.password;
  362. rconData.noRetry    = program.noRetry;
  363. rconData.killFeed   = program.killFeed;
  364.  
  365. if(program.args && program.args != "") {
  366.     log("Sending command: " + program.args.join(' '));
  367.     RunCommandOnce(program.args.join(' '));
  368. } else {
  369.     rcon = new RconService(rconData);
  370.     rcon.defaultListener = function(msg) {logRconData(msg)};
  371.     rcon.Connect();
  372.    
  373.     var readline = require('readline');
  374.     var rl = readline.createInterface({
  375.       input: process.stdin,
  376.       output: process.stdout,
  377.       completer: autoCompleterQuery,
  378.       terminal: true
  379.     });
  380.     rl.on('line', function(l) {
  381.         if(l != "") {
  382.             log("Sending command: " + l, 'hwhite');
  383.             RunCommand(l)
  384.         }
  385.     });
  386. }
Advertisement
Add Comment
Please, Sign In to add comment