func (ib *IrcBot) parsePacket(conn *irc.Conn, line *irc.Line) *models.Packet { result := ib.regex.FindStringSubmatch(line.Text()) if result == nil { return nil } fileName := cleanFileName(result[3]) packet := models.NewPacket(result[1], result[2], fileName, line.Nick, line.Target(), ib.server.Name, line.Time) //save packet if packet != nil { ib.dataService.SavePacket(packet) } return packet }
// Handles triggers if module is enabled and user/chan is allowed. This is mainly // exported for use by library and should not have to be called by the user func (self *Module) Handle(eventMode Event, trigger string, line *irc.Line) { // Filtered by: denyUser, allowUser, denyChan, allowChan if !self.Enabled() || self.InDenyed(line.Nick) || // Empty allowUser list => allow all (self.LenAllowed(UC_User) != 0 && !self.InAllowed(line.Nick)) || self.InDenyed(line.Target()) || // Empty denyChan list => allow all (self.LenAllowed(UC_Chan) != 0 && !self.InAllowed(line.Target())) { return } eventMode = Event(strings.ToUpper(string(eventMode))) go self.handleString(eventMode, trigger, line) go self.handleRegexp(eventMode, trigger, line) }
func (ei *EndpointIRC) message(c *irc.Conn, l *irc.Line) { var messageTarget MessageTarget if l.Public() { messageTarget = ei.GetChannel(l.Target()) } else { messageTarget = ei.GetUser(l.Target()) } ei.handler(l.Text(), ei.GetUser(l.Nick), l.Target(), messageTarget) }
func (plugin *Plugin) OnJoin(conn *client.Conn, line *client.Line) { logging.Info("vpnbot.Plugin: %v joined %v", line.Src, line.Target()) if lastCheck, ok := plugin.lastCheckNicks[line.Nick]; ok && time.Now().Sub(lastCheck) < 15*time.Minute { // There is a check in progress or another one has been done earlier logging.Debug("vpnbot.Plugin: Not checking %v, last check was %v", line.Nick, humanize.Time(plugin.lastCheckNicks[line.Nick])) return } logging.Debug("vpnbot.Plugin: Checking %v...", line.Nick) plugin.lastCheckNicks[line.Nick] = time.Now() // Is this me? if line.Nick == conn.Me().Nick { logging.Debug("vpnbot.Plugin: %v is actually me, skipping.", line.Nick) return } // Nickname == Ident? (9 chars cut) if !strings.HasPrefix(nonWordCharsRegex.ReplaceAllString(line.Nick, ""), strings.TrimLeft(line.Ident, "~")) { logging.Debug("vpnbot.Plugin: %v's nick doesn't match the ident, skipping.", line.Nick) return } // Hostname is masked RDNS vhost/IP? // TODO - Use regex to avoid banning due to similar vhosts if !maskedAddrRegex.MatchString(line.Host) { // Detected custom vHost logging.Debug("vpnbot.Plugin: %v has a custom vhost, skipping.", line.Nick) return } go func() { botNick := line.Nick nobotActivityChan := make(chan string) defer plugin.bot.HandleFunc("privmsg", func(conn *client.Conn, line *client.Line) { if line.Nick == botNick { nobotActivityChan <- "User sent a message" } }).Remove() defer plugin.bot.HandleFunc("noticed", func(conn *client.Conn, line *client.Line) { if line.Nick == botNick { nobotActivityChan <- "User sent a notice" } }).Remove() defer plugin.bot.HandleFunc("part", func(conn *client.Conn, line *client.Line) { if line.Nick == botNick { nobotActivityChan <- "User left" } }).Remove() defer plugin.bot.HandleFunc("part", func(conn *client.Conn, line *client.Line) { if line.Nick == botNick { } if len(line.Args) > 0 { switch line.Args[0] { case "Excess flood": // If this was an excess flood, consider it spam that should // be good to ban anyways nobotActivityChan <- "Excess flood, banning early" banmask := fmt.Sprintf("%v!%v@%v", "*", "*", line.Host) // TODO - Ramp up/down the duration with increasing/decreasing activity of the bots plugin.banGlobal(plugin.generateBan(line.Nick, banmask, "Instant excess flood", 2*24*time.Hour)) default: nobotActivityChan <- "User quit normally" } } }).Remove() // Give nobotActivityChan some time to prove this is not a bot select { case reason := <-nobotActivityChan: logging.Info("vpnbot.Plugin: %v, skipping.", reason) return case <-time.After(1 * time.Second): } // Get WHOIS info info, err := plugin.whois.WhoIs(line.Nick) if err != nil && err != whois.ErrNoSuchNick { logging.Warn("vpnbot.Plugin: Can't get WHOIS info for %v, skipping: %v", line.Nick, err.Error()) return } // Not an oper? if info.IsOperator { logging.Debug("vpnbot.Plugin: %v is operator, skipping.", line.Nick) return } // Not away if info.IsAway { logging.Debug("vpnbot.Plugin: %v is away, skipping.", line.Nick) return } // Realname == Nickname? if info.Realname != line.Nick { logging.Debug( "vpnbot.Plugin: %v's nick doesn't match the realname, skipping.", line.Nick) return } // Count of channels at least 48 if len(info.Channels) < 48 { logging.Debug( "vpnbot.Plugin: %v is not in a high amount of channels, skipping.", line.Nick) return } // Not halfop, op, aop or owner in any channel for _, prefix := range info.Channels { if prefix == '%' || prefix == '@' || prefix == '&' || prefix == '~' { logging.Debug( "vpnbot.Plugin: %v is opped in a channel, skipping.", line.Nick) return } } // Give nobotActivityChan some time to prove this is not a bot select { case reason := <-nobotActivityChan: logging.Info("vpnbot.Plugin: %v, skipping.", reason) return case <-time.After(250 * time.Millisecond): } // More expensive tests below... // Make sure we deal with an unregistered client status := plugin.nickserv.Status(line.Nick)[line.Nick] if status.Error != nil { logging.Warn("vpnbot.Plugin: Can't get auth status for %v, skipping: %v", line.Nick, status.Error) return } if status.Level >= nickserv.Status_IdentifiedViaPassword { logging.Debug("vpnbot.Plugin: %v is identified, skipping.", line.Nick) return } // Give nobotActivityChan some time to prove this is not a bot select { case reason := <-nobotActivityChan: logging.Info("vpnbot.Plugin: %v, skipping.", reason) return case <-time.After(250 * time.Millisecond): } // This is a bot we need to ban! banmask := fmt.Sprintf("%v!%v@%v", "*", "*", line.Host) // TODO - Ramp up/down the duration with increasing/decreasing activity of the bots plugin.banGlobal(plugin.generateBan(line.Nick, banmask, "Known pattern of ban-evading/logging bot", 2*24*time.Hour)) }() }