protected override void Parse(Core.Server aServer, string aRawData, string aMessage, string[] aCommands) { ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType + "(" + aServer.Name + ")"); string tUserName = aCommands[0].Split('!')[0]; Channel tChan = aServer.Channel(aCommands[2]); Bot tBot = aServer.Bot(tUserName); #region VERSION if (aMessage == "VERSION") { log.Info("Parse() VERSION: " + Settings.Instance.IrcVersion); FireSendData(aServer, "NOTICE " + tUserName + " :\u0001VERSION " + Settings.Instance.IrcVersion + "\u0001"); return; } #endregion #region XGVERSION if (aMessage == "XGVERSION") { log.Info("Parse() XGVERSION: " + Settings.Instance.XgVersion); FireSendData(aServer, "NOTICE " + tUserName + " :\u0001XGVERSION " + Settings.Instance.XgVersion + "\u0001"); return; } #endregion #region DCC DOWNLOAD MESSAGE if (aMessage.StartsWith("DCC") && tBot != null) { Packet tPacket = tBot.OldestActivePacket(); if (tPacket != null) { if (tPacket.Connected) { log.Error("Parse() ignoring dcc from " + tBot + " because " + tPacket + " is already connected"); } else { bool isOk = false; int tPort = 0; Int64 tChunk = 0; string[] tDataList = aMessage.Split(' '); if (tDataList[1] == "SEND") { log.Info("Parse() DCC from " + tBot); // if the name of the file contains spaces, we have to replace em if (aMessage.StartsWith("DCC SEND \"")) { Match tMatch = Regex.Match(aMessage, "DCC SEND \"(?<packet_name>.+)\"(?<bot_data>[^\"]+)$"); if (tMatch.Success) { aMessage = "DCC SEND " + tMatch.Groups["packet_name"].ToString().Replace(" ", "_").Replace("'", "") + tMatch.Groups["bot_data"]; tDataList = aMessage.Split(' '); } } #region IP CALCULATING try { // this works not in mono?! tBot.Ip = IPAddress.Parse(tDataList[3]); } catch (FormatException) { #region WTF - FLIP THE IP BECAUSE ITS REVERSED?! string ip; try { ip = new IPAddress(long.Parse(tDataList[3])).ToString(); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse bot ip from string: " + aMessage, ex); return; } string realIp = ""; int pos = ip.LastIndexOf('.'); try { realIp += ip.Substring(pos + 1) + "."; ip = ip.Substring(0, pos); pos = ip.LastIndexOf('.'); realIp += ip.Substring(pos + 1) + "."; ip = ip.Substring(0, pos); pos = ip.LastIndexOf('.'); realIp += ip.Substring(pos + 1) + "."; ip = ip.Substring(0, pos); pos = ip.LastIndexOf('.'); realIp += ip.Substring(pos + 1); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse bot ip '" + ip + "' from string: " + aMessage, ex); return; } log.Info("Parse() IP parsing failed, using this: " + realIp); try { tBot.Ip = IPAddress.Parse(realIp); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse bot ip from string: " + aMessage, ex); return; } #endregion } #endregion try { tPort = int.Parse(tDataList[4]); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse bot port from string: " + aMessage, ex); return; } // we cant connect to port <= 0 if (tPort <= 0) { log.Error("Parse() " + tBot + " submitted wrong port: " + tPort + ", disabling packet"); tPacket.Enabled = false; // statistics Statistic.Instance.Increase(StatisticType.BotConnectsFailed); } else { tPacket.RealName = tDataList[2]; try { tPacket.RealSize = Int64.Parse(tDataList[5]); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse packet size from string: " + aMessage, ex); return; } tChunk = FileActions.NextAvailablePartSize(tPacket.RealName, tPacket.RealSize); if (tChunk < 0) { log.Error("Parse() file for " + tPacket + " from " + tBot + " already in use, disabling packet"); tPacket.Enabled = false; FireUnRequestFromBot(aServer, tBot); } else if (tChunk > 0) { log.Info("Parse() try resume from " + tBot + " for " + tPacket + " @ " + tChunk); FireSendData(aServer, "PRIVMSG " + tBot.Name + " :\u0001DCC RESUME " + tPacket.RealName + " " + tPort + " " + tChunk + "\u0001"); } else { isOk = true; } } } else if (tDataList[1] == "ACCEPT") { log.Info("Parse() DCC resume accepted from " + tBot); try { tPort = int.Parse(tDataList[3]); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse bot port from string: " + aMessage, ex); return; } try { tChunk = Int64.Parse(tDataList[4]); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse packet chunk from string: " + aMessage, ex); return; } isOk = true; } if (isOk) { log.Info("Parse() downloading from " + tBot + " - Starting: " + tChunk + " - Size: " + tPacket.RealSize); FireAddDownload(tPacket, tChunk, tBot.Ip, tPort); } tPacket.Commit(); } } else { log.Error("Parse() DCC not activated from " + tBot); } } #endregion #region DCC INFO MESSAGE else if (tChan != null) { bool insertBot = false; if (tBot == null) { insertBot = true; tBot = new Bot {Name = tUserName, Connected = true, LastMessage = "initial creation", LastContact = DateTime.Now}; } bool isParsed = false; Match tMatch; #region PACKET /SLOT / QUEUE INFO if (true) { tMatch = Regex.Match(aMessage, Magicstring + " ([0-9]*) (pack(s|)|Pa(c|)ket(e|)|Fil[e]+s) " + Magicstring + "\\s*(?<slot_cur>[0-9]*) (of|von) (?<slot_total>[0-9]*) (slot(s|)|Pl(a|�|.)tz(e|)) (open|opened|free|frei|in use|offen)(, ((Queue|Warteschlange): (?<queue_cur>[0-9]*)(\\/| of )(?<queue_total>[0-9]*),|).*(Record( [a-zA-Z]+|): (?<record>[0-9.]*)(K|)B\\/s|)|)", RegexOptions.IgnoreCase); if (tMatch.Success) { isParsed = true; int valueInt; if (int.TryParse(tMatch.Groups["slot_cur"].ToString(), out valueInt)) { tBot.InfoSlotCurrent = valueInt; } if (int.TryParse(tMatch.Groups["slot_total"].ToString(), out valueInt)) { tBot.InfoSlotTotal = valueInt; } if (int.TryParse(tMatch.Groups["queue_cur"].ToString(), out valueInt)) { tBot.InfoQueueCurrent = valueInt; } if (int.TryParse(tMatch.Groups["queue_total"].ToString(), out valueInt)) { tBot.InfoQueueTotal = valueInt; } if (tBot.InfoSlotCurrent > tBot.InfoSlotTotal) { tBot.InfoSlotTotal = tBot.InfoSlotCurrent; } if (tBot.InfoQueueCurrent > tBot.InfoQueueTotal) { tBot.InfoQueueTotal = tBot.InfoQueueCurrent; } // uhm, there is a free slot and we are still waiting? if (tBot.InfoSlotCurrent > 0 && tBot.State == Bot.States.Waiting) { tBot.State = Bot.States.Idle; FireCreateTimer(aServer, tBot, 0, false); } } } #endregion #region BANDWIDTH if (!isParsed) { tMatch = Regex.Match(aMessage, Magicstring + " ((Bandwidth Usage|Bandbreite) " + Magicstring + "|)\\s*(Current|Derzeit): (?<speed_cur>[0-9.]*)(?<speed_cur_end>(K|)(i|)B)(\\/s|s)(,|)(.*Record: (?<speed_max>[0-9.]*)(?<speed_max_end>(K|)(i|))B(\\/s|s)|)", RegexOptions.IgnoreCase); if (tMatch.Success) { isParsed = true; string speedCurEnd = tMatch.Groups["speed_cur_end"].ToString().ToLower(); string speedMaxEnd = tMatch.Groups["speed_max_end"].ToString().ToLower(); string speedCur = tMatch.Groups["speed_cur"].ToString(); string speedMax = tMatch.Groups["speed_max"].ToString(); if (Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",") { speedCur = speedCur.Replace('.', ','); speedMax = speedMax.Replace('.', ','); } double valueDouble; if (double.TryParse(speedCur, out valueDouble)) { tBot.InfoSpeedCurrent = speedCurEnd.StartsWith("k") ? (Int64) (valueDouble * 1024) : (Int64) valueDouble; } if (double.TryParse(speedMax, out valueDouble)) { tBot.InfoSpeedMax = speedMaxEnd.StartsWith("k") ? (Int64) (valueDouble * 1024) : (Int64) valueDouble; } } } #endregion #region PACKET INFO Packet newPacket = null; if (!isParsed) { // what is this damn char \240 and how to rip it off ??? tMatch = Regex.Match(aMessage, "#(?<pack_id>\\d+)(\u0240|�|)\\s+(\\d*)x\\s+\\[\\s*(�|)\\s*(?<pack_size>[\\<\\>\\d.]+)(?<pack_add>[BbGgiKMs]+)\\]\\s+(?<pack_name>.*)", RegexOptions.IgnoreCase); if (tMatch.Success) { isParsed = true; try { int tPacketId; try { tPacketId = int.Parse(tMatch.Groups["pack_id"].ToString()); } catch (Exception ex) { log.Fatal("Parse() " + tBot + " - can not parse packet id from string: " + aMessage, ex); return; } Packet tPack = tBot.Packet(tPacketId); if (tPack == null) { tPack = new Packet(); newPacket = tPack; tPack.Id = tPacketId; tBot.AddPacket(tPack); } tPack.LastMentioned = DateTime.Now; string name = RemoveSpecialIrcCharsFromPacketName(tMatch.Groups["pack_name"].ToString()); if (tPack.Name != name && tPack.Name != "") { tPack.Enabled = false; if (!tPack.Connected) { tPack.RealName = ""; tPack.RealSize = 0; } } tPack.Name = name; double tPacketSizeFormated; string stringSize = tMatch.Groups["pack_size"].ToString().Replace("<", "").Replace(">", ""); if (Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",") { stringSize = stringSize.Replace('.', ','); } double.TryParse(stringSize, out tPacketSizeFormated); string tPacketAdd = tMatch.Groups["pack_add"].ToString().ToLower(); if (tPacketAdd == "k" || tPacketAdd == "kb") { tPack.Size = (Int64) (tPacketSizeFormated * 1024); } else if (tPacketAdd == "m" || tPacketAdd == "mb") { tPack.Size = (Int64) (tPacketSizeFormated * 1024 * 1024); } else if (tPacketAdd == "g" || tPacketAdd == "gb") { tPack.Size = (Int64) (tPacketSizeFormated * 1024 * 1024 * 1024); } if (tPack.Commit()) { log.Info("Parse() updated " + tPack + " from " + tBot); } } catch (FormatException) {} } } #endregion // insert bot if ok if (insertBot) { if (isParsed) { tChan.AddBot(tBot); log.Info("Parse() inserted " + tBot); } } // and insert packet _AFTER_ this if (newPacket != null) { tBot.AddPacket(newPacket); log.Info("Parse() inserted " + newPacket + " into " + tBot); } #if DEBUG #region NOT NEEDED INFOS if (!isParsed) { tMatch = Regex.Match(aMessage, Magicstring + " To request .* type .*", RegexOptions.IgnoreCase); if (tMatch.Success) { return; } tMatch = Regex.Match(aMessage, ".*\\/(msg|ctcp) .* xdcc (info|send) .*", RegexOptions.IgnoreCase); if (tMatch.Success) { return; } tMatch = Regex.Match(aMessage, Magicstring + " To list a group, type .*", RegexOptions.IgnoreCase); if (tMatch.Success) { return; } tMatch = Regex.Match(aMessage, "Total offered(\\!|): (\\[|)[0-9.]*\\s*[BeGgiKMsTty]+(\\]|)\\s*Total transfer(r|)ed: (\\[|)[0-9.]*\\s*[BeGgiKMsTty]+(\\]|)", RegexOptions.IgnoreCase); if (tMatch.Success) { return; } tMatch = Regex.Match(aMessage, ".* (brought to you|powered|sp(o|0)ns(o|0)red) by .*", RegexOptions.IgnoreCase); if (tMatch.Success) { return; } tMatch = Regex.Match(aMessage, Magicstring + " .*" + tChan.Name + " " + Magicstring, RegexOptions.IgnoreCase); if (tMatch.Success) { return; } } #endregion #region COULD NOT PARSE if (!isParsed) // && tBot.Packets.Count() > 0) { FireParsingError("[DCC Info] " + tBot.Name + " : " + RemoveSpecialIrcChars(aMessage)); } #endregion #endif } #endregion if (tBot != null) { tBot.Commit(); } if (tChan != null) { tChan.Commit(); } }
protected override void Parse(Core.Server aServer, string aRawData, string aMessage, string[] aCommands) { ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType + "(" + aServer.Name + ")"); string tUserName = aCommands[0].Split('!')[0]; string tComCodeStr = aCommands[1]; string tChannelName = aCommands[2]; Channel tChan = aServer.Channel(tChannelName); Bot tBot = aServer.Bot(tUserName); if (tBot != null) { tBot.LastContact = DateTime.Now; } #region PRIVMSG if (tComCodeStr == "PRIVMSG") { _privateMessage.ParseData(aServer, aRawData); return; } #endregion #region NOTICE if (tComCodeStr == "NOTICE") { if (tUserName.ToLower() == "nickserv") { _nickserv.ParseData(aServer, aRawData); } else { _notice.ParseData(aServer, aRawData); } return; } #endregion #region NICK if (tComCodeStr == "NICK") { if (tBot != null) { tBot.Name = aMessage; log.Info("con_DataReceived() bot " + tUserName + " renamed to " + tBot); } else if (tUserName == Settings.Instance.IrcNick) { // what should i do now?! log.Error("con_DataReceived() wtf? i was renamed to " + aMessage); } } #endregion #region KICK else if (tComCodeStr == "KICK") { if (tChan != null) { tUserName = aCommands[3]; if (tUserName == Settings.Instance.IrcNick) { tChan.Connected = false; log.Warn("con_DataReceived() kicked from " + tChan + (aCommands.Length >= 5 ? " (" + aCommands[4] + ")" : "") + " - rejoining"); log.Warn("con_DataReceived() " + aRawData); FireJoinChannel(aServer, tChan); // statistics Statistic.Instance.Increase(StatisticType.ChannelsKicked); } else { tBot = aServer.Bot(tUserName); if (tBot != null) { tBot.Connected = false; tBot.LastMessage = "kicked from " + tChan; log.Info("con_DataReceived() " + tBot + " is offline"); } } } } #endregion #region KILL else if (tComCodeStr == "KILL") { tUserName = aCommands[2]; if (tUserName == Settings.Instance.IrcNick) { log.Warn("con_DataReceived() i was killed from server because of " + aMessage); } else { tBot = aServer.Bot(tUserName); if (tBot != null) { log.Warn("con_DataReceived() " + tBot + " was killed from server?"); } } } #endregion #region JOIN else if (tComCodeStr == "JOIN") { tChannelName = aMessage; tChan = aServer.Channel(tChannelName); if (tChan != null) { if (tBot != null) { tBot.Connected = true; tBot.LastMessage = "joined channel " + tChan.Name; if (tBot.State != Bot.States.Active) { tBot.State = Bot.States.Idle; } log.Info("con_DataReceived() " + tBot + " is online"); FireRequestFromBot(aServer, tBot); } } } #endregion #region PART else if (tComCodeStr == "PART") { if (tChan != null) { if (tBot != null) { tBot.Connected = true; tBot.LastMessage = "parted channel " + tChan.Name; log.Info("con_DataReceived() " + tBot + " parted from " + tChan); } } } #endregion #region QUIT else if (tComCodeStr == "QUIT") { if (tBot != null) { tBot.Connected = false; tBot.LastMessage = "quited"; log.Info("con_DataReceived() " + tBot + " quited"); } } #endregion #region MODE / TOPIC / WALLOP else if (tComCodeStr == "MODE" || tComCodeStr == "TOPIC" || tComCodeStr == "WALLOP") { // uhm, what to do now?! } #endregion #region INVITE else if (tComCodeStr == "INVITE") { log.Info("con_DataReceived() received an invite for channel " + aMessage); // ok, lets do a silent auto join if (Settings.Instance.AutoJoinOnInvite) { log.Info("con_DataReceived() auto joining " + aMessage); FireSendData(aServer, "JOIN " + aMessage); } } #endregion #region PONG else if (tComCodeStr == "PONG") { log.Info("con_DataReceived() PONG"); } #endregion #region INT VALUES else { _intValue.ParseData(aServer, aRawData); } #endregion if (tBot != null) { tBot.Commit(); } if (tChan != null) { tChan.Commit(); } }
protected override void Parse(Core.Server aServer, string aRawData, string aMessage, string[] aCommands) { ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType + "(" + aServer.Name + ")"); Bot tBot = aServer.Bot(aCommands[0].Split('!')[0]); Channel tChan = aServer.Channel(aCommands[2]); string tComCodeStr = aCommands[1]; int tComCode; if (int.TryParse(tComCodeStr, out tComCode)) { switch (tComCode) { #region 4 case 4: // aServer.Connected = true; aServer.Commit(); break; #endregion #region RPL_WHOISCHANNELS case 319: // RPL_WHOISCHANNELS tBot = aServer.Bot(aCommands[3]); if (tBot != null) { string chanName = ""; bool addChan = true; string[] tChannelList = aRawData.Split(':')[2].Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); foreach (string chan in tChannelList) { chanName = "#" + chan.Split('#')[1]; if (aServer.Channel(chanName) != null) { addChan = false; FireRequestFromBot(aServer, tBot); break; } } if (addChan) { log.Info("Parse() auto adding channel " + chanName); aServer.AddChannel(chanName); } } break; #endregion #region RPL_NAMREPLY case 353: // RPL_NAMREPLY tChan = aServer.Channel(aCommands[4]); if (tChan != null) { string[] tUsers = aMessage.Split(' '); foreach (string user in tUsers) { string tUser = Regex.Replace(user, "^(@|!|%|\\+){1}", ""); tBot = tChan.Bot(tUser); if (tBot != null) { tBot.Connected = true; tBot.LastMessage = "joined channel " + tChan.Name; if (tBot.State != Bot.States.Active) { tBot.State = Bot.States.Idle; } log.Info("Parse() " + tBot + " is online"); tBot.Commit(); FireRequestFromBot(aServer, tBot); } } } break; #endregion #region RPL_ENDOFNAMES case 366: // RPL_ENDOFNAMES tChan = aServer.Channel(aCommands[3]); if (tChan != null) { tChan.ErrorCode = 0; tChan.Connected = true; log.Info("Parse() joined " + tChan); } // statistics Statistic.Instance.Increase(StatisticType.ChannelConnectsOk); break; #endregion #region RPL_ENDOFMOTD | ERR_NOMOTD case 376: // RPL_ENDOFMOTD case 422: // ERR_NOMOTD log.Info("Parse() really connected"); aServer.Connected = true; aServer.Commit(); foreach (Channel chan in aServer.Channels) { if (chan.Enabled) { FireJoinChannel(aServer, chan); } } // statistics Statistic.Instance.Increase(StatisticType.ServerConnectsOk); break; #endregion #region ERR_NOCHANMODES case 477: // ERR_NOCHANMODES tChan = aServer.Channel(aCommands[3]); // TODO should we nickserv register here? /*if(Settings.Instance.AutoRegisterNickserv && Settings.Instance.IrcPasswort != "" && Settings.Instance.IrcRegisterEmail != "") { FireSendDataEvent(aServer, "nickserv register " + Settings.Instance.IrcPasswort + " " + Settings.Instance.IrcRegisterEmail); }*/ if (tChan != null) { tChan.ErrorCode = tComCode; //CreateTimerEvent(aServer, tChan, Settings.Instance.ChannelWaitTime); } else { //tBot = aServer.getBot(tCommandList[3]); //if(tBot != null) { CreateTimerEvent(aServer, tBot, Settings.Instance.BotWaitTime); } } break; #endregion #region ERR_TOOMANYCHANNELS case 405: tChan = aServer.Channel(aCommands[3]); if (tChan != null) { tChan.ErrorCode = tComCode; tChan.Connected = false; log.Warn("Parse() could not join " + tChan + ": " + tComCode); } // statistics Statistic.Instance.Increase(StatisticType.ChannelConnectsFailed); break; #endregion #region ERR_CHANNELISFULL | ERR_INVITEONLYCHAN | ERR_BANNEDFROMCHAN | ERR_BADCHANNELKEY | ERR_UNIQOPPRIVSNEEDED case 471: // ERR_CHANNELISFULL case 473: // ERR_INVITEONLYCHAN case 474: // ERR_BANNEDFROMCHAN case 475: // ERR_BADCHANNELKEY case 485: // ERR_UNIQOPPRIVSNEEDED tChan = aServer.Channel(aCommands[3]); if (tChan != null) { tChan.ErrorCode = tComCode; tChan.Connected = false; log.Warn("Parse() could not join " + tChan + ": " + tComCode); FireCreateTimer(aServer, tChan, tComCode == 471 || tComCode == 485 ? Settings.Instance.ChannelWaitTime : Settings.Instance.ChannelWaitTimeLong, false); } // statistics Statistic.Instance.Increase(StatisticType.ChannelConnectsFailed); break; #endregion } if (tBot != null) { tBot.Commit(); } if (tChan != null) { tChan.Commit(); } } else { log.Error("Parse() Irc code " + tComCodeStr + " could not be parsed. (" + aRawData + ")"); } }