Added roster update to chat client example
This commit is contained in:
parent
3037bf6db8
commit
f3252346c4
|
@ -6,5 +6,5 @@ require (
|
||||||
github.com/awesome-gocui/gocui v0.6.1-0.20191115151952-a34ffb055986
|
github.com/awesome-gocui/gocui v0.6.1-0.20191115151952-a34ffb055986
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.6.1
|
github.com/spf13/viper v1.6.1
|
||||||
gosrc.io/xmpp v0.3.1-0.20191212145100-27130d72926b
|
gosrc.io/xmpp v0.3.1-0.20191223080939-f8f820170e08
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Windows
|
// Windows
|
||||||
chatLogWindow = "clw" // Where (received and sent) messages are logged
|
chatLogWindow = "clw" // Where (received and sent) messages are logged
|
||||||
chatInputWindow = "iw" // Where messages are written
|
chatInputWindow = "iw" // Where messages are written
|
||||||
rawInputWindow = "rw" // Where raw stanzas are written
|
rawInputWindow = "rw" // Where raw stanzas are written
|
||||||
|
@ -71,7 +71,11 @@ func layout(g *gocui.Gui) error {
|
||||||
}
|
}
|
||||||
v.Title = "Contacts"
|
v.Title = "Contacts"
|
||||||
v.Wrap = true
|
v.Wrap = true
|
||||||
v.Autoscroll = true
|
// If we set this to true, the contacts list will "fit" in the window but if the number
|
||||||
|
// of contacts exceeds the maximum height, some contacts will be hidden...
|
||||||
|
// If set to false, we can scroll up and down the contact list... infinitely. Meaning lower lines
|
||||||
|
// will be unlimited and empty... Didn't find a way to quickfix yet.
|
||||||
|
v.Autoscroll = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, err := g.SetView(menuWindow, 0, 0, maxX/5-1, 5*maxY/6-2, 0); err != nil {
|
if v, err := g.SetView(menuWindow, 0, 0, maxX/5-1, 5*maxY/6-2, 0); err != nil {
|
||||||
|
@ -215,7 +219,7 @@ func getLine(g *gocui.Gui, v *gocui.View) error {
|
||||||
if len(cv.ViewBufferLines()) == 0 {
|
if len(cv.ViewBufferLines()) == 0 {
|
||||||
printContactsToWindow(g, viewState.contacts)
|
printContactsToWindow(g, viewState.contacts)
|
||||||
}
|
}
|
||||||
} else if l == disconnect {
|
} else if l == disconnect {
|
||||||
maxX, maxY := g.Size()
|
maxX, maxY := g.Size()
|
||||||
msg := "You disconnected from the server. Press enter to quit."
|
msg := "You disconnected from the server. Press enter to quit."
|
||||||
if v, err := g.SetView(disconnectMsg, maxX/2-30, maxY/2, maxX/2-29+len(msg), maxY/2+2, 0); err != nil {
|
if v, err := g.SetView(disconnectMsg, maxX/2-30, maxY/2, maxX/2-29+len(msg), maxY/2+2, 0); err != nil {
|
||||||
|
@ -226,11 +230,12 @@ func getLine(g *gocui.Gui, v *gocui.View) error {
|
||||||
if _, err := g.SetCurrentView(disconnectMsg); err != nil {
|
if _, err := g.SetCurrentView(disconnectMsg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
killChan <- disconnectErr
|
killChan <- disconnectErr
|
||||||
} else if l == askServerForRoster {
|
} else if l == askServerForRoster {
|
||||||
chlw, _ := g.View(chatLogWindow)
|
chlw, _ := g.View(chatLogWindow)
|
||||||
fmt.Fprintln(chlw, infoFormat+" Not yet implemented !")
|
fmt.Fprintln(chlw, infoFormat+"Asking server for contacts list...")
|
||||||
|
rosterChan <- struct{}{}
|
||||||
} else if l == rawMode {
|
} else if l == rawMode {
|
||||||
mw, _ := g.View(menuWindow)
|
mw, _ := g.View(menuWindow)
|
||||||
viewState.input = rawInputWindow
|
viewState.input = rawInputWindow
|
||||||
|
|
|
@ -5,6 +5,7 @@ xmpp_chat_client is a demo client that connect on an XMPP server to chat with ot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
@ -19,6 +20,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -43,6 +45,7 @@ var (
|
||||||
rawTextChan = make(chan string, 5)
|
rawTextChan = make(chan string, 5)
|
||||||
killChan = make(chan error, 1)
|
killChan = make(chan error, 1)
|
||||||
errChan = make(chan error)
|
errChan = make(chan error)
|
||||||
|
rosterChan = make(chan struct{})
|
||||||
|
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
disconnectErr = errors.New("disconnecting client")
|
disconnectErr = errors.New("disconnecting client")
|
||||||
|
@ -182,7 +185,6 @@ func startClient(g *gocui.Gui, config *config) {
|
||||||
|
|
||||||
// ==========================
|
// ==========================
|
||||||
// Start working
|
// Start working
|
||||||
//askForRoster(client, g)
|
|
||||||
updateRosterFromConfig(g, config)
|
updateRosterFromConfig(g, config)
|
||||||
// Sending the default contact in a channel. Default value is the first contact in the list from the config.
|
// Sending the default contact in a channel. Default value is the first contact in the list from the config.
|
||||||
viewState.currentContact = strings.Split(config.Contacts, configContactSep)[0]
|
viewState.currentContact = strings.Split(config.Contacts, configContactSep)[0]
|
||||||
|
@ -190,10 +192,10 @@ func startClient(g *gocui.Gui, config *config) {
|
||||||
clw, _ := g.View(chatLogWindow)
|
clw, _ := g.View(chatLogWindow)
|
||||||
fmt.Fprintf(clw, infoFormat+"Now sending messages to "+viewState.currentContact+" in a private conversation\n")
|
fmt.Fprintf(clw, infoFormat+"Now sending messages to "+viewState.currentContact+" in a private conversation\n")
|
||||||
CorrespChan <- viewState.currentContact
|
CorrespChan <- viewState.currentContact
|
||||||
startMessaging(client, config)
|
startMessaging(client, config, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startMessaging(client xmpp.Sender, config *config) {
|
func startMessaging(client xmpp.Sender, config *config, g *gocui.Gui) {
|
||||||
var text string
|
var text string
|
||||||
var correspondent string
|
var correspondent string
|
||||||
for {
|
for {
|
||||||
|
@ -228,6 +230,8 @@ func startMessaging(client xmpp.Sender, config *config) {
|
||||||
}
|
}
|
||||||
case crrsp := <-CorrespChan:
|
case crrsp := <-CorrespChan:
|
||||||
correspondent = crrsp
|
correspondent = crrsp
|
||||||
|
case <-rosterChan:
|
||||||
|
askForRoster(client, g, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -282,10 +286,43 @@ func updateRosterFromConfig(g *gocui.Gui, config *config) {
|
||||||
viewState.contacts = append(strings.Split(config.Contacts, configContactSep), backFromContacts)
|
viewState.contacts = append(strings.Split(config.Contacts, configContactSep), backFromContacts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the menu panel of the view with the current user's roster.
|
// Updates the menu panel of the view with the current user's roster, by asking the server.
|
||||||
// Need to add support for Roster IQ stanzas to make this work.
|
func askForRoster(client xmpp.Sender, g *gocui.Gui, config *config) {
|
||||||
func askForRoster(client *xmpp.Client, g *gocui.Gui) {
|
// Craft a roster request
|
||||||
// Not implemented yet !
|
req := stanza.NewIQ(stanza.Attrs{From: config.Client[clientJid], Type: stanza.IQTypeGet})
|
||||||
|
req.RosterItems()
|
||||||
|
if logger != nil {
|
||||||
|
m, _ := xml.Marshal(req)
|
||||||
|
logger.Println(string(m))
|
||||||
|
}
|
||||||
|
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
|
||||||
|
// Send the roster request to the server
|
||||||
|
c, err := client.SendIQ(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
logger.Panicln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sending a IQ has a channel spawned to process the response once we receive it.
|
||||||
|
// In order not to block the client, we spawn a goroutine to update the TUI once the server has responded.
|
||||||
|
go func() {
|
||||||
|
serverResp := <-c
|
||||||
|
if logger != nil {
|
||||||
|
m, _ := xml.Marshal(serverResp)
|
||||||
|
logger.Println(string(m))
|
||||||
|
}
|
||||||
|
// Update contacts with the response from the server
|
||||||
|
chlw, _ := g.View(chatLogWindow)
|
||||||
|
if rosterItems, ok := serverResp.Payload.(*stanza.RosterItems); ok {
|
||||||
|
viewState.contacts = []string{}
|
||||||
|
for _, item := range rosterItems.Items {
|
||||||
|
viewState.contacts = append(viewState.contacts, item.Jid)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(chlw, infoFormat+"Contacts list updated !")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintln(chlw, infoFormat+"Failed to update contact list !")
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isDirectory(path string) (bool, error) {
|
func isDirectory(path string) (bool, error) {
|
||||||
|
|
Loading…
Reference in a new issue