2023-11-25 10:31:58 +08:00
|
|
|
package webhook
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2024-06-05 20:53:20 +08:00
|
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
|
|
|
|
|
|
v1pb "github.com/usememos/memos/proto/gen/api/v1"
|
2023-11-25 10:31:58 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// timeout is the timeout for webhook request. Default to 30 seconds.
|
|
|
|
timeout = 30 * time.Second
|
|
|
|
)
|
|
|
|
|
|
|
|
// Post posts the message to webhook endpoint.
|
2024-06-05 20:53:20 +08:00
|
|
|
func Post(requestPayload *v1pb.WebhookRequestPayload) error {
|
|
|
|
body, err := protojson.Marshal(requestPayload)
|
2023-11-25 10:31:58 +08:00
|
|
|
if err != nil {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Wrapf(err, "failed to marshal webhook request to %s", requestPayload.Url)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
2024-06-01 23:46:00 +08:00
|
|
|
|
2024-06-05 20:53:20 +08:00
|
|
|
req, err := http.NewRequest("POST", requestPayload.Url, bytes.NewBuffer(body))
|
2023-11-25 10:31:58 +08:00
|
|
|
if err != nil {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Wrapf(err, "failed to construct webhook request to %s", requestPayload.Url)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client := &http.Client{
|
|
|
|
Timeout: timeout,
|
|
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Wrapf(err, "failed to post webhook to %s", requestPayload.Url)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
b, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Wrapf(err, "failed to read webhook response from %s", requestPayload.Url)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
2024-02-13 09:30:48 +08:00
|
|
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Errorf("failed to post webhook %s, status code: %d, response body: %s", requestPayload.Url, resp.StatusCode, b)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
|
|
|
|
2024-06-05 20:53:20 +08:00
|
|
|
response := &struct {
|
|
|
|
Code int `json:"code"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
}{}
|
2023-11-25 10:31:58 +08:00
|
|
|
if err := json.Unmarshal(b, response); err != nil {
|
2024-06-05 20:53:20 +08:00
|
|
|
return errors.Wrapf(err, "failed to unmarshal webhook response from %s", requestPayload.Url)
|
2023-11-25 10:31:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if response.Code != 0 {
|
|
|
|
return errors.Errorf("receive error code sent by webhook server, code %d, msg: %s", response.Code, response.Message)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|