diff --git a/cmd/sendxmpp/README.md b/cmd/sendxmpp/README.md new file mode 100644 index 0000000..cab4734 --- /dev/null +++ b/cmd/sendxmpp/README.md @@ -0,0 +1,17 @@ +# sendXMPP + +sendxmpp is a tool to send messages from commandline + +## Installation + +To install `sendxmpp` in your Go path: + +``` +$ go get -u gosrc.io/xmpp/cmd/sendxmpp +``` + +## Usage + +``` +$ xmpp-check --help +``` diff --git a/cmd/sendxmpp/cmd.go b/cmd/sendxmpp/cmd.go new file mode 100644 index 0000000..c6f39ba --- /dev/null +++ b/cmd/sendxmpp/cmd.go @@ -0,0 +1,95 @@ +package main + +import ( + "bufio" + "os" + "strings" + "sync" + + "github.com/bdlm/log" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "gosrc.io/xmpp" +) + +var jid = "" +var password = "" + +var receiverMUC = false +var stdIn = false + +var cmd = &cobra.Command{ + Use: "sendxmpp", + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + receiver := strings.Split(args[0], ",") + msgText := "" + + if !stdIn && len(args) < 2 { + log.Error("no message to send") + return + } else if !stdIn { + msgText = args[1] + } + + var err error + client, err := xmpp.NewClient(xmpp.Config{ + Jid: jid, + Password: password, + }, xmpp.NewRouter()) + + if err != nil { + log.Panicf("error on startup xmpp client: %s", err) + } + + wg := sync.WaitGroup{} + wg.Add(1) + + cm := xmpp.NewStreamManager(client, func(c xmpp.Sender) { + log.Info("client connected") + if receiverMUC { + for _, muc := range receiver { + joinMUC(c, muc, "sendxmpp") + } + } + + if !stdIn { + send(c, receiver, msgText) + wg.Done() + return + } + + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + send(c, receiver, scanner.Text()) + } + + if err := scanner.Err(); err != nil { + log.Errorf("error on reading stdin: %s", err) + } + wg.Done() + }) + go func() { + err := cm.Run() + log.Panic("closed connection:", err) + }() + + wg.Wait() + + leaveMUCs(client) + }, +} + +func init() { + cmd.Flags().StringVarP(&jid, "jid", "", "", "using jid (required)") + viper.BindPFlag("jid", cmd.Flags().Lookup("jid")) + // cmd.MarkFlagRequired("jid") + + cmd.Flags().StringVarP(&password, "password", "", "", "using password for your jid (required)") + viper.BindPFlag("password", cmd.Flags().Lookup("password")) + // cmd.MarkFlagRequired("password") + + cmd.Flags().BoolVarP(&stdIn, "stdin", "i", false, "read from stdin instatt of 2. argument") + cmd.Flags().BoolVarP(&receiverMUC, "muc", "m", false, "reciever is a muc (join it before sending messages)") +} diff --git a/cmd/sendxmpp/doc.go b/cmd/sendxmpp/doc.go new file mode 100644 index 0000000..321023d --- /dev/null +++ b/cmd/sendxmpp/doc.go @@ -0,0 +1,6 @@ +/* + +sendxmpp is a command-line to send to send messages to users + +*/ +package main diff --git a/cmd/sendxmpp/log.go b/cmd/sendxmpp/log.go new file mode 100644 index 0000000..eb67593 --- /dev/null +++ b/cmd/sendxmpp/log.go @@ -0,0 +1,34 @@ +package main + +import ( + "os" + + "github.com/bdlm/log" + stdLogger "github.com/bdlm/std/logger" +) + +type hook struct{} + +func (h *hook) Fire(entry *log.Entry) error { + switch entry.Level { + case log.PanicLevel: + entry.Logger.Out = os.Stderr + case log.FatalLevel: + entry.Logger.Out = os.Stderr + case log.ErrorLevel: + entry.Logger.Out = os.Stderr + case log.WarnLevel: + entry.Logger.Out = os.Stdout + case log.InfoLevel: + entry.Logger.Out = os.Stdout + case log.DebugLevel: + entry.Logger.Out = os.Stdout + default: + } + + return nil +} + +func (h *hook) Levels() []stdLogger.Level { + return log.AllLevels +} diff --git a/cmd/sendxmpp/main.go b/cmd/sendxmpp/main.go new file mode 100644 index 0000000..9974b31 --- /dev/null +++ b/cmd/sendxmpp/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/bdlm/log" +) + +func main() { + log.AddHook(&hook{}) + cmd.Execute() +} diff --git a/cmd/sendxmpp/muc.go b/cmd/sendxmpp/muc.go new file mode 100644 index 0000000..85bf7ae --- /dev/null +++ b/cmd/sendxmpp/muc.go @@ -0,0 +1,41 @@ +package main + +import ( + "github.com/bdlm/log" + + "gosrc.io/xmpp" + "gosrc.io/xmpp/stanza" +) + +var mucsToLeave []string + +func joinMUC(c xmpp.Sender, to, nick string) error { + + toJID, err := xmpp.NewJid(to) + if err != nil { + return err + } + toJID.Resource = nick + jid := toJID.Full() + + mucsToLeave = append(mucsToLeave, jid) + + return c.Send(stanza.Presence{Attrs: stanza.Attrs{To: jid}, + Extensions: []stanza.PresExtension{ + stanza.MucPresence{ + History: stanza.History{MaxStanzas: stanza.NewNullableInt(0)}, + }}, + }) + +} + +func leaveMUCs(c xmpp.Sender) { + for _, muc := range mucsToLeave { + if err := c.Send(stanza.Presence{Attrs: stanza.Attrs{ + To: muc, + Type: stanza.PresenceTypeUnavailable, + }}); err != nil { + log.WithField("muc", muc).Errorf("error on leaving muc: %s", err) + } + } +} diff --git a/cmd/sendxmpp/send.go b/cmd/sendxmpp/send.go new file mode 100644 index 0000000..2c00b55 --- /dev/null +++ b/cmd/sendxmpp/send.go @@ -0,0 +1,34 @@ +package main + +import ( + "github.com/bdlm/log" + + "gosrc.io/xmpp" + "gosrc.io/xmpp/stanza" +) + +func send(c xmpp.Sender, receiver []string, msgText string) { + msg := stanza.Message{ + Attrs: stanza.Attrs{Type: stanza.MessageTypeChat}, + Body: msgText, + } + if receiverMUC { + msg.Type = stanza.MessageTypeGroupchat + } + for _, to := range receiver { + msg.To = to + if err := c.Send(msg); err != nil { + log.WithFields(map[string]interface{}{ + "muc": receiverMUC, + "to": to, + "text": msgText, + }).Errorf("error on send message: %s", err) + } else { + log.WithFields(map[string]interface{}{ + "muc": receiverMUC, + "to": to, + "text": msgText, + }).Info("send message") + } + } +}