diff --git a/output/xmpp/main.go b/output/xmpp/main.go index 0a01999..e61c10d 100644 --- a/output/xmpp/main.go +++ b/output/xmpp/main.go @@ -3,11 +3,9 @@ package xmpp import ( "regexp" - xmpp_client "dev.sum7.eu/genofire/yaja/client" - xmpp "dev.sum7.eu/genofire/yaja/xmpp" - "dev.sum7.eu/genofire/yaja/xmpp/base" "github.com/bdlm/log" "github.com/mitchellh/mapstructure" + "gosrc.io/xmpp" "dev.sum7.eu/genofire/logmania/bot" "dev.sum7.eu/genofire/logmania/database" @@ -20,8 +18,6 @@ const ( nickname = "logmania" ) -var historyMaxChars = 0 - var logger = log.WithField("output", proto) type Output struct { @@ -29,7 +25,7 @@ type Output struct { defaults []*database.Notify channels map[string]bool bot *bot.Bot - client *xmpp_client.Client + client *xmpp.Client botOut chan interface{} logOut chan interface{} } @@ -47,26 +43,30 @@ func Init(configInterface interface{}, db *database.DB, bot *bot.Bot) output.Out return nil } - jid := xmppbase.NewJID(config.JID) - client, err := xmpp_client.NewClient(jid, config.Password) + out := &Output{ + channels: make(map[string]bool), + bot: bot, + } + + router := xmpp.NewRouter() + router.HandleFunc("message", out.recvMessage) + router.HandleFunc("presence", out.recvPresence) + + client, err := xmpp.NewClient(xmpp.Config{ + Jid: config.JID, + Password: config.Password, + }, router) if err != nil { logger.Error(err) return nil } + out.client = client + cm := xmpp.NewStreamManager(client, nil) go func() { - client.Start() + cm.Run() log.Panic("closed connection") }() - out := &Output{ - channels: make(map[string]bool), - bot: bot, - client: client, - botOut: make(chan interface{}), - logOut: make(chan interface{}), - } - go out.sender() - go out.receiver() logger.WithField("jid", config.JID).Info("startup") @@ -97,17 +97,19 @@ func (out *Output) Default() []*database.Notify { func (out *Output) Close() { for jid := range out.channels { - toJID := xmppbase.NewJID(jid) - toJID.Resource = nickname - err := out.client.Send(&xmpp.PresenceClient{ - To: toJID, - Type: xmpp.PresenceTypeUnavailable, - }) + toJID, err := xmpp.NewJid(jid) if err != nil { - logger.Error("xmpp could not leave ", toJID.String(), " error:", err) + logger.Error("xmpp could generate jid to leave ", jid, " error:", err) + } + toJID.Resource = nickname + err = out.client.Send(xmpp.Presence{Attrs: xmpp.Attrs{ + To: toJID.Full(), + Type: xmpp.PresenceTypeUnavailable, + }}) + if err != nil { + logger.Error("xmpp could not leave ", toJID.Full(), " error:", err) } } - out.client.Close() } func init() { diff --git a/output/xmpp/recv.go b/output/xmpp/recv.go index 5b7d49e..275b253 100644 --- a/output/xmpp/recv.go +++ b/output/xmpp/recv.go @@ -1,75 +1,78 @@ package xmpp import ( - xmpp "dev.sum7.eu/genofire/yaja/xmpp" "github.com/bdlm/log" + "gosrc.io/xmpp" ) -func (out *Output) receiver() { - for { - element, more := out.client.Recv() - if !more { - log.Warn("could not receive new message, try later") - continue - } - out.recv(element) - } -} -func (out *Output) recv(element interface{}) { - - switch element.(type) { - case *xmpp.PresenceClient: - pres := element.(*xmpp.PresenceClient) - sender := pres.From - logPres := logger.WithField("from", sender.Full()) - switch pres.Type { - case xmpp.PresenceTypeSubscribe: - logPres.Debugf("recv presence subscribe") - pres.Type = xmpp.PresenceTypeSubscribed - pres.To = sender - pres.From = nil - out.botOut <- pres - logPres.Debugf("accept new subscribe") - - pres.Type = xmpp.PresenceTypeSubscribe - pres.ID = "" - out.botOut <- pres - logPres.Info("request also subscribe") - case xmpp.PresenceTypeSubscribed: - logPres.Info("recv presence accepted subscribe") - case xmpp.PresenceTypeUnsubscribe: - logPres.Info("recv presence remove subscribe") - case xmpp.PresenceTypeUnsubscribed: - logPres.Info("recv presence removed subscribe") - case xmpp.PresenceTypeUnavailable: - logPres.Debug("recv presence unavailable") - case "": - logPres.Debug("recv empty presence, maybe from joining muc") - return - default: - logPres.Warnf("recv presence unsupported: %s -> %s", pres.Type, xmpp.XMLChildrenString(pres)) - } - case *xmpp.MessageClient: - msg := element.(*xmpp.MessageClient) - from := msg.From.Bare().String() - if msg.Type == xmpp.MessageTypeGroupchat { - from = protoGroup + ":" + from - } else { - from = proto + ":" + from - } - - answer := out.bot.Handle(from, msg.Body) - if answer == "" { - return - } - to := msg.From - if msg.Type == xmpp.MessageTypeGroupchat && !to.IsBare() { - to = to.Bare() - } - out.botOut <- &xmpp.MessageClient{ - Type: msg.Type, - To: to, - Body: answer, - } +func (out *Output) recvMessage(s xmpp.Sender, p xmpp.Packet) { + msg, ok := p.(xmpp.Message) + if !ok { + log.Errorf("blame gosrc.io/xmpp for routing: %s", p) + return + } + from, err := xmpp.NewJid(msg.From) + if err != nil { + log.Errorf("blame gosrc.io/xmpp for jid encoding: %s", msg.From) + return + } + fromBare := from.Bare() + fromLogmania := "" + if msg.Type == xmpp.MessageTypeGroupchat { + fromLogmania = protoGroup + ":" + fromBare + } else { + fromLogmania = proto + ":" + fromBare + } + + answer := out.bot.Handle(fromLogmania, msg.Body) + if answer == "" { + return + } + reply := xmpp.Message{Attrs: xmpp.Attrs{To: fromBare, Type: msg.Type}, Body: answer} + s.Send(reply) +} + +func (out *Output) recvPresence(s xmpp.Sender, p xmpp.Packet) { + pres, ok := p.(xmpp.Presence) + if !ok { + log.Errorf("blame gosrc.io/xmpp for routing: %s", p) + return + } + from, err := xmpp.NewJid(pres.From) + if err != nil { + log.Errorf("blame gosrc.io/xmpp for jid encoding: %s", pres.From) + return + } + fromBare := from.Bare() + logPres := logger.WithField("from", from) + + switch pres.Type { + case xmpp.PresenceTypeSubscribe: + logPres.Debugf("recv presence subscribe") + s.Send(xmpp.Presence{Attrs: xmpp.Attrs{ + Type: xmpp.PresenceTypeSubscribed, + To: fromBare, + Id: pres.Id, + }}) + logPres.Debugf("accept new subscribe") + + s.Send(xmpp.Presence{Attrs: xmpp.Attrs{ + Type: xmpp.PresenceTypeSubscribe, + To: fromBare, + }}) + logPres.Info("request also subscribe") + case xmpp.PresenceTypeSubscribed: + logPres.Info("recv presence accepted subscribe") + case xmpp.PresenceTypeUnsubscribe: + logPres.Info("recv presence remove subscribe") + case xmpp.PresenceTypeUnsubscribed: + logPres.Info("recv presence removed subscribe") + case xmpp.PresenceTypeUnavailable: + logPres.Debug("recv presence unavailable") + case "": + logPres.Debug("recv empty presence, maybe from joining muc") + return + default: + logPres.Warnf("recv presence unsupported: %s -> %s", pres.Type, pres) } } diff --git a/output/xmpp/send.go b/output/xmpp/send.go index c47c06e..4129f84 100644 --- a/output/xmpp/send.go +++ b/output/xmpp/send.go @@ -1,50 +1,34 @@ package xmpp import ( - "encoding/xml" "strings" - xmpp "dev.sum7.eu/genofire/yaja/xmpp" - "dev.sum7.eu/genofire/yaja/xmpp/base" - "dev.sum7.eu/genofire/yaja/xmpp/x/muc" "github.com/bdlm/log" + "gosrc.io/xmpp" "dev.sum7.eu/genofire/logmania/database" ) func (out *Output) Join(to string) { - toJID := xmppbase.NewJID(to) + toJID, err := xmpp.NewJid(to) + if err != nil { + logger.Error("xmpp could not generate jid to join ", to, " error:", err) + return + } toJID.Resource = nickname - err := out.client.Send(&xmpp.PresenceClient{ - To: toJID, - MUC: &xmuc.Base{ - History: &xmuc.History{ - MaxChars: &historyMaxChars, - }, - }, + err = out.client.Send(xmpp.Presence{Attrs: xmpp.Attrs{To: toJID.Full()}, + Extensions: []xmpp.PresExtension{ + xmpp.MucPresence{ + History: xmpp.History{MaxStanzas: 0}, + }}, }) if err != nil { - logger.Error("xmpp could not join ", toJID.String(), " error:", err) + logger.Error("xmpp could not join ", toJID.Full(), " error:", err) } else { out.channels[to] = true } } -func (out *Output) sender() { - // priority of bot higher: https://groups.google.com/forum/#!topic/golang-nuts/M2xjN_yWBiQ - for { - select { - case el := <-out.botOut: - out.client.Send(el) - default: - select { - case el := <-out.logOut: - out.client.Send(el) - default: - } - } - } -} func (out *Output) Send(e *log.Entry, to *database.Notify) bool { html, text := formatLog(e) if html == "" || text == "" { @@ -52,44 +36,28 @@ func (out *Output) Send(e *log.Entry, to *database.Notify) bool { return false } html = strings.TrimRight(to.RunReplace(html), "\n") - var body xmpp.XMLElement - xml.Unmarshal([]byte(html), &body) - text = strings.TrimRight(to.RunReplace(text), "\n") + msg := xmpp.Message{ + Attrs: xmpp.Attrs{ + To: to.To, + }, + Body: text, + Extensions: []xmpp.MsgExtension{ + xmpp.HTML{Body: xmpp.HTMLBody{InnerXML: html}}, + }, + } if to.Protocol == protoGroup { if _, ok := out.channels[to.To]; ok { - toJID := xmppbase.NewJID(to.To) - toJID.Resource = nickname - err := out.client.Send(&xmpp.PresenceClient{ - To: toJID, - MUC: &xmuc.Base{ - History: &xmuc.History{ - MaxChars: &historyMaxChars, - }, - }, - }) - if err != nil { - logger.Error("xmpp could not join ", toJID.String(), " error:", err) - } else { - out.channels[to.To] = true - } - } - out.logOut <- &xmpp.MessageClient{ - Type: xmpp.MessageTypeGroupchat, - To: xmppbase.NewJID(to.To), - Body: text, - HTML: &xmpp.HTML{Body: xmpp.HTMLBody{Body: body}}, + out.Join(to.To) } + msg.Type = xmpp.MessageTypeGroupchat + out.client.Send(msg) return true } if to.Protocol == proto { - out.logOut <- &xmpp.MessageClient{ - Type: xmpp.MessageTypeChat, - To: xmppbase.NewJID(to.To), - Body: text, - HTML: &xmpp.HTML{Body: xmpp.HTMLBody{Body: body}}, - } + msg.Type = xmpp.MessageTypeChat + out.client.Send(msg) return true } return false