From ff3645dfb37f64580f1f1746ed2879225f7cd011 Mon Sep 17 00:00:00 2001 From: Harry Metske Date: Fri, 30 Aug 2024 13:54:53 +0200 Subject: [PATCH 1/4] switch underlying matrix library from gomatrix to mautrix-go include a few dependency bumps and switch to golang 1.23 --- go.mod | 23 +++++++--- go.sum | 53 +++++++++++++++++----- internal/matrix/client.go | 95 ++++++++++++++++----------------------- 3 files changed, 99 insertions(+), 72 deletions(-) diff --git a/go.mod b/go.mod index b703e65..c8f2cea 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,16 @@ module github.com/sebhoss/matrix-alertmanager-receiver -go 1.21 +go 1.23 + +toolchain go1.23.0 require ( - github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 github.com/prometheus/alertmanager v0.27.0 github.com/prometheus/client_golang v1.20.2 github.com/prometheus/common v0.57.0 github.com/stretchr/testify v1.9.0 + maunium.net/go/mautrix v0.20.0 sigs.k8s.io/yaml v1.4.0 ) @@ -19,17 +21,28 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + github.com/tidwall/gjson v1.17.3 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + go.mau.fi/util v0.7.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 32b0f9d..b74992e 100644 --- a/go.sum +++ b/go.sum @@ -2,13 +2,15 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -20,10 +22,15 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= -github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= @@ -38,18 +45,42 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M= github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 h1:OfRzdxCzDhp+rsKWXuOO2I/quKMJ/+TQwVbIP/gltZg= github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92/go.mod h1:7/OT02F6S6I7v6WXb+IjhMuZEYfH/RJ5RwEWnEo5BMg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94= +github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +go.mau.fi/util v0.7.0 h1:l31z+ivrSQw+cv/9eFebEqtQW2zhxivGypn+JT0h/ws= +go.mau.fi/util v0.7.0/go.mod h1:bWYreIoTULL/UiRbZdfddPh7uWDFW5yX4YCv5FB0eE0= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA= +golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -57,5 +88,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +maunium.net/go/mautrix v0.20.0 h1:bzQnVQR+LvQxV1YlAr7BSWCS8AWa0Ov0lyPhbbChM0o= +maunium.net/go/mautrix v0.20.0/go.mod h1:V725r8w7oddsS7CxnmTAp634A4nwJCFY7J3jiTMUz2c= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/matrix/client.go b/internal/matrix/client.go index e648839..5be3e59 100644 --- a/internal/matrix/client.go +++ b/internal/matrix/client.go @@ -7,24 +7,20 @@ package matrix import ( "context" - "github.com/matrix-org/gomatrix" + "fmt" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/sebhoss/matrix-alertmanager-receiver/internal/config" + "html" "log/slog" + "maunium.net/go/mautrix" + "maunium.net/go/mautrix/event" + "maunium.net/go/mautrix/id" "os" - "slices" + "regexp" ) var ( - joinRoomSuccessTotal = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "matrix_alertmanager_receiver_join_room_success_total", - Help: "The total number of successful join room operations", - }, []string{"room"}) - joinRoomFailureTotal = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "matrix_alertmanager_receiver_join_room_failure_total", - Help: "The total number of failed join room operations", - }, []string{"room"}) sendSuccessTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "matrix_alertmanager_receiver_send_success_total", Help: "The total number of successful send operations", @@ -37,64 +33,49 @@ var ( type SendingFunc func(htmlText string, roomID string) -var joinedRoomIDs []string +// An HTMLMessage is the contents of a Matrix HTML formated message event. +type HTMLMessage struct { + Body string `json:"body"` + MsgType string `json:"msgtype"` + Format string `json:"format"` + FormattedBody string `json:"formatted_body"` +} + +var htmlRegex = regexp.MustCompile("<[^<]+?>") + +// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition +// to the provided HTML. +func GetHTMLMessage(msgtype, htmlText string) HTMLMessage { + return HTMLMessage{ + Body: html.UnescapeString(htmlRegex.ReplaceAllLiteralString(htmlText, "")), + MsgType: msgtype, + Format: "org.matrix.custom.html", + FormattedBody: htmlText, + } +} func CreatingSendingFunc(ctx context.Context, configuration config.Matrix) SendingFunc { matrixClient := createMatrixClient(ctx, configuration) - fetchJoinedRooms(ctx, matrixClient) - return func(htmlText string, room string) { - msg := gomatrix.GetHTMLMessage("m.text", htmlText) - mappedRoom := room - if mapped, ok := configuration.RoomMapping[room]; ok { - mappedRoom = mapped - } - err := joinRoom(ctx, matrixClient, mappedRoom) - if err != nil { - joinRoomFailureTotal.WithLabelValues(mappedRoom).Inc() - slog.ErrorContext(ctx, "Failed to join room", slog.Any("error", err)) + if respSendEvent, err := matrixClient.SendMessageEvent(ctx, id.RoomID(room), event.NewEventType("m.room.message"), GetHTMLMessage("m.text", htmlText)); err != nil { + sendFailureTotal.Inc() + slog.ErrorContext(ctx, "Could not send message to Matrix homeserver", slog.Any("error", err)) } else { - joinRoomSuccessTotal.WithLabelValues(mappedRoom).Inc() - _, err = matrixClient.SendMessageEvent(mappedRoom, "m.room.message", msg) - if err != nil { - sendFailureTotal.Inc() - slog.ErrorContext(ctx, "Could not send message to Matrix homeserver", slog.Any("error", err)) - } else { - sendSuccessTotal.Inc() - slog.DebugContext(ctx, "Message sent to Matrix homeserver") - } + sendSuccessTotal.Inc() + slog.DebugContext(ctx, fmt.Sprintf("Message %s sent to Matrix homeserver", respSendEvent.EventID)) } } } -func createMatrixClient(ctx context.Context, configuration config.Matrix) *gomatrix.Client { +func createMatrixClient(ctx context.Context, configuration config.Matrix) *mautrix.Client { + var err error + var matrixClient *mautrix.Client slog.DebugContext(ctx, "Creating Matrix client", slog.Any("configuration", configuration.LogValue())) - matrixClient, err := gomatrix.NewClient(configuration.HomeServerURL, configuration.UserID, configuration.AccessToken) - if err != nil { - slog.ErrorContext(ctx, "Could not log in to Matrix homeserver", slog.Any("error", err)) + if matrixClient, err = mautrix.NewClient(configuration.HomeServerURL, id.UserID(configuration.UserID), configuration.AccessToken); err != nil { + slog.ErrorContext(ctx, "Failed to create matrix client", slog.Any("error", err)) os.Exit(1) + } else { + slog.DebugContext(ctx, "Created Matrix client") } - slog.DebugContext(ctx, "Created Matrix client") return matrixClient } - -func fetchJoinedRooms(ctx context.Context, client *gomatrix.Client) { - joinedRooms, err := client.JoinedRooms() - if err != nil { - slog.ErrorContext(ctx, "Could not fetch Matrix rooms", slog.Any("error", err)) - os.Exit(1) - } - joinedRoomIDs = append(joinedRoomIDs, joinedRooms.JoinedRooms...) -} - -func joinRoom(ctx context.Context, client *gomatrix.Client, roomToJoin string) error { - if !slices.Contains(joinedRoomIDs, roomToJoin) { - slog.DebugContext(ctx, "Joining room", slog.String("room", roomToJoin)) - _, err := client.JoinRoom(roomToJoin, "", nil) - if err != nil { - return err - } - joinedRoomIDs = append(joinedRoomIDs, roomToJoin) - } - return nil -} From d5fc480a331ce07f39139cc08546dc2899d5776f Mon Sep 17 00:00:00 2001 From: Harry Metske Date: Fri, 30 Aug 2024 13:56:30 +0200 Subject: [PATCH 2/4] update go.mod --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index c8f2cea..c8fe25e 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,6 @@ module github.com/sebhoss/matrix-alertmanager-receiver go 1.23 -toolchain go1.23.0 - require ( github.com/prometheus/alertmanager v0.27.0 github.com/prometheus/client_golang v1.20.2 From 843405c628e410b7187c099090eaaea38be8609d Mon Sep 17 00:00:00 2001 From: Harry Metske Date: Fri, 30 Aug 2024 20:58:25 +0200 Subject: [PATCH 3/4] add an explicit room join back and also the room mapping --- internal/matrix/client.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/internal/matrix/client.go b/internal/matrix/client.go index 5be3e59..8b0c5a6 100644 --- a/internal/matrix/client.go +++ b/internal/matrix/client.go @@ -57,12 +57,20 @@ func GetHTMLMessage(msgtype, htmlText string) HTMLMessage { func CreatingSendingFunc(ctx context.Context, configuration config.Matrix) SendingFunc { matrixClient := createMatrixClient(ctx, configuration) return func(htmlText string, room string) { - if respSendEvent, err := matrixClient.SendMessageEvent(ctx, id.RoomID(room), event.NewEventType("m.room.message"), GetHTMLMessage("m.text", htmlText)); err != nil { - sendFailureTotal.Inc() - slog.ErrorContext(ctx, "Could not send message to Matrix homeserver", slog.Any("error", err)) + mappedRoom := room + if mapped, ok := configuration.RoomMapping[room]; ok { + mappedRoom = mapped + } + if _, err := matrixClient.JoinRoom(ctx, mappedRoom, "", nil); err != nil { + slog.ErrorContext(ctx, fmt.Sprintf("Could not join room %s", room), slog.Any("error", err)) } else { - sendSuccessTotal.Inc() - slog.DebugContext(ctx, fmt.Sprintf("Message %s sent to Matrix homeserver", respSendEvent.EventID)) + if respSendEvent, err := matrixClient.SendMessageEvent(ctx, id.RoomID(room), event.NewEventType("m.room.message"), GetHTMLMessage("m.text", htmlText)); err != nil { + sendFailureTotal.Inc() + slog.ErrorContext(ctx, "Could not send message to Matrix homeserver", slog.Any("error", err)) + } else { + sendSuccessTotal.Inc() + slog.DebugContext(ctx, fmt.Sprintf("Message %s sent to Matrix homeserver", respSendEvent.EventID)) + } } } } From e8302bc56bd25291d42c436420dfc679d384ccac Mon Sep 17 00:00:00 2001 From: Harry Metske Date: Sat, 31 Aug 2024 15:26:44 +0200 Subject: [PATCH 4/4] add prometheus metrics for room joining back fix room mapping use format.HTMLToContent instead of our own HTMLMessage --- go.mod | 1 + go.sum | 2 ++ internal/matrix/client.go | 66 ++++++++++++++++++++++++--------------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index c8fe25e..679e143 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/yuin/goldmark v1.7.4 // indirect go.mau.fi/util v0.7.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect diff --git a/go.sum b/go.sum index b74992e..f4fb2bb 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= go.mau.fi/util v0.7.0 h1:l31z+ivrSQw+cv/9eFebEqtQW2zhxivGypn+JT0h/ws= go.mau.fi/util v0.7.0/go.mod h1:bWYreIoTULL/UiRbZdfddPh7uWDFW5yX4YCv5FB0eE0= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= diff --git a/internal/matrix/client.go b/internal/matrix/client.go index 8b0c5a6..74e370f 100644 --- a/internal/matrix/client.go +++ b/internal/matrix/client.go @@ -11,16 +11,24 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/sebhoss/matrix-alertmanager-receiver/internal/config" - "html" "log/slog" "maunium.net/go/mautrix" "maunium.net/go/mautrix/event" + "maunium.net/go/mautrix/format" "maunium.net/go/mautrix/id" "os" - "regexp" + "slices" ) var ( + joinRoomSuccessTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "matrix_alertmanager_receiver_join_room_success_total", + Help: "The total number of successful join room operations", + }, []string{"room"}) + joinRoomFailureTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "matrix_alertmanager_receiver_join_room_failure_total", + Help: "The total number of failed join room operations", + }, []string{"room"}) sendSuccessTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "matrix_alertmanager_receiver_send_success_total", Help: "The total number of successful send operations", @@ -33,38 +41,22 @@ var ( type SendingFunc func(htmlText string, roomID string) -// An HTMLMessage is the contents of a Matrix HTML formated message event. -type HTMLMessage struct { - Body string `json:"body"` - MsgType string `json:"msgtype"` - Format string `json:"format"` - FormattedBody string `json:"formatted_body"` -} - -var htmlRegex = regexp.MustCompile("<[^<]+?>") - -// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition -// to the provided HTML. -func GetHTMLMessage(msgtype, htmlText string) HTMLMessage { - return HTMLMessage{ - Body: html.UnescapeString(htmlRegex.ReplaceAllLiteralString(htmlText, "")), - MsgType: msgtype, - Format: "org.matrix.custom.html", - FormattedBody: htmlText, - } -} +var joinedRoomIDs []string func CreatingSendingFunc(ctx context.Context, configuration config.Matrix) SendingFunc { matrixClient := createMatrixClient(ctx, configuration) + fetchJoinedRooms(ctx, matrixClient) return func(htmlText string, room string) { mappedRoom := room if mapped, ok := configuration.RoomMapping[room]; ok { mappedRoom = mapped } - if _, err := matrixClient.JoinRoom(ctx, mappedRoom, "", nil); err != nil { + if err := joinRoom(ctx, matrixClient, mappedRoom); err != nil { + joinRoomFailureTotal.WithLabelValues(mappedRoom).Inc() slog.ErrorContext(ctx, fmt.Sprintf("Could not join room %s", room), slog.Any("error", err)) } else { - if respSendEvent, err := matrixClient.SendMessageEvent(ctx, id.RoomID(room), event.NewEventType("m.room.message"), GetHTMLMessage("m.text", htmlText)); err != nil { + joinRoomSuccessTotal.WithLabelValues(mappedRoom).Inc() + if respSendEvent, err := matrixClient.SendMessageEvent(ctx, id.RoomID(mappedRoom), event.NewEventType("m.room.message"), format.HTMLToContent(htmlText)); err != nil { sendFailureTotal.Inc() slog.ErrorContext(ctx, "Could not send message to Matrix homeserver", slog.Any("error", err)) } else { @@ -82,8 +74,30 @@ func createMatrixClient(ctx context.Context, configuration config.Matrix) *mautr if matrixClient, err = mautrix.NewClient(configuration.HomeServerURL, id.UserID(configuration.UserID), configuration.AccessToken); err != nil { slog.ErrorContext(ctx, "Failed to create matrix client", slog.Any("error", err)) os.Exit(1) - } else { - slog.DebugContext(ctx, "Created Matrix client") } + slog.DebugContext(ctx, "Created Matrix client") return matrixClient } + +func fetchJoinedRooms(ctx context.Context, client *mautrix.Client) { + joinedRooms, err := client.JoinedRooms(ctx) + if err != nil { + slog.ErrorContext(ctx, "Could not fetch Matrix rooms", slog.Any("error", err)) + os.Exit(1) + } + for _, roomID := range joinedRooms.JoinedRooms { + joinedRoomIDs = append(joinedRoomIDs, roomID.String()) + } +} + +func joinRoom(ctx context.Context, client *mautrix.Client, roomToJoin string) error { + if !slices.Contains(joinedRoomIDs, roomToJoin) { + slog.DebugContext(ctx, "Joining room", slog.String("room", roomToJoin)) + _, err := client.JoinRoom(ctx, roomToJoin, "", nil) + if err != nil { + return err + } + joinedRoomIDs = append(joinedRoomIDs, roomToJoin) + } + return nil +}