From fe44270e0ca9f02060ae1213de410491d9eb1eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20ma=CC=8Ase=CC=81n?= Date: Tue, 21 Nov 2023 17:39:11 +0100 Subject: [PATCH] fix(matrix): add missing txid to send message call --- pkg/services/matrix/matrix.go | 5 ++- pkg/services/matrix/matrix_api.go | 2 +- pkg/services/matrix/matrix_client.go | 67 +++++++++++++--------------- pkg/services/matrix/matrix_test.go | 6 +-- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/pkg/services/matrix/matrix.go b/pkg/services/matrix/matrix.go index d3936ee4..25ee0ec1 100644 --- a/pkg/services/matrix/matrix.go +++ b/pkg/services/matrix/matrix.go @@ -2,10 +2,11 @@ package matrix import ( "fmt" + "net/url" + "github.com/containrrr/shoutrrr/pkg/format" "github.com/containrrr/shoutrrr/pkg/services/standard" t "github.com/containrrr/shoutrrr/pkg/types" - "net/url" ) // Scheme is the identifying part of this service's configuration URL @@ -49,7 +50,7 @@ func (s *Service) Send(message string, params *t.Params) error { if len(errors) > 0 { for _, err := range errors { - s.Logf("error sending message: %w", err) + s.Logf("error sending message: %v", err) } return fmt.Errorf("%v error(s) sending message, with initial error: %v", len(errors), errors[0]) } diff --git a/pkg/services/matrix/matrix_api.go b/pkg/services/matrix/matrix_api.go index abf29213..625b0cf8 100644 --- a/pkg/services/matrix/matrix_api.go +++ b/pkg/services/matrix/matrix_api.go @@ -7,7 +7,7 @@ type identifierType string const ( apiLogin = "/_matrix/client/r0/login" apiRoomJoin = "/_matrix/client/r0/join/%s" - apiSendMessage = "/_matrix/client/r0/rooms/%s/send/m.room.message" + apiSendMessage = "/_matrix/client/r0/rooms/%s/send/m.room.message/%v" apiJoinedRooms = "/_matrix/client/r0/joined_rooms" contentType = "application/json" diff --git a/pkg/services/matrix/matrix_client.go b/pkg/services/matrix/matrix_client.go index 6d9de36c..72a7e7ac 100644 --- a/pkg/services/matrix/matrix_client.go +++ b/pkg/services/matrix/matrix_client.go @@ -4,10 +4,12 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "net/url" "strings" + "sync/atomic" "github.com/containrrr/shoutrrr/pkg/types" "github.com/containrrr/shoutrrr/pkg/util" @@ -17,6 +19,7 @@ type client struct { apiURL url.URL accessToken string logger types.StdLogger + counter uint64 } func newClient(host string, disableTLS bool, logger types.StdLogger) (c *client) { @@ -41,6 +44,10 @@ func newClient(host string, disableTLS bool, logger types.StdLogger) (c *client) return c } +func (c *client) txId() uint64 { + return atomic.AddUint64(&c.counter, 1) +} + func (c *client) useToken(token string) { c.accessToken = token c.updateAccessToken() @@ -127,6 +134,10 @@ func (c *client) sendToJoinedRooms(message string) (errors []error) { return append(errors, fmt.Errorf("failed to get joined rooms: %w", err)) } + if len(joinedRooms) == 0 { + return append(errors, fmt.Errorf("no rooms has been joined")) + } + // Send to all rooms that are joined for _, roomID := range joinedRooms { c.logf("Sending message to '%v'...\n", roomID) @@ -148,63 +159,49 @@ func (c *client) joinRoom(room string) (roomID string, err error) { func (c *client) sendMessageToRoom(message string, roomID string) error { resEvent := apiResEvent{} - return c.apiPost(fmt.Sprintf(apiSendMessage, roomID), apiReqSend{ + return c.apiPut(fmt.Sprintf(apiSendMessage, roomID, c.txId()), apiReqSend{ MsgType: msgTypeText, Body: message, }, &resEvent) } func (c *client) apiGet(path string, response interface{}) error { - c.apiURL.Path = path - - var err error - var res *http.Response - res, err = http.Get(c.apiURL.String()) - if err != nil { - return err - } - - var body []byte - defer res.Body.Close() - body, err = ioutil.ReadAll(res.Body) - - if res.StatusCode >= 400 { - resError := &apiResError{} - if err == nil { - if err = json.Unmarshal(body, resError); err == nil { - return resError - } - } - - return fmt.Errorf("got HTTP %v", res.Status) - } + return c.apiReq(path, "GET", nil, response) +} - if err != nil { - return err - } +func (c *client) apiPost(path string, request interface{}, response interface{}) error { + return c.apiReq(path, "POST", request, response) +} - return json.Unmarshal(body, response) +func (c *client) apiPut(path string, request interface{}, response interface{}) error { + return c.apiReq(path, "PUT", request, response) } -func (c *client) apiPost(path string, request interface{}, response interface{}) error { +func (c *client) apiReq(path string, method string, request interface{}, response interface{}) error { c.apiURL.Path = path - var err error - var body []byte + var payload io.Reader = nil + if request != nil { + body, err := json.Marshal(request) + if err != nil { + return err + } + payload = bytes.NewReader(body) + } - body, err = json.Marshal(request) + req, err := http.NewRequest(method, c.apiURL.String(), payload) if err != nil { return err } + req.Header.Set("Content-Type", contentType) - var res *http.Response - res, err = http.Post(c.apiURL.String(), contentType, bytes.NewReader(body)) + res, err := http.DefaultClient.Do(req) if err != nil { return err } defer res.Body.Close() - body, err = ioutil.ReadAll(res.Body) + body, err := ioutil.ReadAll(res.Body) if res.StatusCode >= 400 { resError := &apiResError{} diff --git a/pkg/services/matrix/matrix_test.go b/pkg/services/matrix/matrix_test.go index abf73009..937daa6d 100644 --- a/pkg/services/matrix/matrix_test.go +++ b/pkg/services/matrix/matrix_test.go @@ -167,13 +167,13 @@ func setupMockResponders() { mockServer+apiJoinedRooms, httpmock.NewStringResponder(200, `{ "joined_rooms": [ "!room:mockserver" ] }`)) - httpmock.RegisterResponder("POST", mockServer+fmt.Sprintf(apiSendMessage, "%21room:mockserver"), + httpmock.RegisterResponder("PUT", `=~`+mockServer+fmt.Sprintf(apiSendMessage, "%21room:mockserver", `[0-9]+`), httpmock.NewJsonResponderOrPanic(200, apiResEvent{EventID: "7"})) - httpmock.RegisterResponder("POST", mockServer+fmt.Sprintf(apiSendMessage, "1"), + httpmock.RegisterResponder("PUT", `=~`+mockServer+fmt.Sprintf(apiSendMessage, "1", `[0-9]+`), httpmock.NewJsonResponderOrPanic(200, apiResEvent{EventID: "8"})) - httpmock.RegisterResponder("POST", mockServer+fmt.Sprintf(apiSendMessage, "2"), + httpmock.RegisterResponder("PUT", `=~`+mockServer+fmt.Sprintf(apiSendMessage, "2", `[0-9]+`), httpmock.NewJsonResponderOrPanic(200, apiResEvent{EventID: "9"})) httpmock.RegisterResponder("POST", mockServer+fmt.Sprintf(apiRoomJoin, "%23room1"),