mirror of
https://github.com/FluuxIO/go-xmpp.git
synced 2025-10-22 12:35:36 -07:00
Move examples out of the cmd directory
They are now in _examples dir. Fix #26
This commit is contained in:
5
_examples/go.mod
Normal file
5
_examples/go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module gosrc.io/xmpp/_examples
|
||||
|
||||
go 1.12
|
||||
|
||||
require gosrc.io/xmpp v0.0.0-20190608091551-b7461ae97fed
|
11
_examples/go.sum
Normal file
11
_examples/go.sum
Normal file
@@ -0,0 +1,11 @@
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/processone/mpg123 v1.0.0 h1:o2WOyGZRM255or1Zc/LtF/jARn51B+9aQl72Qace0GA=
|
||||
github.com/processone/mpg123 v1.0.0/go.mod h1:X/FeL+h8vD1bYsG9tIWV3M2c4qNTZOficyvPVBP08go=
|
||||
github.com/processone/soundcloud v1.0.0 h1:/+i6+Yveb7Y6IFGDSkesYI+HddblzcRTQClazzVHxoE=
|
||||
github.com/processone/soundcloud v1.0.0/go.mod h1:kDLeWpkRtN3C8kIReQdxoiRi92P9xR6yW6qLOJnNWfY=
|
||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc h1:Yx9JGxI1SBhVLFjpAkWMaO1TF+xyqtHLjZpvQboJGiM=
|
||||
golang.org/x/net v0.0.0-20190110200230-915654e7eabc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gosrc.io/xmpp v0.0.0-20190608091551-b7461ae97fed h1:uLrripMKk85UZ0Kd9V2S7qQy2CM4kveMZkCBqBEOqmY=
|
||||
gosrc.io/xmpp v0.0.0-20190608091551-b7461ae97fed/go.mod h1:it3z4S42Sy7eHWFqwmdFJbygg7lCmbrhKeqK7HQSqSU=
|
20
_examples/xmpp_component/README.md
Normal file
20
_examples/xmpp_component/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# xmpp_component
|
||||
|
||||
This component will connect to ejabberd and act as a subdomain "service" of your primary XMPP domain
|
||||
(in that case localhost).
|
||||
|
||||
To be able to connect this component, you need to add a listener to your XMPP server.
|
||||
|
||||
Here is an example ejabberd configuration for that component listener:
|
||||
|
||||
```yaml
|
||||
listen:
|
||||
...
|
||||
-
|
||||
port: 8888
|
||||
module: ejabberd_service
|
||||
password: "mypass"
|
||||
```
|
||||
|
||||
ejabberd will listen for a component (service) on port 8888 and allows it to connect using the
|
||||
secret "mypass".
|
105
_examples/xmpp_component/xmpp_component.go
Normal file
105
_examples/xmpp_component/xmpp_component.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gosrc.io/xmpp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
component := MyComponent{Name: "Test Component", Category: "gateway", Type: "service"}
|
||||
component.xmpp = &xmpp.Component{Host: "service.localhost", Secret: "mypass"}
|
||||
if err := component.xmpp.Connect("localhost:8888"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
packet, err := component.xmpp.ReadPacket()
|
||||
if err != nil {
|
||||
fmt.Println("read error", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch p := packet.(type) {
|
||||
case xmpp.IQ:
|
||||
switch inner := p.Payload[0].(type) {
|
||||
case *xmpp.DiscoInfo:
|
||||
fmt.Println("Disco Info")
|
||||
if p.Type == "get" {
|
||||
DiscoResult(component, p.PacketAttrs, inner)
|
||||
}
|
||||
case *xmpp.DiscoItems:
|
||||
fmt.Println("DiscoItems")
|
||||
if p.Type == "get" {
|
||||
DiscoItems(component, p.PacketAttrs, inner)
|
||||
}
|
||||
default:
|
||||
fmt.Println("ignoring iq packet", inner)
|
||||
xError := xmpp.Err{
|
||||
Code: 501,
|
||||
Reason: "feature-not-implemented",
|
||||
Type: "cancel",
|
||||
}
|
||||
reply := p.MakeError(xError)
|
||||
_ = component.xmpp.Send(&reply)
|
||||
}
|
||||
|
||||
case xmpp.Message:
|
||||
fmt.Println("Received message:", p.Body)
|
||||
|
||||
case xmpp.Presence:
|
||||
fmt.Println("Received presence:", p.Type)
|
||||
|
||||
default:
|
||||
fmt.Println("ignoring packet:", packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type MyComponent struct {
|
||||
Name string
|
||||
// Typical categories and types: https://xmpp.org/registrar/disco-categories.html
|
||||
Category string
|
||||
Type string
|
||||
|
||||
xmpp *xmpp.Component
|
||||
}
|
||||
|
||||
func DiscoResult(c MyComponent, attrs xmpp.PacketAttrs, info *xmpp.DiscoInfo) {
|
||||
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
|
||||
var identity xmpp.Identity
|
||||
if info.Node == "" {
|
||||
identity = xmpp.Identity{
|
||||
Name: c.Name,
|
||||
Category: c.Category,
|
||||
Type: c.Type,
|
||||
}
|
||||
}
|
||||
|
||||
payload := xmpp.DiscoInfo{
|
||||
Identity: identity,
|
||||
Features: []xmpp.Feature{
|
||||
{Var: xmpp.NSDiscoInfo},
|
||||
{Var: xmpp.NSDiscoItems},
|
||||
},
|
||||
}
|
||||
iq.AddPayload(&payload)
|
||||
|
||||
_ = c.xmpp.Send(iq)
|
||||
}
|
||||
|
||||
func DiscoItems(c MyComponent, attrs xmpp.PacketAttrs, items *xmpp.DiscoItems) {
|
||||
iq := xmpp.NewIQ("result", attrs.To, attrs.From, attrs.Id, "en")
|
||||
|
||||
var payload xmpp.DiscoItems
|
||||
if items.Node == "" {
|
||||
payload = xmpp.DiscoItems{
|
||||
Items: []xmpp.DiscoItem{
|
||||
{Name: "test node", JID: "service.localhost", Node: "node1"},
|
||||
},
|
||||
}
|
||||
}
|
||||
iq.AddPayload(&payload)
|
||||
_ = c.xmpp.Send(iq)
|
||||
}
|
51
_examples/xmpp_echo/xmpp_echo.go
Normal file
51
_examples/xmpp_echo/xmpp_echo.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
xmpp_echo is a demo client that connect on an XMPP server and echo message received back to original sender.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gosrc.io/xmpp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config := xmpp.Config{
|
||||
Address: "localhost:5222",
|
||||
Jid: "test@localhost",
|
||||
Password: "test",
|
||||
PacketLogger: os.Stdout,
|
||||
Insecure: true,
|
||||
}
|
||||
|
||||
client, err := xmpp.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatalf("%+v", err)
|
||||
}
|
||||
|
||||
// If you pass the client to a connection manager, it will handle the reconnect policy
|
||||
// for you automatically.
|
||||
cm := xmpp.NewClientManager(client, nil)
|
||||
err = cm.Start()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Iterator to receive packets coming from our XMPP connection
|
||||
for packet := range client.Recv() {
|
||||
switch packet := packet.(type) {
|
||||
case xmpp.Message:
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Body = %s - from = %s\n", packet.Body, packet.From)
|
||||
reply := xmpp.Message{PacketAttrs: xmpp.PacketAttrs{To: packet.From}, Body: packet.Body}
|
||||
_ = client.Send(reply)
|
||||
default:
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Ignoring packet: %T\n", packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO create default command line client to send message or to send an arbitrary XMPP sequence from a file,
|
||||
// (using templates ?)
|
120
_examples/xmpp_jukebox/xmpp_jukebox.go
Normal file
120
_examples/xmpp_jukebox/xmpp_jukebox.go
Normal file
@@ -0,0 +1,120 @@
|
||||
// Can be launched with:
|
||||
// ./xmpp_jukebox -jid=test@localhost/jukebox -password=test -address=localhost:5222
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/processone/mpg123"
|
||||
"github.com/processone/soundcloud"
|
||||
"gosrc.io/xmpp"
|
||||
)
|
||||
|
||||
// Get the actual song Stream URL from SoundCloud website song URL and play it with mpg123 player.
|
||||
const scClientID = "dde6a0075614ac4f3bea423863076b22"
|
||||
|
||||
func main() {
|
||||
jid := flag.String("jid", "", "jukebok XMPP JID, resource is optional")
|
||||
password := flag.String("password", "", "XMPP account password")
|
||||
address := flag.String("address", "", "If needed, XMPP server DNSName or IP and optional port (ie myserver:5222)")
|
||||
flag.Parse()
|
||||
|
||||
var client *xmpp.Client
|
||||
var err error
|
||||
if client, err = connectXmpp(*jid, *password, *address); err != nil {
|
||||
log.Fatal("Could not connect to XMPP: ", err)
|
||||
}
|
||||
|
||||
p, err := mpg123.NewPlayer()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Iterator to receive packets coming from our XMPP connection
|
||||
for packet := range client.Recv() {
|
||||
|
||||
switch packet := packet.(type) {
|
||||
case xmpp.Message:
|
||||
processMessage(client, p, &packet)
|
||||
case xmpp.IQ:
|
||||
processIq(client, p, &packet)
|
||||
case xmpp.Presence:
|
||||
// Do nothing with received presence
|
||||
default:
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Ignoring packet: %T\n", packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processMessage(client *xmpp.Client, p *mpg123.Player, packet *xmpp.Message) {
|
||||
command := strings.Trim(packet.Body, " ")
|
||||
if command == "stop" {
|
||||
p.Stop()
|
||||
} else {
|
||||
playSCURL(p, command)
|
||||
sendUserTune(client, "Radiohead", "Spectre")
|
||||
}
|
||||
}
|
||||
|
||||
func processIq(client *xmpp.Client, p *mpg123.Player, packet *xmpp.IQ) {
|
||||
switch payload := packet.Payload[0].(type) {
|
||||
// We support IOT Control IQ
|
||||
case *xmpp.ControlSet:
|
||||
var url string
|
||||
for _, element := range payload.Fields {
|
||||
if element.XMLName.Local == "string" && element.Name == "url" {
|
||||
url = strings.Trim(element.Value, " ")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
playSCURL(p, url)
|
||||
setResponse := new(xmpp.ControlSetResponse)
|
||||
reply := xmpp.IQ{PacketAttrs: xmpp.PacketAttrs{To: packet.From, Type: "result", Id: packet.Id}, Payload: []xmpp.IQPayload{setResponse}}
|
||||
_ = client.Send(reply)
|
||||
// TODO add Soundclound artist / title retrieval
|
||||
sendUserTune(client, "Radiohead", "Spectre")
|
||||
default:
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Other IQ Payload: %T\n", packet.Payload)
|
||||
}
|
||||
}
|
||||
|
||||
func sendUserTune(client *xmpp.Client, artist string, title string) {
|
||||
tune := xmpp.Tune{Artist: artist, Title: title}
|
||||
iq := xmpp.NewIQ("set", "", "", "usertune-1", "en")
|
||||
payload := xmpp.PubSub{Publish: xmpp.Publish{Node: "http://jabber.org/protocol/tune", Item: xmpp.Item{Tune: tune}}}
|
||||
iq.AddPayload(&payload)
|
||||
_ = client.Send(iq)
|
||||
}
|
||||
|
||||
func playSCURL(p *mpg123.Player, rawURL string) {
|
||||
songID, _ := soundcloud.GetSongID(rawURL)
|
||||
// TODO: Maybe we need to check the track itself to get the stream URL from reply ?
|
||||
url := soundcloud.FormatStreamURL(songID)
|
||||
|
||||
_ = p.Play(url)
|
||||
}
|
||||
|
||||
func connectXmpp(jid string, password string, address string) (client *xmpp.Client, err error) {
|
||||
xmppConfig := xmpp.Config{Address: address,
|
||||
Jid: jid, Password: password, PacketLogger: os.Stdout, Insecure: true}
|
||||
|
||||
if client, err = xmpp.NewClient(xmppConfig); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = client.Connect(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TODO
|
||||
// - Have a player API to play, play next, or add to queue
|
||||
// - Have the ability to parse custom packet to play sound
|
||||
// - Use PEP to display tunes status
|
||||
// - Ability to "speak" messages
|
Reference in New Issue
Block a user