first version with gosrc.io/xmpp

This commit is contained in:
Martin/Geno 2019-07-15 23:57:26 +02:00
parent f35f1eac42
commit 18676475d3
11 changed files with 192 additions and 116 deletions

View File

@ -7,7 +7,7 @@ import (
libHTTP "dev.sum7.eu/genofire/golang-lib/http"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
@ -30,7 +30,7 @@ func (r requestBody) String() string {
}
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
runtime.HookRegister[hookType] = func(client xmpp.Sender, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
log.WithField("type", hookType).Info("loaded")
return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType)
@ -47,12 +47,14 @@ func init() {
})
ok := false
msg := request.String()
for _, hook := range hooks {
if request.Payload.VCSURL != hook.Secret {
continue
}
logger.Infof("run hook")
runtime.Notify(client, hook, request.String())
runtime.Notify(client, hook, msg, msg)
ok = true
}
if !ok {

View File

@ -1,13 +1,16 @@
log_level = 50
webserver_bind = ":8080"
[xmpp]
host = "fireorbit.de"
username = "bot@fireorbit.de"
password = "example"
startup_notify_user = ["user@fireorbit.de"]
startup_notify_muc = []
nickname = "logbot"
[xmpp]
address = "fireorbit.de"
jid = "bot@fireorbit.de"
password = "example"
# suported hooks are, which could be declared multiple times with different `secrets` (see [[hooks.grafana]]):
[[hooks.grafana]]
[[hooks.prometheus]]

View File

@ -7,8 +7,8 @@ import (
libHTTP "dev.sum7.eu/genofire/golang-lib/http"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"github.com/mitchellh/mapstructure"
"gosrc.io/xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
@ -21,7 +21,7 @@ var eventHeader = map[string]string{
const hookType = "git"
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
runtime.HookRegister[hookType] = func(client xmpp.Sender, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
log.WithField("type", hookType).Info("loaded")
return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType)
@ -62,12 +62,14 @@ func init() {
})
ok := false
msg := request.String(event)
for _, hook := range hooks {
if secret != hook.Secret {
continue
}
logger.Infof("run hook")
runtime.Notify(client, hook, request.String(event))
runtime.Notify(client, hook, msg, msg)
ok = true
}
if !ok {

View File

@ -10,7 +10,7 @@ import (
libHTTP "dev.sum7.eu/genofire/golang-lib/http"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
@ -24,7 +24,7 @@ var eventHeader = map[string]string{
const hookType = "gitlab"
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
runtime.HookRegister[hookType] = func(client xmpp.Sender, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
log.WithField("type", hookType).Info("loaded")
return func(w http.ResponseWriter, r *http.Request) {
event := r.Header.Get("X-Gitlab-Event")
@ -131,7 +131,7 @@ func init() {
continue
}
logger.Infof("run hook")
runtime.Notify(client, hook, msg)
runtime.Notify(client, hook, msg, msg)
ok = true
}
if !ok {

View File

@ -6,7 +6,7 @@ import (
libHTTP "dev.sum7.eu/genofire/golang-lib/http"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
@ -39,7 +39,7 @@ func (r requestBody) String() string {
}
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
runtime.HookRegister[hookType] = func(client xmpp.Sender, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
log.WithField("type", hookType).Info("loaded")
return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType)
@ -65,12 +65,14 @@ func init() {
})
ok = false
msg := request.String()
for _, hook := range hooks {
if secret != hook.Secret {
continue
}
runtime.Notify(client, hook, request.String())
runtime.Notify(client, hook, msg, msg)
if request.ImageURL != "" {
runtime.NotifyImage(client, hook, request.ImageURL, request.String())
} else {

70
main.go
View File

@ -9,7 +9,7 @@ import (
"dev.sum7.eu/genofire/golang-lib/file"
"github.com/bdlm/log"
"github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
_ "dev.sum7.eu/genofire/hook2xmpp/circleci"
_ "dev.sum7.eu/genofire/hook2xmpp/git"
@ -19,39 +19,36 @@ import (
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
var config = runtime.Config{}
func main() {
configFile := "config.conf"
flag.StringVar(&configFile, "config", configFile, "path of configuration file")
flag.Parse()
config := &runtime.Config{}
if err := file.ReadTOML(configFile, config); err != nil {
if err := file.ReadTOML(configFile, &config); err != nil {
log.WithField("tip", "maybe call me with: hook2xmpp--config /etc/hook2xmpp.conf").Panicf("error on read config: %s", err)
}
log.SetLevel(config.LogLevel)
// load config
options := xmpp.Options{
Host: config.XMPP.Host,
User: config.XMPP.Username,
Resource: config.XMPP.Resource,
Password: config.XMPP.Password,
StartTLS: config.XMPP.StartTLS,
NoTLS: config.XMPP.NoTLS,
Debug: config.XMPP.Debug,
Session: config.XMPP.Session,
Status: config.XMPP.Status,
StatusMessage: config.XMPP.StatusMessage,
}
client, err := options.NewClient()
router := xmpp.NewRouter()
var err error
client, err := xmpp.NewClient(xmpp.Config{
Address: config.XMPP.Address,
Jid: config.XMPP.JID,
Password: config.XMPP.Password,
}, router)
if err != nil {
log.Panicf("error on startup xmpp client: %s", err)
}
go runtime.Start(client)
cm := xmpp.NewStreamManager(client, postStartup)
go func() {
err := cm.Run()
log.Panic("closed connection:", err)
}()
for hookType, getHandler := range runtime.HookRegister {
hooks, ok := config.Hooks[hookType]
if ok {
@ -68,45 +65,14 @@ func main() {
}
}()
var mucs []string
for _, muc := range config.StartupNotifyMuc {
mucs = append(mucs, muc)
client.JoinMUCNoHistory(muc, config.Nickname)
}
for _, hooks := range config.Hooks {
for _, hook := range hooks {
for _, muc := range hook.NotifyMuc {
mucs = append(mucs, muc)
client.JoinMUCNoHistory(muc, config.Nickname)
}
}
}
notify := func(msg string) {
for _, muc := range config.StartupNotifyMuc {
client.SendHtml(xmpp.Chat{Remote: muc, Type: "groupchat", Text: msg})
}
for _, user := range config.StartupNotifyUser {
client.SendHtml(xmpp.Chat{Remote: user, Type: "chat", Text: msg})
}
}
log.Infof("started hock2xmpp with %s", client.JID())
notify("startup of hock2xmpp")
// Wait for system signal
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs
notify("stopped of hock2xmpp")
for _, muc := range mucs {
client.LeaveMUC(muc)
}
closeXMPP(client)
srv.Close()
client.Close()
log.Infof("closed by receiving: %s", sig)
}

View File

@ -8,8 +8,8 @@ import (
libHTTP "dev.sum7.eu/genofire/golang-lib/http"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"github.com/prometheus/alertmanager/notify/webhook"
"gosrc.io/xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
@ -17,7 +17,7 @@ import (
const hookType = "prometheus"
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
runtime.HookRegister[hookType] = func(client xmpp.Sender, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
log.WithField("type", hookType).Info("loaded")
return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType)
@ -51,7 +51,7 @@ func init() {
continue
}
logger.Infof("run hook")
runtime.Notify(client, hook, content)
runtime.Notify(client, hook, content, content)
ok = true
}
if !ok {

View File

@ -7,16 +7,9 @@ type Config struct {
WebserverBind string `toml:"webserver_bind"`
XMPP struct {
Host string `toml:"host"`
Username string `toml:"username"`
Resource string `toml:"resource"`
Password string `toml:"password"`
Debug bool `toml:"debug"`
NoTLS bool `toml:"no_tls"`
StartTLS bool `toml:"start_tls"`
Session bool `toml:"session"`
Status string `toml:"status"`
StatusMessage string `toml:"status_message"`
Address string `toml:"address"`
JID string `toml:"jid"`
Password string `toml:"password"`
} `toml:"xmpp"`
Nickname string `toml:"nickname"`

View File

@ -3,10 +3,10 @@ package runtime
import (
"net/http"
xmpp "github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
)
type HookHandler func(*xmpp.Client, []Hook) func(http.ResponseWriter, *http.Request)
type HookHandler func(xmpp.Sender, []Hook) func(http.ResponseWriter, *http.Request)
var HookRegister map[string]HookHandler

View File

@ -1,51 +1,70 @@
package runtime
import (
"fmt"
"github.com/bdlm/log"
xmpp "github.com/mattn/go-xmpp"
"gosrc.io/xmpp"
"gosrc.io/xmpp/stanza"
)
func Start(client *xmpp.Client) {
for {
m, err := client.Recv()
if err != nil {
continue
}
switch v := m.(type) {
case xmpp.Chat:
if v.Type == "chat" {
log.Debugf("from %s: %s", v.Remote, v.Text)
}
if v.Type == "groupchat" {
}
case xmpp.Presence:
// do nothing
}
func NotifyImage(client xmpp.Sender, hook Hook, url string, desc string) {
msg := stanza.Message{
Attrs: stanza.Attrs{Type: stanza.MessageTypeGroupchat},
Body: url,
Extensions: []stanza.MsgExtension{
stanza.OOB{URL: url, Desc: desc},
},
}
}
func NotifyImage(client *xmpp.Client, hook Hook, url string, desc string) {
msg := fmt.Sprintf(`<message to='%%s' type='%%s'>
<body>%s</body>
<x xmlns='jabber:x:oob'>
<url>%s</url>
<desc>%s</desc>
</x>
</message>`, url, url, desc)
for _, muc := range hook.NotifyMuc {
client.SendOrg(fmt.Sprintf(msg, muc, "groupchat"))
msg.To = muc
if err := client.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"muc": muc,
"url": url,
}).Errorf("error on image notify: %s", err)
}
}
msg.Type = stanza.MessageTypeChat
for _, user := range hook.NotifyUser {
client.SendOrg(fmt.Sprintf(msg, user, "chat"))
msg.To = user
if err := client.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"user": user,
"url": url,
}).Errorf("error on image notify: %s", err)
}
}
}
func Notify(client *xmpp.Client, hook Hook, msg string) {
func Notify(client xmpp.Sender, hook Hook, text, html string) {
msg := stanza.Message{
Attrs: stanza.Attrs{Type: stanza.MessageTypeGroupchat},
Body: text,
Extensions: []stanza.MsgExtension{
stanza.HTML{Body: stanza.HTMLBody{InnerXML: html}},
},
}
for _, muc := range hook.NotifyMuc {
client.SendHtml(xmpp.Chat{Remote: muc, Type: "groupchat", Text: msg})
msg.To = muc
if err := client.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"muc": muc,
"text": text,
}).Errorf("error on notify: %s", err)
}
}
msg.Type = stanza.MessageTypeChat
for _, user := range hook.NotifyUser {
client.SendHtml(xmpp.Chat{Remote: user, Type: "chat", Text: msg})
msg.To = user
if err := client.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"user": user,
"text": text,
}).Errorf("error on notify: %s", err)
}
}
}

89
xmpp.go Normal file
View File

@ -0,0 +1,89 @@
package main
import (
"github.com/bdlm/log"
"gosrc.io/xmpp"
"gosrc.io/xmpp/stanza"
)
var mucs []string
func notify(c xmpp.Sender, text string) {
msg := stanza.Message{
Attrs: stanza.Attrs{Type: stanza.MessageTypeGroupchat},
Body: text,
}
for _, muc := range config.StartupNotifyMuc {
msg.To = muc
if err := c.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"muc": muc,
"msg": text,
}).Errorf("error on startup notify: %s", err)
}
}
msg.Type = stanza.MessageTypeChat
for _, user := range config.StartupNotifyUser {
msg.To = user
if err := c.Send(msg); err != nil {
log.WithFields(map[string]interface{}{
"user": user,
"msg": text,
}).Errorf("error on startup notify: %s", err)
}
}
log.Infof("notify: %s", text)
}
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()
mucs = append(mucs, jid)
return c.Send(stanza.Presence{Attrs: stanza.Attrs{To: jid},
Extensions: []stanza.PresExtension{
stanza.MucPresence{
History: stanza.History{MaxStanzas: stanza.NewNullableInt(0)},
}},
})
}
func postStartup(c xmpp.Sender) {
for _, muc := range config.StartupNotifyMuc {
if err := joinMUC(c, muc, config.Nickname); err != nil {
log.WithField("muc", muc).Errorf("error on joining muc: %s", err)
}
}
for _, hooks := range config.Hooks {
for _, hook := range hooks {
for _, muc := range hook.NotifyMuc {
if err := joinMUC(c, muc, config.Nickname); err != nil {
log.WithField("muc", muc).Errorf("error on joining muc: %s", err)
}
}
}
}
notify(c, "started hock2xmpp")
}
func closeXMPP(c xmpp.Sender) {
notify(c, "stopped of hock2xmpp")
for _, muc := range mucs {
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)
}
}
}