potentially fix events being dropped

This commit is contained in:
Liam Stanley 2016-11-13 05:27:53 -05:00
parent 747aa46bf3
commit c76d4bd6d2
5 changed files with 38 additions and 48 deletions

@ -2,20 +2,17 @@ package girc
// handleEvent runs the necessary callbacks for the incoming event
func (c *Client) handleEvent(event *Event) {
// log the event
c.log.Print(event.String())
// wildcard callbacks first
if callbacks, ok := c.callbacks[ALLEVENTS]; ok {
for i := 0; i < len(callbacks); i++ {
callbacks[i].Execute(c, event)
callbacks[i].Execute(c, *event)
}
}
// regular non-threaded callbacks
if callbacks, ok := c.callbacks[event.Command]; ok {
for i := 0; i < len(callbacks); i++ {
callbacks[i].Execute(c, event)
callbacks[i].Execute(c, *event)
}
}
@ -24,7 +21,7 @@ func (c *Client) handleEvent(event *Event) {
// "routine_". e.g. "routine_JOIN".
if callbacks, ok := c.callbacks["routine_"+event.Command]; ok {
for i := 0; i < len(callbacks); i++ {
go callbacks[i].Execute(c, event)
go callbacks[i].Execute(c, *event)
}
}
}
@ -35,25 +32,25 @@ func (c *Client) AddCallbackHandler(cmd string, callback Callback) {
}
// AddCallback registers the callback function for the given command
func (c *Client) AddCallback(cmd string, callback func(c *Client, e *Event)) {
func (c *Client) AddCallback(cmd string, callback func(c *Client, e Event)) {
c.callbacks[cmd] = append(c.callbacks[cmd], CallbackFunc(callback))
}
// AddBgCallback registers the callback function for the given command
// and executes it in a go-routine, after all other callbacks have been ran
func (c *Client) AddBgCallback(cmd string, callback func(c *Client, e *Event)) {
func (c *Client) AddBgCallback(cmd string, callback func(c *Client, e Event)) {
c.callbacks["routine_"+cmd] = append(c.callbacks["routine_"+cmd], CallbackFunc(callback))
}
// Callback is an interface to handle IRC events
type Callback interface {
Execute(*Client, *Event)
Execute(*Client, Event)
}
// CallbackFunc is a type that represents the function necessary to implement Callback
type CallbackFunc func(c *Client, e *Event)
type CallbackFunc func(c *Client, e Event)
// Execute calls the CallbackFunc with the sender and irc message
func (f CallbackFunc) Execute(c *Client, e *Event) {
func (f CallbackFunc) Execute(c *Client, e Event) {
f(c, e)
}

15
conn.go

@ -25,13 +25,9 @@ type Conn struct {
// NewConn returns a new Conn using rwc for i/o
func NewConn(rwc io.ReadWriteCloser) *Conn {
return &Conn{
Encoder: Encoder{
writer: rwc,
},
Decoder: Decoder{
reader: bufio.NewReader(rwc),
},
conn: rwc,
Encoder: Encoder{writer: rwc},
Decoder: Decoder{reader: bufio.NewReader(rwc)},
conn: rwc,
}
}
@ -70,6 +66,7 @@ func (dec *Decoder) Decode() (e *Event, err error) {
dec.mu.Lock()
dec.line, err = dec.reader.ReadString(delim)
dec.mu.Unlock()
if err != nil {
return nil, err
}
@ -99,14 +96,14 @@ func (enc *Encoder) Encode(e *Event) (err error) {
// Write writes len(p) bytes from p followed by CR+LF. goroutine safe.
func (enc *Encoder) Write(p []byte) (n int, err error) {
enc.mu.Lock()
defer enc.mu.Unlock()
n, err = enc.writer.Write(p)
if err != nil {
enc.mu.Unlock()
return
}
_, err = enc.writer.Write(endline)
enc.mu.Unlock()
return
}

@ -2,6 +2,7 @@ package main
import (
"log"
"os"
"github.com/Liamraystanley/girc"
@ -9,13 +10,14 @@ import (
func main() {
conf := girc.Config{
Server: "irc.byteirc.org",
Port: 6667,
Nick: "test",
User: "test1",
Name: "Example bot",
MaxRetries: 3,
Logger: os.Stdout,
Server: "irc.byteirc.org",
Port: 6667,
Nick: "test",
User: "test1",
Name: "Example bot",
MaxRetries: 3,
Logger: os.Stdout,
DisableHelpers: false,
}
client := girc.New(conf)
@ -29,6 +31,6 @@ func main() {
client.Wait()
}
func registerConnect(c *girc.Client, e *girc.Event) {
func registerConnect(c *girc.Client, e girc.Event) {
c.Send(&girc.Event{Command: girc.JOIN, Params: []string{"#dev"}})
}

@ -1,10 +1,6 @@
package girc
import (
"time"
"github.com/y0ssar1an/q"
)
import "time"
func (c *Client) registerHelpers() {
c.AddBgCallback(SUCCESS, handleWelcome)
@ -29,7 +25,7 @@ func (c *Client) registerHelpers() {
// that enough time has passed and now they can send commands
//
// should always run in separate thread
func handleWelcome(c *Client, e *Event) {
func handleWelcome(c *Client, e Event) {
// this should be the nick that the server gives us. 99% of the time, it's the
// one we supplied during connection, but some networks will insta-rename users.
if len(e.Params) > 0 {
@ -43,18 +39,18 @@ func handleWelcome(c *Client, e *Event) {
// nickCollisionHandler helps prevent the client from having conflicting
// nicknames with another bot, user, etc
func nickCollisionHandler(c *Client, e *Event) {
func nickCollisionHandler(c *Client, e Event) {
c.SetNick(c.GetNick() + "_")
}
// handlePING helps respond to ping requests from the server
func handlePING(c *Client, e *Event) {
func handlePING(c *Client, e Event) {
// TODO: we should be sending pings too.
c.Send(&Event{Command: PONG, Params: e.Params, Trailing: e.Trailing})
}
// handleJOIN ensures that the state has updated users and channels
func handleJOIN(c *Client, e *Event) {
func handleJOIN(c *Client, e Event) {
if len(e.Params) == 0 {
return
}
@ -66,7 +62,7 @@ func handleJOIN(c *Client, e *Event) {
}
// handlePART ensures that the state is clean of old user and channel entries
func handlePART(c *Client, e *Event) {
func handlePART(c *Client, e Event) {
if len(e.Params) == 0 {
return
}
@ -79,7 +75,7 @@ func handlePART(c *Client, e *Event) {
c.State.deleteUser(e.Params[0], e.Prefix.Name)
}
func handleWHO(c *Client, e *Event) {
func handleWHO(c *Client, e Event) {
var channel, user, host, nick string
// assume WHOX related
@ -104,11 +100,9 @@ func handleWHO(c *Client, e *Event) {
c.State.createUserIfNotExists(channel, nick, user, host)
}
func handleKICK(c *Client, e *Event) {
func handleKICK(c *Client, e Event) {
if len(e.Params) < 2 {
// needs at least channel and user
return
}
q.Q(e)
}

12
main.go

@ -205,8 +205,6 @@ func (c *Client) ReadLoop() error {
return c.Reconnect()
}
// TODO: not adding PRIVMSG entries?
log.Printf("sending event: %#v\n", event)
c.Events <- event
}
}
@ -214,12 +212,14 @@ func (c *Client) ReadLoop() error {
// Wait reads from the events channel and sends the events to be handled
// for every message it receives.
func (c *Client) Wait() {
var e *Event
for {
select {
case e = <-c.Events:
log.Printf("received event: %#v\n", e)
c.handleEvent(e)
case event := <-c.Events:
// log the event
c.log.Print(event.String())
// run in the background
go c.handleEvent(event)
case <-c.quitChan:
return
}