From 684991327e43aa7c570a1c895984f4a0a3652517 Mon Sep 17 00:00:00 2001 From: Chris Wynn <939050+wcwynn@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:56:41 +0900 Subject: [PATCH] Webhook improvements (#22) * Added ability to receive actual webhook details - This commit adds some support to get the actual webhook url and other details. The webhook url is required as a parameter when deleting the webhook. When deleting the webhook, the configured webhook may be unknown. In such cases it is necessary to have a means to actually retrieve the url in order to provide the parameter required for a succssful delete request. * Fixed bug in deleteWebhook - Changed from DEL to POST so that it works and matches the API spec * Fixed failing webhook test - Updated the test expectation to match the api spec --- webhook.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++- webhook_test.go | 4 +-- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/webhook.go b/webhook.go index fddc8af..3ee1d99 100644 --- a/webhook.go +++ b/webhook.go @@ -73,6 +73,30 @@ const ( type webhookQueryResponse struct { } +type webhookQueryUrlResponse struct { + StatusCode int `json:"statusCode"` + Message string `json:"message"` + Body webhookQueryUrlResponseBody `json:"body"` +} + +type webhookQueryUrlResponseBody struct { + URLs []string `json:"urls"` +} + +type webhookQueryDetailsResponse struct { + StatusCode int `json:"statusCode"` + Message string `json:"message"` + Body []WebhookQueryDetails `json:"body"` +} + +type WebhookQueryDetails struct { + URL string `json:"url"` + CreateTime int64 `json:"createTime"` + LastUpdate int64 `json:"lastUpdateTime"` + DeviceList string `json:"deviceList"` + Enable bool `json:"enable"` +} + // Query retrieves the current configuration info of the webhook. // The second argument `url` is required for QueryDetails action type. func (svc *WebhookService) Query(ctx context.Context, action WebhookQueryActionType, url string) error { @@ -100,6 +124,71 @@ func (svc *WebhookService) Query(ctx context.Context, action WebhookQueryActionT return nil } +// QueryUrl retrieves the current url configuration info of the webhook. +func (svc *WebhookService) QueryUrl(ctx context.Context) (string, error) { + const path = "/v1.1/webhook/queryWebhook" + + req := webhookQueryRequest{ + Action: QueryURL, + } + + resp, err := svc.c.post(ctx, path, req) + if err != nil { + return "", err + } + defer resp.Close() + + var response webhookQueryUrlResponse + if err := resp.DecodeJSON(&response); err != nil { + return "", err + } + + if response.StatusCode == 190 { + return "", fmt.Errorf("undocumented error %d occurred for queryWebhook API: %s", response.StatusCode, response.Message) + } else if response.StatusCode != 100 { + return "", fmt.Errorf("unknown error %d from queryWebhook API: %s", response.StatusCode, response.Message) + } + + if len(response.Body.URLs) < 1 { + return "", errors.New("queryWebhook API response urls is empty") + } + + return response.Body.URLs[0], nil +} + +// QueryDetails retrieves the current details configuration info of the webhook. +func (svc *WebhookService) QueryDetails(ctx context.Context, url string) (*WebhookQueryDetails, error) { + const path = "/v1.1/webhook/queryWebhook" + + req := webhookQueryRequest{ + Action: QueryDetails, + } + req.URLs = []string{url} + + resp, err := svc.c.post(ctx, path, req) + if err != nil { + return nil, err + } + defer resp.Close() + + var response webhookQueryDetailsResponse + if err := resp.DecodeJSON(&response); err != nil { + return nil, err + } + + if response.StatusCode == 190 { + return nil, fmt.Errorf("undocumented error %d occurred for queryWebhook API: %s", response.StatusCode, response.Message) + } else if response.StatusCode != 100 { + return nil, fmt.Errorf("unknown error %d from queryWebhook API: %s", response.StatusCode, response.Message) + } + + if len(response.Body) < 1 { + return nil, errors.New("queryWebhook API response body is empty") + } + + return &response.Body[0], nil +} + type webhookUpdateRequest struct { Action string `json:"action"` // the type of actions but for now this must be updateWebhook Config webhookConfig `json:"config"` @@ -145,7 +234,7 @@ func (svc *WebhookService) Delete(ctx context.Context, url string) error { URL: url, } - resp, err := svc.c.del(ctx, path, req) + resp, err := svc.c.post(ctx, path, req) if err != nil { return err } diff --git a/webhook_test.go b/webhook_test.go index d32fa8b..8cf6035 100644 --- a/webhook_test.go +++ b/webhook_test.go @@ -155,8 +155,8 @@ func TestWebhookDelete(t *testing.T) { http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"statusCode":100,"body":{},"message":""}`)) - if r.Method != http.MethodDelete { - t.Fatalf("DELETE method is expected but %s", r.Method) + if r.Method != http.MethodPost { + t.Fatalf("POST method is expected but %s", r.Method) } var got map[string]string