Example #1
0
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)
}
Example #2
0
func (self *ModManager) run(event string, line *irc.Line) {
	self.mut.RLock()
	defer self.mut.RUnlock()

	for _, mod := range self.modules {
		// Module should check if enabled, not handlers
		go mod.Handle(module.Event(event), line.Text(), line)
	}
}
Example #3
0
func (self *Module) handleRegexp(eventMode Event, trigger string, line *irc.Line) {
	self.reMut.RLock()
	defer self.reMut.RUnlock()

	for _, reM := range self.reTriggers[eventMode] {
		if reM.trigger.MatchString(trigger) {
			go reM.fn(line.Copy())
		}
	}
}
Example #4
0
func (self *Module) handleString(eventMode Event, trigger string, line *irc.Line) {
	trigger = strings.ToLower(trigger)
	evT := eventTrigger{eventMode, trigger}

	self.stMut.RLock()
	defer self.stMut.RUnlock()

	for _, fn := range self.stTriggers[evT] {
		go fn(line.Copy())
	}
}
Example #5
0
// Implement client.Handler so commandSet can Handle things directly.
func (cs *commandSet) Handle(conn *client.Conn, line *client.Line) {
	// This is a dirty hack to treat factoid additions as a special
	// case, since they may begin with command string prefixes.
	ctx := context(conn, line)
	if ctx == nil || util.IsFactoidAddition(line.Text()) {
		return
	}
	if r, ln := cs.match(ctx.Text()); ctx.Addressed && r != nil {
		// Cut command off, trim and compress spaces.
		ctx.Args[1] = strings.Join(strings.Fields(ctx.Args[1][ln:]), " ")
		r.Run(ctx)
	}
}
Example #6
0
func handle_command(conn *irc.Conn, line *irc.Line, args []string) {
	command := args[0][len(RC.CmdPrefix):]
	args = args[1:]

	st := conn.StateTracker()
	authed := RC.Authed[line.Nick]

	if line.Nick == RC.Owner && authed {
		// Owner-only commands
		if command == "mock" {
			for _, n := range args {
				_, is_on := st.IsOn(RC.Channel, n)
				if is_on {
					RC.Mocking[n] = true
					conn.Privmsg(RC.Channel, "Now mocking "+n)
				}
			}
		} else if command == "unmock" {
			for _, n := range args {
				if RC.Mocking[n] {
					RC.Mocking[n] = false
					conn.Privmsg(RC.Channel, "No longer mocking "+n)
				}
			}
		} else if command == "shorten" {
			fmt.Println("unimplemented")
		} else if command == "snoop" {
			fmt.Println("unimplemented")
		}
	} else if (RC.Ops[line.Nick] || line.Nick == RC.Owner) && authed {
		// Ops-level commands
		if command == "poop" {
			conn.Privmsg(RC.Channel, "poop")
		}
	} else if command == "identify" && !line.Public() {
		fmt.Println("User " + line.Nick + " attempting to auth...")
		h := sha256.New()
		h.Write([]byte(args[0]))
		pwd_hash := hex.EncodeToString(h.Sum(nil))
		if (line.Nick == RC.Owner || RC.Ops[line.Nick]) && RC.Password == pwd_hash {
			fmt.Println("Auth succeeded for " + line.Nick)
			RC.Authed[line.Nick] = true
			conn.Privmsg(line.Nick, "You're authenticated now.")
		} else {
			fmt.Println("WARNING: Auth failed for " + line.Nick + "!")
			conn.Privmsg(line.Nick, "You f****d up.")
		}
	}
}
Example #7
0
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
}
Example #8
0
// 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)
}
Example #9
0
func context(conn *client.Conn, line *client.Line) *Context {
	ctx := &Context{conn: conn, Line: line.Copy(), rws: bot.rewriters}
	// This is a bit of a dirty hack; context() returns nil to ignore a line.
	// TODO(fluffle): Ignores based on masks (or more likely regex).
	if ctx.Nick != "" && conf.Ns(ignoreNs).String(strings.ToLower(ctx.Nick)) != "" {
		return nil
	}
	if ctx.Cmd != client.PRIVMSG {
		return ctx
	}
	ctx.Args[1], ctx.Addressed = util.RemovePrefixedNick(
		strings.TrimSpace(ctx.Args[1]), ctx.Me())
	// If we're being talked to in private, line.Args[0] will contain our Nick.
	// We should consider this as "addressing" us, and set Addressed = true
	if ctx.Args[0] == ctx.Me() {
		ctx.Addressed = true
	}
	return ctx
}
Example #10
0
File: bot.go Project: pzsz/sp0rkle
func transformLine(line *client.Line) *base.Line {
	// We want line.Args[1] to contain the (possibly) stripped version of itself
	// but modifying the pointer will result in other goroutines seeing the
	// change, so we need to copy line for our own edification.
	nl := &base.Line{Line: line.Copy()}
	if nl.Cmd != "PRIVMSG" {
		return nl
	}
	nl.Args[1], nl.Addressed = util.RemovePrefixedNick(
		strings.TrimSpace(line.Args[1]), irc.Me.Nick)
	// If we're being talked to in private, line.Args[0] will contain our Nick.
	// To ensure the replies go to the right place (without performing this
	// check everywhere) test for this and set line.Args[0] == line.Nick.
	// We should consider this as "addressing" us too, and set Addressed = true
	if nl.Args[0] == irc.Me.Nick {
		nl.Args[0] = nl.Nick
		nl.Addressed = true
	}
	return nl
}
Example #11
0
// Handle privmsgs
func handle_privmsg(conn *irc.Conn, line *irc.Line) {
	text := line.Text()
	args := strings.Split(text, " ")
	//var url_regex = regexp.MustCompile(`\Ahttps?://([[:alnum:]][a-zA-Z0-9-]{1,61}[[:alnum:]]\.?){2,3}((%[0-9A-Fa-f]{2}|[-_.!~*';/?#:@&=+$,A-Za-z0-9])+)?\z`)
	var url_regex = regexp.MustCompile(`\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))`)

	// handle a prefixed command
	if strings.Index(text, RC.CmdPrefix) == 0 {
		handle_command(conn, line, args)
	} else if len(url_regex.FindString(text)) > 0 {
		s := GetScanner()
		s.Handle(conn, line, text)
	}
	// Handle mocking
	if RC.Mocking[line.Nick] {
		SendMessage(conn, "Hey, everybody! "+line.Nick+" said something!", nil)
		SendMessage(conn, line.Nick+": "+line.Text(), nil)
		SendMessage(conn, "Great job, "+line.Nick+"! ╭(ᐛ)و", nil)
	}
}
Example #12
0
// Do some standard processing on incoming lines and dispatch a bot_privmsg
func bot_privmsg(irc *client.Conn, line *client.Line) {
	bot := getState(irc)

	l, p := util.RemovePrefixedNick(strings.TrimSpace(line.Args[1]), irc.Me.Nick)
	// We want line.Args[1] to contain the (possibly) stripped version of itself
	// but modifying the pointer will result in other goroutines seeing the
	// change, so we need to copy line for our own edification.
	nl := &base.Line{Line: *line.Copy()}
	nl.Args[1] = l
	nl.Addressed = p
	// If we're being talked to in private, line.Args[0] will contain our Nick.
	// To ensure the replies go to the right place (without performing this
	// check everywhere) test for this and set line.Args[0] == line.Nick.
	// We should consider this as "addressing" us too, and set Addressed = true
	if nl.Args[0] == irc.Me.Nick {
		nl.Args[0] = nl.Nick
		nl.Addressed = true
	}
	bot.Dispatch("bot_privmsg", nl)
}
Example #13
0
func (ib *IrcBot) handleNotice(conn *irc.Conn, line *irc.Line) {
	log.Printf("[NOTICE] %v", line.Text())
	ib.logToConsole("[NOTICE] " + line.Text())
}
Example #14
0
func (ib *IrcBot) log372(conn *irc.Conn, line *irc.Line) {
	ib.logToConsole(line.Text())
}
Example #15
0
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))
	}()
}