-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
echobot_example_test.go
101 lines (89 loc) · 2.46 KB
/
echobot_example_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright 2018 The Mellium Contributors.
// Use of this source code is governed by the BSD 2-clause
// license that can be found in the LICENSE file.
package xmpp_test
import (
"context"
"crypto/tls"
"encoding/xml"
"io"
"log"
"mellium.im/sasl"
"mellium.im/xmlstream"
"mellium.im/xmpp"
"mellium.im/xmpp/jid"
"mellium.im/xmpp/stanza"
)
const (
login = "[email protected]"
pass = "just an example don't hardcode passwords"
)
// MessageBody is a message stanza that contains a body. It is normally used for
// chat messages.
type MessageBody struct {
stanza.Message
Body string `xml:"body"`
}
func Example_echobot() {
j := jid.MustParse(login)
s, err := xmpp.DialClientSession(
context.TODO(), j,
xmpp.BindResource(),
xmpp.StartTLS(&tls.Config{
ServerName: j.Domain().String(),
}),
xmpp.SASL("", pass, sasl.ScramSha1Plus, sasl.ScramSha1, sasl.Plain),
)
if err != nil {
log.Printf("Error establishing a session: %q", err)
return
}
defer func() {
log.Println("Closing session…")
if err := s.Close(); err != nil {
log.Printf("Error closing session: %q", err)
}
log.Println("Closing conn…")
if err := s.Conn().Close(); err != nil {
log.Printf("Error closing connection: %q", err)
}
}()
// Send initial presence to let the server know we want to receive messages.
err = s.Send(context.TODO(), stanza.Presence{Type: stanza.AvailablePresence}.Wrap(nil))
if err != nil {
log.Printf("Error sending initial presence: %q", err)
return
}
s.Serve(xmpp.HandlerFunc(func(t xmlstream.TokenReadEncoder, start *xml.StartElement) error {
d := xml.NewTokenDecoder(t)
// Ignore anything that's not a message. In a real system we'd want to at
// least respond to IQs.
if start.Name.Local != "message" {
return nil
}
msg := MessageBody{}
err = d.DecodeElement(&msg, start)
if err != nil && err != io.EOF {
log.Printf("Error decoding message: %q", err)
return nil
}
// Don't reflect messages unless they are chat messages and actually have a
// body.
// In a real world situation we'd probably want to respond to IQs, at least.
if msg.Body == "" || msg.Type != stanza.ChatMessage {
return nil
}
reply := MessageBody{
Message: stanza.Message{
To: msg.From.Bare(),
},
Body: msg.Body,
}
log.Printf("Replying to message %q from %s with body %q", msg.ID, reply.To, reply.Body)
err = t.Encode(reply)
if err != nil {
log.Printf("Error responding to message %q: %q", msg.ID, err)
}
return nil
}))
}