mirror of
				https://github.com/fluffle/goirc
				synced 2025-11-03 19:48:04 +00:00 
			
		
		
		
	Added more documentation, commands are a list now, not a set :)
This commit is contained in:
		
							parent
							
								
									89c23a7787
								
							
						
					
					
						commit
						e8eba53828
					
				
					 3 changed files with 36 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -32,6 +32,7 @@ func main() {
 | 
			
		|||
		func(conn *irc.Conn, line *irc.Line) { quit <- true })
 | 
			
		||||
 | 
			
		||||
	// Set up some simple commands, !bark and !roll.
 | 
			
		||||
	// The !roll command will also get the  "!help roll" command also.
 | 
			
		||||
	c.SimpleCommandFunc("bark", func(conn *irc.Conn, line *irc.Line) { conn.Privmsg(line.Target(), "Woof Woof") })
 | 
			
		||||
	c.SimpleCommandHelpFunc("roll", `Rolls a d6, "roll <n>" to roll n dice at once.`, func(conn *irc.Conn, line *irc.Line) {
 | 
			
		||||
		count := 1
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,9 @@ func main() {
 | 
			
		|||
	})
 | 
			
		||||
 | 
			
		||||
	// Set up some commands that are triggered by a regex in a message.
 | 
			
		||||
	// It is important to see that UrlRegex could actually respond to some
 | 
			
		||||
	// of the Url's that YouTubeRegex listens to, because of this we put the
 | 
			
		||||
	// YouTube command at a higher priority, this way it will take precedence.
 | 
			
		||||
	c.CommandFunc(irc.YouTubeRegex, irc.YouTubeFunc, 10)
 | 
			
		||||
	c.CommandFunc(irc.UrlRegex, irc.UrlFunc, 0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ type Conn struct {
 | 
			
		|||
 | 
			
		||||
	// Handlers and Commands
 | 
			
		||||
	handlers *hSet
 | 
			
		||||
	commands *commandSet
 | 
			
		||||
	commands *commandList
 | 
			
		||||
 | 
			
		||||
	// State tracker for nicks and channels
 | 
			
		||||
	ST         state.StateTracker
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ func Client(nick string, args ...string) *Conn {
 | 
			
		|||
		cLoop:      make(chan bool),
 | 
			
		||||
		cPing:      make(chan bool),
 | 
			
		||||
		handlers:   handlerSet(),
 | 
			
		||||
		commands:   newCommandSet(),
 | 
			
		||||
		commands:   newCommandList(),
 | 
			
		||||
		stRemovers: make([]Remover, 0, len(stHandlers)),
 | 
			
		||||
		PingFreq:   3 * time.Minute,
 | 
			
		||||
		NewNick:    func(s string) string { return s + "_" },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,12 @@ type Handler interface {
 | 
			
		|||
	Handle(*Conn, *Line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HandlerFunc func(*Conn, *Line)
 | 
			
		||||
 | 
			
		||||
func (hf HandlerFunc) Handle(conn *Conn, line *Line) {
 | 
			
		||||
	hf(conn, line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// And when they've been added to the client they are removable.
 | 
			
		||||
type Remover interface {
 | 
			
		||||
	Remove()
 | 
			
		||||
| 
						 | 
				
			
			@ -25,12 +31,6 @@ func (r RemoverFunc) Remove() {
 | 
			
		|||
	r()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type HandlerFunc func(*Conn, *Line)
 | 
			
		||||
 | 
			
		||||
func (hf HandlerFunc) Handle(conn *Conn, line *Line) {
 | 
			
		||||
	hf(conn, line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type hList struct {
 | 
			
		||||
	start, end *hNode
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ func (hs *hSet) dispatch(conn *Conn, line *Line) {
 | 
			
		|||
 | 
			
		||||
type command struct {
 | 
			
		||||
	handler  Handler
 | 
			
		||||
	set      *commandSet
 | 
			
		||||
	set      *commandList
 | 
			
		||||
	regex    string
 | 
			
		||||
	priority int
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -137,42 +137,42 @@ func (c *command) Remove() {
 | 
			
		|||
	c.set.remove(c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commandSet struct {
 | 
			
		||||
type commandList struct {
 | 
			
		||||
	set []*command
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newCommandSet() *commandSet {
 | 
			
		||||
	return &commandSet{}
 | 
			
		||||
func newCommandList() *commandList {
 | 
			
		||||
	return &commandList{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cs *commandSet) add(regex string, handler Handler, priority int) Remover {
 | 
			
		||||
	cs.Lock()
 | 
			
		||||
	defer cs.Unlock()
 | 
			
		||||
func (cl *commandList) add(regex string, handler Handler, priority int) Remover {
 | 
			
		||||
	cl.Lock()
 | 
			
		||||
	defer cl.Unlock()
 | 
			
		||||
	c := &command{
 | 
			
		||||
		handler:  handler,
 | 
			
		||||
		set:      cs,
 | 
			
		||||
		set:      cl,
 | 
			
		||||
		regex:    regex,
 | 
			
		||||
		priority: priority,
 | 
			
		||||
	}
 | 
			
		||||
	// Check for exact regex matches. This will filter out any repeated SimpleCommands.
 | 
			
		||||
	for _, c := range cs.set {
 | 
			
		||||
	for _, c := range cl.set {
 | 
			
		||||
		if c.regex == regex {
 | 
			
		||||
			logging.Error("Command prefix '%s' already registered.", regex)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cs.set = append(cs.set, c)
 | 
			
		||||
	cl.set = append(cl.set, c)
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cs *commandSet) remove(c *command) {
 | 
			
		||||
	cs.Lock()
 | 
			
		||||
	defer cs.Unlock()
 | 
			
		||||
	for index, value := range cs.set {
 | 
			
		||||
func (cl *commandList) remove(c *command) {
 | 
			
		||||
	cl.Lock()
 | 
			
		||||
	defer cl.Unlock()
 | 
			
		||||
	for index, value := range cl.set {
 | 
			
		||||
		if value == c {
 | 
			
		||||
			copy(cs.set[index:], cs.set[index+1:])
 | 
			
		||||
			cs.set = cs.set[:len(cs.set)-1]
 | 
			
		||||
			copy(cl.set[index:], cl.set[index+1:])
 | 
			
		||||
			cl.set = cl.set[:len(cl.set)-1]
 | 
			
		||||
			c.set = nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -180,11 +180,11 @@ func (cs *commandSet) remove(c *command) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Matches the command with the highest priority.
 | 
			
		||||
func (cs *commandSet) match(txt string) (handler Handler) {
 | 
			
		||||
	cs.RLock()
 | 
			
		||||
	defer cs.RUnlock()
 | 
			
		||||
func (cl *commandList) match(txt string) (handler Handler) {
 | 
			
		||||
	cl.RLock()
 | 
			
		||||
	defer cl.RUnlock()
 | 
			
		||||
	maxPriority := math.MinInt32
 | 
			
		||||
	for _, c := range cs.set {
 | 
			
		||||
	for _, c := range cl.set {
 | 
			
		||||
		if c.priority > maxPriority {
 | 
			
		||||
			if regex, error := regexp.Compile(c.regex); error == nil {
 | 
			
		||||
				if regex.MatchString(txt) {
 | 
			
		||||
| 
						 | 
				
			
			@ -203,12 +203,12 @@ func (cs *commandSet) match(txt string) (handler Handler) {
 | 
			
		|||
// "PRIVMSG", "JOIN", etc. but all the numeric replies are left as ascii
 | 
			
		||||
// strings of digits like "332" (mainly because I really didn't feel like
 | 
			
		||||
// putting massive constant tables in).
 | 
			
		||||
func (conn *Conn) Handle(name string, h Handler) Remover {
 | 
			
		||||
	return conn.handlers.add(name, h)
 | 
			
		||||
func (conn *Conn) Handle(name string, handler Handler) Remover {
 | 
			
		||||
	return conn.handlers.add(name, handler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conn *Conn) HandleFunc(name string, hf HandlerFunc) Remover {
 | 
			
		||||
	return conn.Handle(name, hf)
 | 
			
		||||
func (conn *Conn) HandleFunc(name string, handlerFunc HandlerFunc) Remover {
 | 
			
		||||
	return conn.Handle(name, handlerFunc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conn *Conn) Command(regex string, handler Handler, priority int) Remover {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue