BREAKING CHANGES: Run callbacks in main thread and int callback id.
Execute callbacks in main thread. This will break callbacks that use a long time to execute. Create your own thread in AddCallback using gorutines on long running callbacks. Use deterministic IDs for AddCallback. Changes the id from SHA-hash to int.
This commit is contained in:
parent
ab737c68eb
commit
da78ed515c
@ -46,6 +46,20 @@ AddCallback Example
|
||||
//event.Arguments[0] Contains the channel
|
||||
});
|
||||
|
||||
Please note: Callbacks are run in the main thread. If a callback needs a long
|
||||
time to execute please run it in a new thread.
|
||||
|
||||
Example:
|
||||
|
||||
ircobj.AddCallback("PRIVMSG", func(event *irc.Event) {
|
||||
go func(event *irc.Event) {
|
||||
//event.Message() contains the message
|
||||
//event.Nick Contains the sender
|
||||
//event.Arguments[0] Contains the channel
|
||||
}(e)
|
||||
});
|
||||
|
||||
|
||||
Commands
|
||||
--------
|
||||
ircobj := irc.IRC("<nick>", "<user>") //Create new ircobj
|
||||
|
@ -1,10 +1,6 @@
|
||||
package irc
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -14,23 +10,22 @@ import (
|
||||
// which takes only an Event pointer as parameter. Valid event codes are all
|
||||
// IRC/CTCP commands and error/response codes. This function returns the ID of
|
||||
// the registered callback for later management.
|
||||
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) string {
|
||||
func (irc *Connection) AddCallback(eventcode string, callback func(*Event)) int {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
id := 0
|
||||
if _, ok := irc.events[eventcode]; !ok {
|
||||
irc.events[eventcode] = make(map[string]func(*Event))
|
||||
irc.events[eventcode] = make(map[int]func(*Event))
|
||||
id = 0
|
||||
} else {
|
||||
id = len(irc.events[eventcode])
|
||||
}
|
||||
h := sha1.New()
|
||||
rawId := []byte(fmt.Sprintf("%v%d", reflect.ValueOf(callback).Pointer(), rand.Int63()))
|
||||
h.Write(rawId)
|
||||
id := fmt.Sprintf("%x", h.Sum(nil))
|
||||
irc.events[eventcode][id] = callback
|
||||
return id
|
||||
}
|
||||
|
||||
// Remove callback i (ID) from the given event code. This functions returns
|
||||
// true upon success, false if any error occurs.
|
||||
func (irc *Connection) RemoveCallback(eventcode string, i string) bool {
|
||||
func (irc *Connection) RemoveCallback(eventcode string, i int) bool {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if event, ok := irc.events[eventcode]; ok {
|
||||
@ -52,7 +47,7 @@ func (irc *Connection) ClearCallback(eventcode string) bool {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if _, ok := irc.events[eventcode]; ok {
|
||||
irc.events[eventcode] = make(map[string]func(*Event))
|
||||
irc.events[eventcode] = make(map[int]func(*Event))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -61,7 +56,7 @@ func (irc *Connection) ClearCallback(eventcode string) bool {
|
||||
}
|
||||
|
||||
// Replace callback i (ID) associated with a given event code with a new callback function.
|
||||
func (irc *Connection) ReplaceCallback(eventcode string, i string, callback func(*Event)) {
|
||||
func (irc *Connection) ReplaceCallback(eventcode string, i int, callback func(*Event)) {
|
||||
eventcode = strings.ToUpper(eventcode)
|
||||
|
||||
if event, ok := irc.events[eventcode]; ok {
|
||||
@ -120,7 +115,7 @@ func (irc *Connection) RunCallbacks(event *Event) {
|
||||
}
|
||||
|
||||
for _, callback := range callbacks {
|
||||
go callback(event)
|
||||
callback(event)
|
||||
}
|
||||
} else if irc.VerboseCallbackHandler {
|
||||
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
|
||||
@ -128,21 +123,22 @@ func (irc *Connection) RunCallbacks(event *Event) {
|
||||
|
||||
if callbacks, ok := irc.events["*"]; ok {
|
||||
if irc.VerboseCallbackHandler {
|
||||
irc.Log.Printf("Wildcard %v (%v) >> %#v\n", event.Code, len(callbacks), event)
|
||||
irc.Log.Printf("%v (0) >> %#v\n", event.Code, event)
|
||||
}
|
||||
|
||||
for _, callback := range callbacks {
|
||||
go callback(event)
|
||||
callback(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up some initial callbacks to handle the IRC/CTCP protocol.
|
||||
func (irc *Connection) setupCallbacks() {
|
||||
irc.events = make(map[string]map[string]func(*Event))
|
||||
irc.events = make(map[string]map[int]func(*Event))
|
||||
|
||||
//Handle error events
|
||||
irc.AddCallback("ERROR", func(e *Event) { irc.Disconnect() })
|
||||
//Handle error events. This has to be called in a new thred to allow
|
||||
//readLoop to exit
|
||||
irc.AddCallback("ERROR", func(e *Event) { go irc.Disconnect() })
|
||||
|
||||
//Handle ping events
|
||||
irc.AddCallback("PING", func(e *Event) { irc.SendRaw("PONG :" + e.Message()) })
|
||||
@ -223,7 +219,3 @@ func (irc *Connection) setupCallbacks() {
|
||||
irc.nickcurrent = e.Arguments[0]
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ type Connection struct {
|
||||
nickcurrent string //The nickname we currently have.
|
||||
user string
|
||||
registered bool
|
||||
events map[string]map[string]func(*Event)
|
||||
events map[string]map[int]func(*Event)
|
||||
|
||||
QuitMessage string
|
||||
lastMessage time.Time
|
||||
|
60
irc_test.go
60
irc_test.go
@ -184,33 +184,26 @@ func TestConnection(t *testing.T) {
|
||||
irccon2 := IRC("go-eventirc2", "go-eventirc2")
|
||||
irccon2.VerboseCallbackHandler = true
|
||||
irccon2.Debug = true
|
||||
err := irccon1.Connect("irc.freenode.net:6667")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
err = irccon2.Connect("irc.freenode.net:6667")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
|
||||
irccon1.AddCallback("001", func(e *Event) { irccon1.Join("#go-eventirc") })
|
||||
irccon2.AddCallback("001", func(e *Event) { irccon2.Join("#go-eventirc") })
|
||||
con2ok := false
|
||||
irccon1.AddCallback("366", func(e *Event) {
|
||||
t := time.NewTicker(1 * time.Second)
|
||||
i := 10
|
||||
for {
|
||||
<-t.C
|
||||
irccon1.Privmsgf("#go-eventirc", "Test Message%d\n", i)
|
||||
if con2ok {
|
||||
i -= 1
|
||||
go func(e *Event) {
|
||||
t := time.NewTicker(1 * time.Second)
|
||||
i := 10
|
||||
for {
|
||||
<-t.C
|
||||
irccon1.Privmsgf("#go-eventirc", "Test Message%d\n", i)
|
||||
if con2ok {
|
||||
i -= 1
|
||||
}
|
||||
if i == 0 {
|
||||
t.Stop()
|
||||
irccon1.Quit()
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
t.Stop()
|
||||
irccon1.Quit()
|
||||
}
|
||||
}
|
||||
}(e)
|
||||
})
|
||||
|
||||
irccon2.AddCallback("366", func(e *Event) {
|
||||
@ -231,6 +224,18 @@ func TestConnection(t *testing.T) {
|
||||
t.Fatal("Nick change did not work!")
|
||||
}
|
||||
})
|
||||
|
||||
err := irccon1.Connect("irc.freenode.net:6667")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
err = irccon2.Connect("irc.freenode.net:6667")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
|
||||
go irccon2.Loop()
|
||||
irccon1.Loop()
|
||||
}
|
||||
@ -241,11 +246,6 @@ func TestConnectionSSL(t *testing.T) {
|
||||
irccon.Debug = true
|
||||
irccon.UseTLS = true
|
||||
irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
err := irccon.Connect("irc.freenode.net:7000")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
irccon.AddCallback("001", func(e *Event) { irccon.Join("#go-eventirc") })
|
||||
|
||||
irccon.AddCallback("366", func(e *Event) {
|
||||
@ -254,5 +254,11 @@ func TestConnectionSSL(t *testing.T) {
|
||||
irccon.Quit()
|
||||
})
|
||||
|
||||
err := irccon.Connect("irc.freenode.net:7000")
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
t.Fatal("Can't connect to freenode.")
|
||||
}
|
||||
|
||||
irccon.Loop()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user