Advertisement
Guest User

Untitled

a guest
Aug 25th, 2017
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     nodejs IRC class by Matthew Ryan www.haxed.net
  3.     Released under GNU General Public License v3.0
  4.    
  5. */
  6.  
  7.  
  8. const net = require( 'net' );
  9.  
  10. function irc( e ){
  11.     if( !e ) return { authType: { none: 0, nickServ: 1, saslPlain: 2 } };
  12.    
  13.     if( !e.server || !e.server.address || !e.server.port ) throw("invalid or missing server information");
  14.    
  15.     if( !e.userInfo || !e.userInfo.nick ) throw("invalid or missing user information");
  16.    
  17.     e.userInfo.username = e.userInfo.username || "default";
  18.     e.userInfo.auth = e.userInfo.auth || { type: "none" };
  19.    
  20.    
  21.     this.server = e.server;
  22.     this.userInfo = e.userInfo;
  23.     this.channels = e.channels || [];
  24.     this.options = e;
  25.     this.connected = false;
  26.    
  27.     this.cache = ""; /* a place to store data until we need it */
  28.    
  29.     this.onConnect = function( e ){};
  30.     this.onDisconnect = function( e ){};
  31.     this.onData = function( e ){};
  32.     this.onPrivmsg = function( e ){};
  33.     this.onNotice = function( e ){};
  34.     this.onNumeric = function( e ){};
  35.     this.onNickChanged = function( e ){};
  36.     this.onModeChanged = function( e ){};
  37.     this.onConnected = function( e ){};
  38.     this.onChannelJoined = function( e ){};
  39.     this.onChannelLeft = function( e ){};
  40.    
  41.     this.onUserJoined = function( e ){};
  42.     this.onUserLeft = function( e ){};
  43.     this.onUserQuit = function( e ){};
  44.     this.onUserKicked = function( e ){};
  45.    
  46.     this.serverOptions = {
  47.         channelModes: [ "b", "k", "l", "imnpstr" ],
  48.         prefix: [ "ov", "@+" ]
  49.     };
  50.    
  51.     const me = this;
  52.    
  53.     /* now lets make a tcp socket */
  54.     this.client = new net.Socket();
  55.     this.client.connect(e.server.port, e.server.address, function() {
  56.         me.connected = true;
  57.         me.onConnect();
  58.         /* let's register */
  59.         if( me.server.password ) me.sendData( "PASS :" + me.server.password );
  60.         me.sendData( "NICK " + me.userInfo.nick );
  61.         me.sendData( "USER " + me.userInfo.username + " * * :" + me.userInfo.username  );
  62.     });
  63.     this.client.on('data', function(data) {
  64.         me.cache += data.toString().replace( /\r/i, "" );
  65.         if( me.cache.substr(me.cache.length - 1) == "\n" ) {
  66.             const databits = me.cache.split( "\n" );
  67.             for( let i in databits ) {
  68.                 if( databits[i].length > 0 ){
  69.                     me.onData( databits[i] );
  70.                     me.parseData( databits[i] );
  71.                 }
  72.             }
  73.             me.cache = "";
  74.         }
  75.     });
  76.     this.client.on('close', function(e) {
  77.         if( me.connected ) me.onDisconnect({ code: 0, message: "socket closed" });
  78.         me.connected = false;
  79.     });
  80.     this.client.on('error', function(e) {
  81.         me.onDisconnect({ code: 2, message: e.code });
  82.         me.connected = false;
  83.     });
  84. }
  85.  
  86. irc.prototype.quit = function(e){
  87.     this.sendData( "QUIT :" + e );
  88. }
  89.  
  90. irc.prototype.setModes = function( e ){
  91.     /* irc.setMode({ for: "#channel", modes: {add: [{ mode: "k", value: "key" }] } }); */
  92.     let str = "MODE " + e.for + " ";
  93.     let amodes = ""; /* modes to add */
  94.     let rmodes = ""; /* modes to remove */
  95.     let vals = ""; /* mode values */
  96.     for( let i in e.modes ) {
  97.         let m = e.modes[i]; /* working mode */
  98.         if(m.state == "add"){
  99.             if( amodes == "" ) amodes = "+";
  100.             amodes +=  m.mode;
  101.         }else{
  102.             if( rmodes == "" ) rmodes = "-";
  103.             rmodes +=  m.mode;
  104.         }
  105.         if( m.value != undefined ) vals += (" " + m.value);
  106.     }
  107.     this.sendData( str + amodes + rmodes + vals );
  108. }
  109.  
  110. irc.prototype.parseData = function( e ){
  111.     e = e.replace( /(\r|\n)/g, "" );
  112.     if( e.substr(0,1) != ":" ) e = ":server " + e;
  113.     const bits = e.split( " " );
  114.     const me = this;
  115.     let cMsg = "";
  116.    
  117.     if( bits.length > 2 ) {
  118.    
  119.         if( e.indexOf(" :") > 1 ) cMsg = e.substr( e.indexOf( " :" ) + 2 );
  120.        
  121.         if( isNaN( parseInt( bits[1] ) ) ) {
  122.             /* it's a numeric ! */
  123.             this.onNumeric( { number: parseInt( bits[1] ), data: e } );
  124.         }
  125.        
  126.         switch( bits[1].toUpperCase() ) {
  127.            
  128.             case "001":
  129.                 this.onConnected();
  130.                 switch( this.userInfo.auth.type ) {
  131.                     case 1:
  132.                         /* nickserv */
  133.                         this.sendData( "NICKSERV IDENTIFY " + this.userInfo.auth.user + " " + this.userInfo.auth.password );
  134.                         break;
  135.                 }
  136.                
  137.                 setTimeout(function(){
  138.                     const tj = [];
  139.                     if( me.channels.length > 0 ) {
  140.                         for(let i in me.channels){
  141.                             let cstr = me.channels[i].name;
  142.                             if( me.channels[i].key ) cstr += " " + me.channels[i].key;
  143.                             tj.push( cstr );
  144.                             if( tj.length == 10 ) {
  145.                                 me.sendData( "JOIN " + tj.toString() );
  146.                                 tj = [];
  147.                             }
  148.                         }
  149.                         me.sendData( "JOIN " + tj.toString() );
  150.                     }
  151.                 },10000);
  152.  
  153.                 break;
  154.                
  155.             case "JOIN":
  156.                 if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
  157.                     this.onChannelJoined( { channel: bits[2] } );
  158.                 }else{
  159.                     this.onUserJoined( { channel: bits[2], user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1) } );
  160.                 }
  161.                 break;
  162.                
  163.             case "PART":
  164.                 if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
  165.                     this.onChannelLeft( { channel: bits[2] } );
  166.                 }else{
  167.                     this.onUserLeft( { channel: bits[2], user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1), message: cMsg } );
  168.                 }
  169.                 break;
  170.                
  171.             case "QUIT":
  172.                 if( parseUser( bits[0] ).nick == this.userInfo.nick ){
  173.                     this.connected = false;
  174.                     this.client.close();
  175.                     this.onDisconnect({ code: 1, message: "quit from server" });
  176.                 }else{
  177.                     this.onUserQuit( { user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1), message: cMsg } );
  178.                 }
  179.                 break;
  180.             case "KICK":
  181.                 this.onUserKicked({ channel: bits[2], user: bits[3], kicker: parseUser( bits[0] ).nick, reason: cMsg });
  182.                 break;
  183.             case "MODE":
  184.                 const modeObj = {
  185.                     for: bits[2],
  186.                     modes: []
  187.                 };
  188.                
  189.                 const modeStr = e.substr( bits[0].length + bits[1].length + bits[2].length + 3 );
  190.                 const vals = modeStr.split( " " );
  191.                 const modesWithVals = "ovbqkl";
  192.                 let wv = "add"; /* working value for a mode */
  193.                 let modes = modeStr.split( " " )[0].split( "" );
  194.                
  195.                 vals.splice( 0, 1 );
  196.  
  197.                 for( let i in modes ){
  198.                     if( modes[i] == "+" ){
  199.                         wv = "add";
  200.                     }else if( modes[i] == ":" ){
  201.                     }else if( modes[i] == "-" ){
  202.                         wv = "remove";
  203.                     }else{
  204.                         let mVal = "";
  205.                         if( vals.length > 0 && (this.serverOptions.channelModes[0].indexOf( modes[i] ) > -1 || this.serverOptions.channelModes[1].indexOf( modes[i] ) > -1 || this.serverOptions.prefix[0].indexOf( modes[i] ) > -1) ){
  206.                             mVal = vals[0];
  207.                             vals.splice( 0, 1 );
  208.                         }
  209.                         modeObj.modes.push({ state: wv, mode: modes[i], value: mVal });
  210.                     }
  211.                 }
  212.                
  213.                 this.onModeChanged( modeObj );
  214.                 break;
  215.             case "NICK":
  216.                 this.onNickChanged({ old: parseUser( bits[0] ).nick, new: bits[2].replace( ":", "" ) });
  217.                 if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
  218.                     /* it's us! let's update our nick */
  219.                     this.userInfo.nick = bits[2].replace( ":", "" );
  220.                 }
  221.                 break;
  222.             case "NOTICE":
  223.                 this.onNotice({ from:  parseUser( bits[0] ).nick, to: bits[2], message: cMsg, hostInfo: bits[0].substr(1) });
  224.                 break;
  225.                
  226.             case "PRIVMSG":
  227.                 this.onPrivmsg({ from:  parseUser( bits[0] ).nick, to: bits[2], message: cMsg, hostInfo: bits[0].substr(1) });
  228.                 break;
  229.                
  230.             case "PING":
  231.                 this.sendData( "PONG " + bits[2] );
  232.                 break;
  233.         }
  234.    
  235.     }
  236.    
  237.     function parseUser( e ) {
  238.         e = e.replace( ":", "" );
  239.         e = e.replace( "@", "!" ).split( "!" );
  240.         return { nick: e[0], user: e[1], host: e[2] };
  241.     }
  242.    
  243. }
  244.  
  245. irc.prototype.sendData = function( e ){
  246.     this.client.write( e + "\r\n" );
  247. }
  248.  
  249. irc.prototype.sendPrivmsg = function( e ){
  250.     this.sendData( "PRIVMSG " + e.to + " :" + e.message );
  251. }
  252.  
  253. module.exports = irc;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement