Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- nodejs IRC class by Matthew Ryan www.haxed.net
- Released under GNU General Public License v3.0
- */
- const net = require( 'net' );
- function irc( e ){
- if( !e ) return { authType: { none: 0, nickServ: 1, saslPlain: 2 } };
- if( !e.server || !e.server.address || !e.server.port ) throw("invalid or missing server information");
- if( !e.userInfo || !e.userInfo.nick ) throw("invalid or missing user information");
- e.userInfo.username = e.userInfo.username || "default";
- e.userInfo.auth = e.userInfo.auth || { type: "none" };
- this.server = e.server;
- this.userInfo = e.userInfo;
- this.channels = e.channels || [];
- this.options = e;
- this.connected = false;
- this.cache = ""; /* a place to store data until we need it */
- this.onConnect = function( e ){};
- this.onDisconnect = function( e ){};
- this.onData = function( e ){};
- this.onPrivmsg = function( e ){};
- this.onNotice = function( e ){};
- this.onNumeric = function( e ){};
- this.onNickChanged = function( e ){};
- this.onModeChanged = function( e ){};
- this.onConnected = function( e ){};
- this.onChannelJoined = function( e ){};
- this.onChannelLeft = function( e ){};
- this.onUserJoined = function( e ){};
- this.onUserLeft = function( e ){};
- this.onUserQuit = function( e ){};
- this.onUserKicked = function( e ){};
- this.serverOptions = {
- channelModes: [ "b", "k", "l", "imnpstr" ],
- prefix: [ "ov", "@+" ]
- };
- const me = this;
- /* now lets make a tcp socket */
- this.client = new net.Socket();
- this.client.connect(e.server.port, e.server.address, function() {
- me.connected = true;
- me.onConnect();
- /* let's register */
- if( me.server.password ) me.sendData( "PASS :" + me.server.password );
- me.sendData( "NICK " + me.userInfo.nick );
- me.sendData( "USER " + me.userInfo.username + " * * :" + me.userInfo.username );
- });
- this.client.on('data', function(data) {
- me.cache += data.toString().replace( /\r/i, "" );
- if( me.cache.substr(me.cache.length - 1) == "\n" ) {
- const databits = me.cache.split( "\n" );
- for( let i in databits ) {
- if( databits[i].length > 0 ){
- me.onData( databits[i] );
- me.parseData( databits[i] );
- }
- }
- me.cache = "";
- }
- });
- this.client.on('close', function(e) {
- if( me.connected ) me.onDisconnect({ code: 0, message: "socket closed" });
- me.connected = false;
- });
- this.client.on('error', function(e) {
- me.onDisconnect({ code: 2, message: e.code });
- me.connected = false;
- });
- }
- irc.prototype.quit = function(e){
- this.sendData( "QUIT :" + e );
- }
- irc.prototype.setModes = function( e ){
- /* irc.setMode({ for: "#channel", modes: {add: [{ mode: "k", value: "key" }] } }); */
- let str = "MODE " + e.for + " ";
- let amodes = ""; /* modes to add */
- let rmodes = ""; /* modes to remove */
- let vals = ""; /* mode values */
- for( let i in e.modes ) {
- let m = e.modes[i]; /* working mode */
- if(m.state == "add"){
- if( amodes == "" ) amodes = "+";
- amodes += m.mode;
- }else{
- if( rmodes == "" ) rmodes = "-";
- rmodes += m.mode;
- }
- if( m.value != undefined ) vals += (" " + m.value);
- }
- this.sendData( str + amodes + rmodes + vals );
- }
- irc.prototype.parseData = function( e ){
- e = e.replace( /(\r|\n)/g, "" );
- if( e.substr(0,1) != ":" ) e = ":server " + e;
- const bits = e.split( " " );
- const me = this;
- let cMsg = "";
- if( bits.length > 2 ) {
- if( e.indexOf(" :") > 1 ) cMsg = e.substr( e.indexOf( " :" ) + 2 );
- if( isNaN( parseInt( bits[1] ) ) ) {
- /* it's a numeric ! */
- this.onNumeric( { number: parseInt( bits[1] ), data: e } );
- }
- switch( bits[1].toUpperCase() ) {
- case "001":
- this.onConnected();
- switch( this.userInfo.auth.type ) {
- case 1:
- /* nickserv */
- this.sendData( "NICKSERV IDENTIFY " + this.userInfo.auth.user + " " + this.userInfo.auth.password );
- break;
- }
- setTimeout(function(){
- const tj = [];
- if( me.channels.length > 0 ) {
- for(let i in me.channels){
- let cstr = me.channels[i].name;
- if( me.channels[i].key ) cstr += " " + me.channels[i].key;
- tj.push( cstr );
- if( tj.length == 10 ) {
- me.sendData( "JOIN " + tj.toString() );
- tj = [];
- }
- }
- me.sendData( "JOIN " + tj.toString() );
- }
- },10000);
- break;
- case "JOIN":
- if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
- this.onChannelJoined( { channel: bits[2] } );
- }else{
- this.onUserJoined( { channel: bits[2], user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1) } );
- }
- break;
- case "PART":
- if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
- this.onChannelLeft( { channel: bits[2] } );
- }else{
- this.onUserLeft( { channel: bits[2], user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1), message: cMsg } );
- }
- break;
- case "QUIT":
- if( parseUser( bits[0] ).nick == this.userInfo.nick ){
- this.connected = false;
- this.client.close();
- this.onDisconnect({ code: 1, message: "quit from server" });
- }else{
- this.onUserQuit( { user: parseUser( bits[0] ).nick, hostInfo: bits[0].substr(1), message: cMsg } );
- }
- break;
- case "KICK":
- this.onUserKicked({ channel: bits[2], user: bits[3], kicker: parseUser( bits[0] ).nick, reason: cMsg });
- break;
- case "MODE":
- const modeObj = {
- for: bits[2],
- modes: []
- };
- const modeStr = e.substr( bits[0].length + bits[1].length + bits[2].length + 3 );
- const vals = modeStr.split( " " );
- const modesWithVals = "ovbqkl";
- let wv = "add"; /* working value for a mode */
- let modes = modeStr.split( " " )[0].split( "" );
- vals.splice( 0, 1 );
- for( let i in modes ){
- if( modes[i] == "+" ){
- wv = "add";
- }else if( modes[i] == ":" ){
- }else if( modes[i] == "-" ){
- wv = "remove";
- }else{
- let mVal = "";
- 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) ){
- mVal = vals[0];
- vals.splice( 0, 1 );
- }
- modeObj.modes.push({ state: wv, mode: modes[i], value: mVal });
- }
- }
- this.onModeChanged( modeObj );
- break;
- case "NICK":
- this.onNickChanged({ old: parseUser( bits[0] ).nick, new: bits[2].replace( ":", "" ) });
- if( parseUser( bits[0] ).nick.toLowerCase() == this.userInfo.nick.toLowerCase() ){
- /* it's us! let's update our nick */
- this.userInfo.nick = bits[2].replace( ":", "" );
- }
- break;
- case "NOTICE":
- this.onNotice({ from: parseUser( bits[0] ).nick, to: bits[2], message: cMsg, hostInfo: bits[0].substr(1) });
- break;
- case "PRIVMSG":
- this.onPrivmsg({ from: parseUser( bits[0] ).nick, to: bits[2], message: cMsg, hostInfo: bits[0].substr(1) });
- break;
- case "PING":
- this.sendData( "PONG " + bits[2] );
- break;
- }
- }
- function parseUser( e ) {
- e = e.replace( ":", "" );
- e = e.replace( "@", "!" ).split( "!" );
- return { nick: e[0], user: e[1], host: e[2] };
- }
- }
- irc.prototype.sendData = function( e ){
- this.client.write( e + "\r\n" );
- }
- irc.prototype.sendPrivmsg = function( e ){
- this.sendData( "PRIVMSG " + e.to + " :" + e.message );
- }
- module.exports = irc;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement