/// <summary> /// Default WhoHandler. Simply makes sure all the users on the channel have /// valid masks and are known about. /// </summary> /// <param name="serverid">The server id.</param> /// <param name="c">The channel queried.</param> /// <param name="user">The user parsed.</param> /// <returns>The commands to execute.</returns> /*public static string[] WhoHandler(int serverid, Channel c, IRCHost user) { Server s = Server.GetServer( serverid ); User u = null; try { u = s.UserDatabase[user.Nick]; } catch ( KeyNotFoundException ) { u = new User( user ); s.UserDatabase.AddUser( u ); s.UserDatabase.Authenticate( u ); } ChannelUser cu = null; try { cu = c[user.Nick]; cu.InternalUser = u; } catch ( KeyNotFoundException ) { //THIS SHOULD NEVER HAPPEN DO NOTHING. } return null; }*/ /// <summary> /// Default AuthModeHandler function. /// </summary> /// <param name="sid">The serverid of the event.</param> /// <param name="nick">The nickname of the user the message was sent to.</param> /// <param name="userhost">The userhost of the user the message was sent from.</param> /// <param name="text">The text the user wrote.</param> public static string[] AuthModeHandler(int sid, string nick, User userhost, string text) { Server s = Server.GetServer( sid ); if ( s.IsInAuthMode && s.CurrentNickName == nick ) { Project2Q.SDK.UserSystem.RegisteredUser ru = new Project2Q.SDK.UserSystem.RegisteredUser(); ru.HostList.Add( new Project2Q.SDK.UserSystem.IRCHost( userhost.CurrentHost.FullHost ) ); ru.Privegeles.SetPriveleges( Project2Q.SDK.UserSystem.Priveleges.SuperUser ); ru.Privegeles.NumericalLevel = 1000; s.UserDatabase.AddRegisteredUser( ru ); s.UserDatabase.Authenticate( userhost ); s.ExitAuthMode(); } return null; }
/// <summary> /// Default ServerMode handler. Used to collect bot modes. /// </summary> /// <param name="serverId">The server id.</param> /// <param name="u">The user that was altered (should normally be us).</param> /// <param name="recipient">The recipient of the mode.</param> /// <param name="modestring">The modes applied.</param> /// <returns></returns> public static string[] ServerModeMessageHandler(int serverId, User u, string recipient, string modestring) { Server s = Server.GetServer( serverId ); if ( s.CurrentIP == null && s.CurrentNickName == recipient ) { //We can try to dns the user hostname to retrieve our IP. IPAddress[] ips = Dns.GetHostAddresses( u.Hostname ); //Should only ever be one -_- if ( ips.Length > 0 ) s.CurrentIP = ips[0]; } return null; }
/// <summary> /// Fires the OnServerModeMessage event. /// </summary> /// <param name="sid">The server id.</param> /// <param name="c">The channel.</param> /// <returns>The raw data to be sent to the server.</returns> public string[] OnServerModeMessage(int sid, User u, string recipient, string modes) { if ( ServerModeMessage == null ) return null; ServerModeMessageEvent umme = new ServerModeMessageEvent(); umme.sid = sid; umme.user = u; umme.modes = modes; umme.receiver = recipient; return InvocationTunnel( ServerModeMessage.GetInvocationList(), umme, "onServerModeData" ); }
/// <summary> /// Fires the UserMessage event. /// </summary> /// <param name="sid">Server id.</param> /// <param name="nick">The nick the message was sent to.</param> /// <param name="userhost">The userhost of the user who sent it.</param> /// <param name="text">The text contained in the message.</param> /// <returns>Raw data.</returns> public string[] OnUserMessage(int sid, string nick, User userhost, string text) { if (UserMessage == null) return null; UserMessageEvent ue = new UserMessageEvent(); ue.sid = sid; ue.sender = userhost; ue.receiver = nick; ue.text = text; return InvocationTunnel(UserMessage.GetInvocationList(), ue, "userMessageData", ( userhost.UserAttributes == null ) ? null : userhost.UserAttributes.Privegeles ); }
/// <summary> /// Fires UserNotice Event /// </summary> /// <param name="sid">ServerID</param> /// <param name="user">The user who sent the message</param> /// <param name="text">The text the user sent</param> /// <returns>The raw data to be sent to the server</returns> public string[][] OnPrivateNotice( int sid, User user, string text ) { if ( PrivateNotice != null ) return InvocationTunnel( this.PrivateNotice.GetInvocationList(), user.UserAttributes == null ? null : user.UserAttributes.Privegeles, sid, user, text ); return null; }
/// <summary> /// Fires the OnQuit event. /// </summary> /// <param name="sid"></param> /// <param name="u">The user that quit.</param> /// <param name="message">The message sent to the server.</param> /// <returns>The raw data to be sent to the server.</returns> public string[] OnQuit(int sid, User u, string message) { if ( Quit == null ) return null; QuitEvent qe = new QuitEvent(); qe.serverId = sid; qe.u = u; qe.message = message; return InvocationTunnel( BotJoin.GetInvocationList(), qe, "onQuitData" ); }
/// <summary> /// Fires the ChannelNotice event. /// </summary> /// <param name="sid">Server ID</param> /// <param name="channel">Channel on which the notice was sent to</param> /// <param name="user">User who sent the notice</param> /// <param name="text">/text that was in the notice</param> /// <returns>Raw data.</returns> public string[] OnChannelNotice( int sid, Channel channel, User user, string text ) { if ( ChannelNotice == null ) return null; ChannelNoticeEvent cn = new ChannelNoticeEvent(); cn.sid = sid; cn.channel = channel; cn.user = user; cn.text = text; return InvocationTunnel( ChannelNotice.GetInvocationList(), cn, "channelNoticeData", ( user.UserAttributes == null ) ? null : user.UserAttributes.Privegeles ); }
/// <summary> /// Invokes the Parsers. /// </summary> /// <param name="s">The server object.</param> /// <param name="c">The channel triggered on.</param> /// <param name="u">The user triggered from.</param> /// <param name="cu">The channeluser triggered from.</param> /// <param name="text">The offending text.</param> /// <param name="pt">The Parse Types to invoke on.</param> private static void InvokeParsers(Server s, Channel c, User u, ChannelUser cu, string text, IRCEvents.ParseTypes pt) { bool pcount = s.EventObject.Parses.Count > 0; bool wcount = s.EventObject.WildcardParses.Count > 0; if ( pcount || wcount ) { IRCEvents.ParseReturns pr = CreateParseReturns( s.ServerID, c, u, cu, text ); if ( pcount ) s.QueueData( ParseInvocation( pr.Text, s.EventObject, pr, pt, false ) ); if ( wcount ) s.QueueData( ParseInvocation( pr.Text, s.EventObject, pr, pt, true ) ); } }
/// <summary> /// Creates a channeluser with an internal user and a flag. /// </summary> /// <param name="u"></param> /// <param name="flag"></param> public ChannelUser(User u, Nullable<char> flag) { internalUser = u; userFlag = flag; }
/// <summary> /// Creates a channeluser with everything nulled. /// </summary> public ChannelUser() { internalUser = null; userFlag = null; }
/// <summary> /// Fires UserMessage Event /// </summary> /// <param name="sid">Server ID</param> /// <param name="nick">The nick who the message was destined for.</param> /// <param name="userhost">The userhost of the sender.</param> /// <param name="text">The contents of the message.</param> /// <returns>The raw data to be sent to the server.</returns> public string[][] OnUserMessage(int sid, string nick, User user, string text) { if ( UserMessage != null ) { return InvocationTunnel(this.UserMessage.GetInvocationList(), user.UserAttributes == null ? null : user.UserAttributes.Privegeles, sid, nick, user, text); } return null; }
/// <summary> /// Fires the OnServerModeMessage event. /// </summary> /// <param name="sid">The server id.</param> /// <param name="c">The channel.</param> /// <returns>The raw data to be sent to the server.</returns> public string[][] OnServerModeMessage(int sid, User u, string recipient, string modes) { if ( ServerModeMessage != null ) return InvocationTunnel( this.ServerModeMessage.GetInvocationList(), sid, u, recipient, modes); return null; }
/// <summary> /// Fires the Quit event. /// </summary> /// <param name="sid">The server on which the quit happened.</param> /// <param name="u">The user that quit.</param> /// <param name="message">The quit message.</param> /// <returns>The raw data to be sent to the server.</returns> public string[][] OnQuit(int sid, User u, string message) { if ( Quit != null ) return InvocationTunnel( this.Quit.GetInvocationList(), sid, u, message ); return null; }
/// <summary> /// This method parses all raw data for each packet of data that /// a Server object might receive. It then uses the events defined /// in IRCEvents and fires them through the appropriate server object. /// </summary> /// <param name="s">The Server which the data was received on.</param> /// <param name="raw">The raw text from the socket.</param> public static void Parse(Server s, string raw) { //TODO: IMPLEMENT THE REST :D int spacestring = 0; int lastchar = 0; int firstchar = 0; //Remove excessive spaces from everything. StringBuilder sb = new StringBuilder(); for ( int i = 0; i < raw.Length; i++ ) { if ( raw[i] == ' ' ) { if ( spacestring++ == 0 ) lastchar = i; } else if ( spacestring > 1 ) { sb.Append( raw, firstchar, lastchar - firstchar + 1 ); spacestring = 0; firstchar = i; lastchar = i; } else { spacestring = 0; lastchar = i; } } if ( sb.Length > 0 || ( lastchar != firstchar && firstchar != 0 && lastchar != raw.Length - 1 ) ) { sb.Append( raw, firstchar, lastchar - firstchar + 1 ); } if ( sb.Length > 0 ) raw = sb.ToString(); //Make sure this excessive space is handled with care. (For all instances where text is preceeded by a space) raw = raw.Replace( ": ", ":" ); //Replies to ping handler if ( raw.StartsWith( "PING :" ) ) { string[] parsed = raw.Split( ':' ); s.QueueData( s.EventObject.OnPing( s.ServerID, parsed[1] ) ); } if ( raw.StartsWith( "ERROR :" ) ) { Console.WriteLine( "[Error: whatsit]" ); } //All that work above for this? string[] spaceSplit = raw.Split( ' ' ); if ( spaceSplit.Length <= 1 ) return; //Nothing below here takes only one spaceSplit arg. switch ( spaceSplit[1] ) { case "001": { string welcome = raw.Substring( spaceSplit[0].Length + spaceSplit[1].Length + 4 + spaceSplit[2].Length ); s.QueueData( s.EventObject.OnWelcome( s.ServerID, welcome ) ); } break; case "352": { //spaceSplit[5] = spaceSplit[5].Substring( 1 ); //Get rid of the : on the first name. // // 0 1 2 3 4 5 6 7 8 9 10 //":TechConnect.NL.EU.GameSurge.net 352 P2Q #phishcave ~2q d75-155-184-58.bchsia.telus.net *.GameSurge.net P2Q H :0 2Q Beta" IRCHost ir = new IRCHost(spaceSplit[7], spaceSplit[4], spaceSplit[5]); //fix on debug. Channel c = UpdateChanDB(s, spaceSplit[3]); UpdateUserDB(s, ir); //UpdateBothDB(s, spaceSplit[3], spaceSplit[7]); //This should blank add all the users if (spaceSplit[8].Contains("@")) UpdateBothDB(s, spaceSplit[3], spaceSplit[7], '@'); //NO Simple. hah else if (spaceSplit[8].Contains("+")) UpdateBothDB(s, spaceSplit[3], spaceSplit[7], '+'); else UpdateBothDB(s, spaceSplit[3], spaceSplit[7], null); //Invoke the event. s.QueueData(s.EventObject.OnNames(s.ServerID, c)); } break; case "353": { spaceSplit[5] = spaceSplit[5].Substring( 1 ); //Get rid of the : on the first name. //if ( spaceSplit[2] == s.Config.NickName ) //Do we need to parse ourself? ~fish // break; Channel c = UpdateChanDB( s, spaceSplit[4] ); //This should blank add all the users for ( int i = 5; i < spaceSplit.Length; i++ ) { if ( spaceSplit[i][0] == '@' || spaceSplit[i][0] == '+' ) UpdateBothDB( s, spaceSplit[4], spaceSplit[i].Substring( 1 ), spaceSplit[i][0] ); else UpdateBothDB( s, spaceSplit[4], spaceSplit[i], null ); } //Invoke the event. s.QueueData( s.EventObject.OnNames( s.ServerID, c ) ); } break; case "433": { //:SERVER 433 * THENICK :Nickname is already in use. s.QueueData( s.EventObject.OnErr_NickNameInUse( s.ServerID, spaceSplit[3] ) ); } break; case "MODE": { //SERVERMODE: //:USERHOST MODE RECIPIENT :MODESTRING if ( spaceSplit[3][0] == ':' ) { IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); User u = new User( irch ); s.QueueData( s.EventObject.OnServerModeMessage( s.ServerID, u, spaceSplit[2], spaceSplit[3].TrimStart( ':' ) ) ); } else { //:USERMODE //TODO: HANDLE THIS //:USERHOST MODE MODESTRING MODEAFFECTUSER MODEAFFECTUSER MODEAFFECTUSER } } break; case "JOIN": { IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); Channel c = UpdateChanDB( s, spaceSplit[2] ); if ( irch.Nick.Equals( s.CurrentNickName ) ) { //We joined the channel. s.QueueData( s.EventObject.OnBotJoin( s.ServerID, c ) ); } else { //Someone joined the channel. //Update the user first. UpdateUserDB( s, irch ); //Now update the channel. ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick ); s.QueueData( s.EventObject.OnJoin( s.ServerID, c, cu ) ); } } break; case "PRIVMSG": { string privmsgtxt = raw.Substring( spaceSplit[0].Length + spaceSplit[1].Length + spaceSplit[2].Length + 4 ); //:USERHOST PRIVMSG RECIPIENT :TEXT // length length length + 4 (3 spaces & a :) IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); User u = UpdateUserDB( s, irch ); //Replies to Channel/User CTCP Messages. if ( spaceSplit.Length > 4 && spaceSplit[3].Length > 2 && spaceSplit[3][1] == (char)1 && raw.EndsWith( ( (char)1 ).ToString() ) ) { if ( spaceSplit[2].Length >= 1 && ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) ) { Channel c = UpdateChanDB( s, spaceSplit[2] ); ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick ); s.QueueData( s.EventObject.OnChannelCTCPMessage( s.ServerID, c, cu, privmsgtxt.Trim( (char)1 ) ) ); } else s.QueueData( s.EventObject.OnUserCTCPMessage( s.ServerID, spaceSplit[2], u, privmsgtxt.Trim( (char)1 ) ) ); } //TODO: Evaluate if these can be moved up above the CTCP messages once it's converted. else if ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) { Channel c = UpdateChanDB( s, spaceSplit[2] ); ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick ); InvokeParsers( s, c, u, cu, privmsgtxt, IRCEvents.ParseTypes.ChannelMessage ); s.QueueData( s.EventObject.OnChannelMessage( s.ServerID, c, cu, privmsgtxt ) ); } else { InvokeParsers( s, null, u, null, privmsgtxt, IRCEvents.ParseTypes.PrivateMessage ); s.QueueData( s.EventObject.OnUserMessage( s.ServerID, spaceSplit[2], u, privmsgtxt ) ); } } break; case "NOTICE": { // user notice // :HOST NOTICE ME :MSG // channel notice // :HOST NOTICE CHANNEL :MSG IRCHost irch; string text = raw.Substring( spaceSplit[0].Length + spaceSplit[1].Length + spaceSplit[2].Length + 4 ); try { irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); } catch ( FormatException ) { // looks like this is a server notice. InvokeParsers( s, null, null, null, text, IRCEvents.ParseTypes.ServerNotice ); s.QueueData( s.EventObject.OnServerNotice( s.ServerID, text ) ); break; } User u = UpdateUserDB( s, irch ); if ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) { Channel c = UpdateChanDB( s, spaceSplit[2] ); InvokeParsers( s, c, u, null, text, IRCEvents.ParseTypes.ChannelNotice ); s.QueueData( s.EventObject.OnChannelNotice( s.ServerID, c, u, text ) ); } else { InvokeParsers( s, null, u, null, text, IRCEvents.ParseTypes.PrivateNotice ); s.QueueData( s.EventObject.OnPrivateNotice( s.ServerID, u, text ) ); } } break; case "QUIT": { //:USERHOST QUIT :MESSAGE IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); User u = UpdateUserDB( s, irch ); //Premature call of event. s.QueueData( s.EventObject.OnQuit( s.ServerID, u, raw.Substring( spaceSplit[0].Length + spaceSplit[1].Length + 3 ) ) ); foreach ( Channel c in s.ChannelDatabase ) c.RemoveUser( u.Nickname ); s.UserDatabase.RemoveUser( u ); } break; case "PART": { //:USERHOST PART CHANNELNAME :MESSAGE IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); if ( irch.Nick.Equals( s.CurrentNickName ) ) { s.QueueData( s.EventObject.OnBotPart( s.ServerID, s.ChannelDatabase[spaceSplit[2]], spaceSplit.Length > 3 ? spaceSplit[3] : null ) ); s.ChannelDatabase.RemoveChannel( spaceSplit[2] ); } else { User u = UpdateUserDB( s, irch ); ChannelUser cu = UpdateBothDB( s, spaceSplit[2], u.Nickname ); //Premature call of event. s.QueueData( s.EventObject.OnPart( s.ServerID, cu, s.ChannelDatabase[spaceSplit[2]], spaceSplit.Length > 3 ? spaceSplit[3] : null ) ); s.ChannelDatabase[spaceSplit[2]].RemoveUser( u ); bool stillOnAChannel = false; foreach ( Channel c in s.ChannelDatabase ) if ( c.HasNick( u.Nickname ) ) stillOnAChannel = true; if ( stillOnAChannel == false ) s.UserDatabase.RemoveUser( u ); } } break; case "NICK": { //:USERHOST NICK :NEWNICK IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); string newNick = spaceSplit[2].Substring( 1 ); string oldNick = irch.Nick; if ( oldNick == s.CurrentNickName ) { //We need to update. s.CurrentNickName = newNick; s.QueueData( s.EventObject.OnBotNickName( s.ServerID, newNick, oldNick ) ); } else { User oldUser = null; try { oldUser = s.UserDatabase[irch.Nick];//Get the old user. Remove him from the DB. } catch ( KeyNotFoundException ) { //see below. } if ( oldUser == null ) { //This means he wasn't in our user database.. WEIRD. Add him, add him to the db, but still //broadcast it as a nick message. oldUser = new User( irch ); s.UserDatabase.AddUser( oldUser ); s.UserDatabase.Authenticate( oldUser ); } else { s.UserDatabase.RemoveUser( oldUser ); //Removed him. oldUser.CurrentHost.Nick = newNick; //Change his nick in the local User variable. s.UserDatabase.AddUser( oldUser ); //Re-Add him to the database. s.UserDatabase.Authenticate( oldUser ); } ChannelUser cu = null; foreach ( Channel c in s.ChannelDatabase ) { //Replace nick in all channels that had the old nick identifier. try { cu = c[oldNick]; //Preserve his channel settings by retrieving this piece of info. } catch ( KeyNotFoundException ) { continue; } cu.InternalUser = oldUser; //Set the new internal user. (nick matches might change authentication) c.ReplaceUser( oldNick, cu ); //Replace the user in the database, remove oldNick, add the channeluser. } s.QueueData( s.EventObject.OnNickName( s.ServerID, oldUser, oldNick ) ); } } break; } }
/// <summary> /// Fires the OnNickName event. /// </summary> /// <param name="sid">The server id.</param> /// <param name="u">The user that changed their nick (post-change).</param> /// <param name="oldnick">The old nickname.</param> /// <returns>The raw data to be sent to the server.</returns> public string[] OnNickName(int sid, User u, string oldnick) { if ( NickName == null ) return null; NickNameEvent ne = new NickNameEvent(); ne.sid = sid; ne.u = u; ne.oldNick = oldnick; return InvocationTunnel( NickName.GetInvocationList(), ne, "onNickData", ( u.UserAttributes == null ) ? null : u.UserAttributes.Privegeles ); }
/// <summary> /// Creates a parse returns struct. /// </summary> /// <param name="serverId">The server id.</param> /// <param name="c">The channel triggered on.</param> /// <param name="u">The user triggered from.</param> /// <param name="cu">The channeluser triggered from.</param> /// <param name="text">The offending text.</param> /// <returns>A new parse returns struct.</returns> private static IRCEvents.ParseReturns CreateParseReturns(int serverId, Channel c, User u, ChannelUser cu, string text) { IRCEvents.ParseReturns pr = new IRCEvents.ParseReturns(); pr.Channel = c; pr.User = u; pr.ChannelUser = cu; pr.ServerID = serverId; pr.Text = text; return pr; }
/// <summary> /// Fires the PrivateNotice event. /// </summary> /// <param name="sid">Server ID</param> /// <param name="user">User who sent the message.</param> /// <param name="text">Text in the notice.</param> /// <returns>Raw data.</returns> public string[] OnPrivateNotice( int sid, User user, string text ) { if ( PrivateNotice == null ) return null; PrivateNoticeEvent pn = new PrivateNoticeEvent(); pn.sid = sid; pn.user = user; pn.text = text; return InvocationTunnel( PrivateNotice.GetInvocationList(), pn, "privateNoticeData", ( user.UserAttributes == null ) ? null : user.UserAttributes.Privegeles ); }
/// <summary> /// Determines if a user is known by the internal databases. If not /// it will create and authenticate the user. If so, it will simply look up the user. /// </summary> /// <param name="s">The server to check for the user on.</param> /// <param name="irch">The irc host to check for.</param> /// <returns>The new or old user.</returns> private static User UpdateUserDB(Server s, IRCHost irch) { User u; try { u = s.UserDatabase[irch.Nick]; if ( !u.CurrentHost.Equals( irch ) ) u.CurrentHost = irch; } catch ( KeyNotFoundException ) { u = new User( irch ); s.UserDatabase.AddUser( u ); s.UserDatabase.Authenticate( u ); } return u; }
/// <summary> /// Fires the NickName event. /// </summary> /// <param name="sid">The server on which the nick change happened on.</param> /// <param name="u">The new user that emerged from the nick change.</param> /// <param name="oldnick">The old nickname.</param> /// <returns>The raw data to be sent to the server.</returns> public string[][] OnNickName(int sid, User u, string oldnick) { if ( NickName != null ) return InvocationTunnel( this.NickName.GetInvocationList(), u.UserAttributes == null ? null : u.UserAttributes.Privegeles, sid, u, oldnick ); return null; }