<commit_before>package bot

import (
	"fmt"
	"github.com/aarondl/ultimateq/irc"
	"sync"
)

// coreHandler is the bot's main handling struct. As such it has access directly
// to the bot itself. It's used to deal with mission critical events such as
// pings, connects, disconnects etc.
type coreHandler struct {
	// The bot this core handler belongs to.
	bot *Bot

	// How many nicks have been sent.
	nickvalue int

	// Protect access to core Handler
	protect sync.RWMutex
}

// HandleRaw implements the dispatch.EventHandler interface so the bot can
// deal with all irc messages coming in.
func (c *coreHandler) HandleRaw(msg *irc.IrcMessage, sender irc.Sender) {
	switch msg.Name {

	case irc.PING:
		sender.Writeln(irc.PONG + " :" + msg.Args[0])

	case irc.CONNECT:
		c.protect.Lock()
		server := c.getServer(sender)
		c.nickvalue = 0
		c.protect.Unlock()
		sender.Writeln("NICK :" + server.conf.GetNick())
		sender.Writeln(fmt.Sprintf(
			"USER %v 0 * :%v",
			server.conf.GetUsername(),
			server.conf.GetRealname(),
		))

	case irc.ERR_NICKNAMEINUSE:
		c.protect.Lock()
		server := c.getServer(sender)
		var nick string
		if c.nickvalue == 0 && 0 < len(server.conf.GetAltnick()) {
			nick = server.conf.GetAltnick()
			c.nickvalue += 1
		} else {
			nick = server.conf.GetNick()
			for i := 0; i < c.nickvalue; i++ {
				nick += "_"
			}
			c.nickvalue += 1
		}
		c.protect.Unlock()
		sender.Writeln("NICK :" + nick)

	case irc.RPL_BOUNCE:
		c.protect.Lock()
		server := c.getServer(sender)
		c.protect.Unlock()
		server.caps.ParseProtoCaps(msg)
		server.dispatcher.Protocaps(server.caps)

	}
}

// getServer is a helper to look up the server based on sender key.
func (c coreHandler) getServer(sender irc.Sender) *Server {
	c.bot.serversProtect.RLock()
	defer c.bot.serversProtect.RUnlock()
	return c.bot.servers[sender.GetKey()]
}<commit_msg>Make core handler lock less.<commit_after>package bot

import (
	"fmt"
	"github.com/aarondl/ultimateq/irc"
	"sync"
)

// coreHandler is the bot's main handling struct. As such it has access directly
// to the bot itself. It's used to deal with mission critical events such as
// pings, connects, disconnects etc.
type coreHandler struct {
	// The bot this core handler belongs to.
	bot *Bot

	// How many nicks have been sent.
	nickvalue int

	// Protect access to core Handler
	protect sync.RWMutex
}

// HandleRaw implements the dispatch.EventHandler interface so the bot can
// deal with all irc messages coming in.
func (c *coreHandler) HandleRaw(msg *irc.IrcMessage, sender irc.Sender) {
	switch msg.Name {

	case irc.PING:
		sender.Writeln(irc.PONG + " :" + msg.Args[0])

	case irc.CONNECT:
		c.protect.Lock()
		server := c.getServer(sender)
		c.nickvalue = 0
		c.protect.Unlock()
		sender.Writeln("NICK :" + server.conf.GetNick())
		sender.Writeln(fmt.Sprintf(
			"USER %v 0 * :%v",
			server.conf.GetUsername(),
			server.conf.GetRealname(),
		))

	case irc.ERR_NICKNAMEINUSE:
		c.protect.Lock()
		server := c.getServer(sender)
		var nick string
		if c.nickvalue == 0 && 0 < len(server.conf.GetAltnick()) {
			nick = server.conf.GetAltnick()
			c.nickvalue += 1
		} else {
			nick = server.conf.GetNick()
			for i := 0; i < c.nickvalue; i++ {
				nick += "_"
			}
			c.nickvalue += 1
		}
		c.protect.Unlock()
		sender.Writeln("NICK :" + nick)

	case irc.RPL_BOUNCE:
		c.protect.Lock()
		server := c.getServer(sender)
		c.protect.Unlock()
		server.caps.ParseProtoCaps(msg)
		server.dispatcher.Protocaps(server.caps)

	}
}

// getServer is a helper to look up the server based on sender.
func (c coreHandler) getServer(sender irc.Sender) *Server {
	s, ok := sender.(ServerSender)
	if ok {
		return s.server
	}

	c.bot.serversProtect.RLock()
	defer c.bot.serversProtect.RUnlock()
	return c.bot.servers[sender.GetKey()]
}
{'fraction_non_alphanumeric': 0.13241525423728814, 'fraction_numerical': 0.00423728813559322, 'mean_word_length': 3.407234539089848, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5480817', 'n_tokens_mistral': 1487, 'n_tokens_neox': 1351, 'n_words': 358}