diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..69a7a03
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.swp
+bin/
diff --git a/GNUmakefile b/GNUmakefile
new file mode 100644
index 0000000..00b2b5c
--- /dev/null
+++ b/GNUmakefile
@@ -0,0 +1,31 @@
+#
+# Makefile for hookAPI
+#
+# switches:
+# define the ones you want in the CFLAGS definition...
+#
+# TRACE - turn on tracing/debugging code
+#
+#
+#
+#
+
+# Version for distribution
+VER=1_0r1
+
+MAKEFILE=GNUmakefile
+
+# We Use Compact Memory Model
+
+all: bin/example
+ @[ -d bin ] || exit
+
+bin/example: _example/example.go xmpp.go
+ @[ -d bin ] || mkdir bin
+ go build -o $@ _example/example.go
+ @strip $@ || echo "example OK"
+
+clean:
+
+distclean: clean
+ @rm -rf bin
diff --git a/_example/example.go b/_example/example.go
index fbd0b12..d0da4a3 100644
--- a/_example/example.go
+++ b/_example/example.go
@@ -5,10 +5,11 @@ import (
"crypto/tls"
"flag"
"fmt"
- "github.com/mattn/go-xmpp"
+ "github.com/kjx98/go-xmpp"
"log"
"os"
"strings"
+ "time"
)
var server = flag.String("server", "", "server")
@@ -16,7 +17,7 @@ var username = flag.String("username", "", "username")
var password = flag.String("password", "", "password")
var status = flag.String("status", "xa", "status")
var statusMessage = flag.String("status-msg", "I for one welcome our new codebot overlords.", "status message")
-var notls = flag.Bool("notls", false, "No TLS")
+var notls = flag.Bool("notls", true, "No TLS")
var debug = flag.Bool("debug", false, "debug output")
var session = flag.Bool("session", false, "use server session")
@@ -55,6 +56,7 @@ func main() {
Debug: *debug,
Session: *session,
Status: *status,
+ Resource: "bot",
StatusMessage: *statusMessage,
}
@@ -72,18 +74,52 @@ func main() {
}
switch v := chat.(type) {
case xmpp.Chat:
- fmt.Println(v.Remote, v.Text)
+ if v.Type == "roster" {
+ fmt.Println("roster", v.Roster)
+ } else {
+ for _, element := range v.OtherElem {
+ if element.XMLName.Space == "jabber:x:conference" {
+ // if not join
+ talk.JoinMUCNoHistory(v.Remote, "bot")
+ }
+ // composing, paused, active
+ if element.XMLName.Space ==
+ "http://jabber.org/protocol/chatstates" &&
+ element.XMLName.Local == "composing" {
+ fmt.Println(v.Remote, "is composing")
+ }
+ }
+ if strings.TrimSpace(v.Text) != "" {
+ fmt.Println(v.Remote, v.Text)
+ }
+ }
case xmpp.Presence:
- fmt.Println(v.From, v.Show)
+ fmt.Println("Presence:", v.From, v.Show, v.Type)
+ case xmpp.Roster, xmpp.Contact:
+ // TODO: update local roster
+ fmt.Println("Roster/Contact:", v)
+ case xmpp.IQ:
+ // ping ignore
+ if v.Type == "result" && v.ID == "c2s1" {
+ fmt.Printf("Got pong from %s to %s\n", v.From, v.To)
+ }
+ default:
+ fmt.Printf("def: %v\n", v)
}
}
}()
+ // get roster first
+ talk.Roster()
+ talk.SendOrg("")
for {
in := bufio.NewReader(os.Stdin)
line, err := in.ReadString('\n')
if err != nil {
continue
}
+ if len(line) >= 4 && line[:4] == "quit" {
+ break
+ }
line = strings.TrimRight(line, "\n")
tokens := strings.SplitN(line, " ", 2)
@@ -91,4 +127,6 @@ func main() {
talk.Send(xmpp.Chat{Remote: tokens[0], Type: "chat", Text: tokens[1]})
}
}
+ talk.SendOrg("`)) || bytes.Equal(bytes.TrimSpace(v.Query), []byte(``)) {
+ if v.Query.XMLName.Space == "urn:xmpp:ping" {
+ fmt.Println("clientIQ ping")
err := c.SendResultPing(v.ID, v.From)
if err != nil {
return Chat{}, err
}
}
- return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type, Query: v.Query}, nil
+ //
+ // TODO: shall we check XMLName.Local is "query"?
+ if (v.Type == "result" || v.Type == "set") &&
+ v.Query.XMLName.Space == "jabber:iq:roster" {
+ var item rosterItem
+ var r Roster
+ vv := strings.Split(v.Query.InnerXML, "/>")
+ for _, ss := range vv {
+ if strings.TrimSpace(ss) == "" {
+ continue
+ }
+ ss += "/>"
+ if err := xml.Unmarshal([]byte(ss), &item); err != nil {
+ return nil, errors.New("unmarshal roster : " + err.Error())
+ } else {
+ if item.Subscription == "remove" {
+ continue
+ }
+ r = append(r, Contact{item.Jid, item.Name, item.Group})
+ }
+ }
+ return Chat{Type: "roster", Roster: r}, nil
+ }
+ return IQ{ID: v.ID, From: v.From, To: v.To, Type: v.Type,
+ Query: []byte(v.Query.InnerXML)}, nil
}
}
}
@@ -857,14 +882,15 @@ type clientPresence struct {
type clientIQ struct {
// info/query
- XMLName xml.Name `xml:"jabber:client iq"`
- From string `xml:"from,attr"`
- ID string `xml:"id,attr"`
- To string `xml:"to,attr"`
- Type string `xml:"type,attr"` // error, get, result, set
- Query []byte `xml:",innerxml"`
- Error clientError
- Bind bindBind
+ XMLName xml.Name `xml:"jabber:client iq"`
+ From string `xml:"from,attr"`
+ ID string `xml:"id,attr"`
+ To string `xml:"to,attr"`
+ Type string `xml:"type,attr"` // error, get, result, set
+ Query XMLElement `xml:",any"`
+
+ Error clientError
+ Bind bindBind
}
type clientError struct {
@@ -880,11 +906,11 @@ type clientQuery struct {
}
type rosterItem struct {
- XMLName xml.Name `xml:"jabber:iq:roster item"`
- Jid string `xml:",attr"`
- Name string `xml:",attr"`
- Subscription string `xml:",attr"`
- Group []string
+ XMLName xml.Name `xml:"item"`
+ Jid string `xml:"jid,attr"`
+ Name string `xml:"name,attr"`
+ Subscription string `xml:"subscription,attr"`
+ Group []string `"xml:"group"`
}
// Scan XML token stream to find next StartElement.