Bladeren bron

Merge pull request #6 from postman0/master

generic lua events
Пётр 9 jaren geleden
bovenliggende
commit
6aeb0ea27a
3 gewijzigde bestanden met toevoegingen van 91 en 56 verwijderingen
  1. 85 51
      luaexecutor/executor.go
  2. 2 1
      main.go
  3. 4 4
      static/bootstrap.lua

+ 85 - 51
luaexecutor/executor.go

@@ -11,19 +11,19 @@ import (
 )
 
 const sleepDuration time.Duration = 1 * time.Second
-const callbacksLocation string = "chatclbks"
+const callbacksLocation string = "clbks"
 
-// An utility struct for incoming messages.
-type IncomingMessage struct {
-	Sender string
-	Body   string
+// An utility struct for incoming events.
+type IncomingEvent struct {
+	Type string
+	Data map[string]string
 }
 
 // Executor executes Lua scripts in a shared Lua VM.
 type Executor struct {
 	incomingScripts chan string
 	outgoingMsgs    chan string
-	incomingMsgs    chan IncomingMessage
+	incomingEvents  chan IncomingEvent
 	stateMutex      sync.Mutex
 	state           *lua.State
 	xmppStream      stream.Stream
@@ -33,7 +33,7 @@ func NewExecutor(s stream.Stream) *Executor {
 	e := &Executor{
 		incomingScripts: make(chan string),
 		outgoingMsgs:    make(chan string),
-		incomingMsgs:    make(chan IncomingMessage),
+		incomingEvents:  make(chan IncomingEvent),
 	}
 	e.xmppStream = s
 	e.state = lua.NewState()
@@ -46,12 +46,27 @@ func NewExecutor(s stream.Stream) *Executor {
 	}
 
 	registerClbk := func(l *lua.State) int {
-		// get callbacks table
+		// get events table
 		l.PushString(callbacksLocation)
 		l.Table(lua.RegistryIndex)
+		// get callbacks table
+		evtName := lua.CheckString(l, 1)
+		l.PushString(evtName)
+		l.Table(-2)
+		// create new table if one doesn't exist
+		if l.IsNil(-1) {
+			l.Pop(1)
+			// create and add table to the events table
+			l.PushString(evtName)
+			l.NewTable()
+			l.SetTable(-3)
+			// and get it back
+			l.PushString(evtName)
+			l.Table(-2)
+		}
 		// set callback
-		l.PushValue(1)
 		l.PushValue(2)
+		l.PushValue(3)
 		l.SetTable(-3)
 		l.SetTop(0)
 		return 0
@@ -59,34 +74,43 @@ func NewExecutor(s stream.Stream) *Executor {
 
 	listClbks := func(l *lua.State) int {
 		clbkNames := []string{}
-		// get callbacks table
+		// get events table
 		l.PushString(callbacksLocation)
 		l.Table(lua.RegistryIndex)
-		// loop
-		l.PushNil()
-		for l.Next(-2) {
-			key, ok := l.ToString(-2)
-			// ignore non-string shit
-			if ok {
-				clbkNames = append(clbkNames, key)
+		// get callbacks for the event
+		evtName := lua.CheckString(l, 1)
+		l.PushString(evtName)
+		l.Table(-2)
+		if !l.IsNil(-1) {
+			// loop
+			l.PushNil()
+			for l.Next(-2) {
+				key, ok := l.ToString(-2)
+				// ignore non-string shit
+				if ok {
+					clbkNames = append(clbkNames, key)
+				}
+				l.Pop(1)
 			}
-			l.Pop(1)
-		}
-		l.SetTop(0)
-		l.NewTable()
-		// build a list from callback names
-		for i, key := range clbkNames {
-			l.PushInteger(i + 1)
-			l.PushString(key)
-			l.SetTable(-3)
+			l.SetTop(0)
+			l.NewTable()
+			// build a list from callback names
+			for i, key := range clbkNames {
+				l.PushInteger(i + 1)
+				l.PushString(key)
+				l.SetTable(-3)
+			}
+		} else {
+			l.SetTop(0)
+			l.PushNil()
 		}
 		return 1
 	}
 
 	var chatLibrary = []lua.RegistryFunction{
 		lua.RegistryFunction{"send", send},
-		lua.RegistryFunction{"onmessage", registerClbk},
-		lua.RegistryFunction{"listmsghandlers", listClbks},
+		lua.RegistryFunction{"addEventHandler", registerClbk},
+		lua.RegistryFunction{"listEventHandlers", listClbks},
 	}
 
 	lua.NewLibrary(e.state, chatLibrary)
@@ -127,31 +151,42 @@ func (e *Executor) sendingRoutine() {
 	}
 }
 
-func (e *Executor) processIncomingMsgs() {
-	for msg := range e.incomingMsgs {
+func (e *Executor) processIncomingEvents() {
+	for evt := range e.incomingEvents {
 		e.stateMutex.Lock()
-		// get callbacks table
+		// get events table
 		e.state.PushString(callbacksLocation)
 		e.state.Table(lua.RegistryIndex)
+		// get callbacks table for the specific event
+		e.state.PushString(evt.Type)
+		e.state.Table(-2)
 		// loop over callbacks
-		e.state.PushNil()
-		for e.state.Next(-2) {
-			if e.state.IsFunction(-1) {
-				e.state.PushString(msg.Sender)
-				e.state.PushString(msg.Body)
-				err := e.state.ProtectedCall(2, 0, 0)
-				if err != nil {
-					m := entity.MSG(entity.GROUPCHAT)
-					m.To = "golang@conference.jabber.ru"
-					m.Body, _ = e.state.ToString(-1)
-					e.xmppStream.Write(entity.ProduceStatic(m))
+		if !e.state.IsNil(-1) {
+			e.state.PushNil()
+			for e.state.Next(-2) {
+				if e.state.IsFunction(-1) {
+					// create the table which will be passed to the handler
+					e.state.NewTable()
+					// loop over the event data, populating the table
+					for k, v := range evt.Data {
+						e.state.PushString(k)
+						e.state.PushString(v)
+						e.state.SetTable(-3)
+					}
+					err := e.state.ProtectedCall(1, 0, 0)
+					if err != nil {
+						m := entity.MSG(entity.GROUPCHAT)
+						m.To = "golang@conference.jabber.ru"
+						m.Body, _ = e.state.ToString(-1)
+						e.xmppStream.Write(entity.ProduceStatic(m))
+						e.state.Pop(1)
+					}
+				} else {
 					e.state.Pop(1)
 				}
-			} else {
-				e.state.Pop(1)
 			}
 		}
-		// pop callbacks table
+		// pop callbacks table or nil value
 		e.state.Pop(1)
 		e.stateMutex.Unlock()
 	}
@@ -160,12 +195,12 @@ func (e *Executor) processIncomingMsgs() {
 func (e *Executor) Start() {
 	go e.sendingRoutine()
 	go e.execute()
-	go e.processIncomingMsgs()
+	go e.processIncomingEvents()
 }
 
 func (e *Executor) Stop() {
 	close(e.incomingScripts)
-	close(e.incomingMsgs)
+	close(e.incomingEvents)
 	close(e.outgoingMsgs)
 }
 
@@ -173,8 +208,7 @@ func (e *Executor) Run(script string) {
 	e.incomingScripts <- script
 }
 
-// Call this on every incoming message - it's required for
-// chat.onmessage to work.
-func (e *Executor) NewMessage(msg IncomingMessage) {
-	e.incomingMsgs <- msg
+// Call this on every event - it's required for event handlers to work
+func (e *Executor) NewEvent(evt IncomingEvent) {
+	e.incomingEvents <- evt
 }

+ 2 - 1
main.go

@@ -135,7 +135,8 @@ func bot(st stream.Stream) error {
 						posts.Unlock()
 					}
 					if sender != ME {
-						executor.NewMessage(luaexecutor.IncomingMessage{sender, e.Body})
+						executor.NewEvent(luaexecutor.IncomingEvent{"message",
+							map[string]string{"sender": sender, "body": e.Body}})
 						switch {
 						/*case strings.EqualFold(strings.TrimSpace(e.Body), "пщ"):
 						go func() {

+ 4 - 4
static/bootstrap.lua

@@ -1,7 +1,7 @@
-chat.onmessage("пщ", function(s, m)
-   if m == "пщ" then chat.send("пщ") end
+chat.addEventHandler("message", "пщ", function(evt)
+   if evt.body == "пщ" then chat.send("пщ") end
 end)
 
-chat.onmessage("зига", function(s, m)
-   if m == "o/" then chat.send("\\o,") end
+chat.addEventHandler("message", "зига", function(evt)
+   if evt.body == "o/" then chat.send("\\o,") end
 end)