Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom objects v2 #280

Merged
merged 4 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions zendesk/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type API interface {
UserFieldAPI
ViewAPI
WebhookAPI
CustomObjectAPI
}

var _ API = (*Client)(nil)
172 changes: 172 additions & 0 deletions zendesk/custom_object.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package zendesk

import (
"context"
"encoding/json"
"fmt"
"time"
)

type CustomObjectRecord struct {
Url string `json:"url,omitempty"`
Name string `json:"name,omitempty"`
ID string `json:"id,omitempty"`
CustomObjectKey string `json:"custom_object_key"`
CustomObjectFields map[string]interface{} `json:"custom_object_fields" binding:"required"`
CreatedByUserID string `json:"created_by_user_id,omitempty"`
UpdatedByUserID string `json:"updated_by_user_id,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}

// CustomObjectAPI an interface containing all custom object related methods
type CustomObjectAPI interface {
CreateCustomObjectRecord(
ctx context.Context, record CustomObjectRecord, customObjectKey string) (CustomObjectRecord, error)
SearchCustomObjectRecords(
ctx context.Context,
customObjectKey string,
opts *CustomObjectAutocompleteOptions,
) ([]CustomObjectRecord, Page, error)
ListCustomObjectRecords(
ctx context.Context, customObjectKey string, opts *CustomObjectListOptions) ([]CustomObjectRecord, Page, error)
ShowCustomObjectRecord(
ctx context.Context, customObjectKey string, customObjectRecordID string,
) (*CustomObjectRecord, error)
UpdateCustomObjectRecord(
ctx context.Context, customObjectKey string, customObjectRecordID string, record CustomObjectRecord,
) (*CustomObjectRecord, error)
}

// CustomObjectAutocompleteOptions custom object search options
type CustomObjectAutocompleteOptions struct {
PageOptions
Name string `url:"name"`
}

// CreateCustomObjectRecord CreateCustomObject create a custom object record
func (z *Client) CreateCustomObjectRecord(
ctx context.Context, record CustomObjectRecord, customObjectKey string,
) (CustomObjectRecord, error) {

var data, result struct {
CustomObjectRecord CustomObjectRecord `json:"custom_object_record"`
}
data.CustomObjectRecord = record

body, err := z.post(ctx, fmt.Sprintf("/custom_objects/%s/records.json", customObjectKey), data)
if err != nil {
return CustomObjectRecord{}, err
}
err = json.Unmarshal(body, &result)
if err != nil {
return CustomObjectRecord{}, err
}
return result.CustomObjectRecord, nil
}

// CustomObjectListOptions custom object list options
type CustomObjectListOptions struct {
PageOptions
ExternalIds []string `url:"external_ids"`
}

// ListCustomObjectRecords list objects
// https://developer.zendesk.com/api-reference/custom-objects/custom_object_records/#list-custom-object-records
func (z *Client) ListCustomObjectRecords(
ctx context.Context, customObjectKey string, opts *CustomObjectListOptions) ([]CustomObjectRecord, Page, error) {
var result struct {
CustomObjectRecords []CustomObjectRecord `json:"custom_object_records"`
Page
}
tmp := opts
if tmp == nil {
tmp = &CustomObjectListOptions{}
}
url := fmt.Sprintf("/custom_objects/%s/records", customObjectKey)
urlWithOptions, err := addOptions(url, tmp)
body, err := z.get(ctx, urlWithOptions)

if err != nil {
return nil, Page{}, err
}
err = json.Unmarshal(body, &result)
if err != nil {
return nil, Page{}, err
}
return result.CustomObjectRecords, result.Page, nil
}

// SearchCustomObjectRecords search for a custom object record by the name field
// https://developer.zendesk.com/api-reference/custom-objects/custom_object_records/#search-custom-object-records
func (z *Client) SearchCustomObjectRecords(
ctx context.Context, customObjectKey string, opts *CustomObjectAutocompleteOptions) ([]CustomObjectRecord, Page, error) {
var result struct {
CustomObjectRecords []CustomObjectRecord `json:"custom_object_records"`
Page
}
tmp := opts
if tmp == nil {
tmp = &CustomObjectAutocompleteOptions{}
}
url := fmt.Sprintf("/custom_objects/%s/records/autocomplete", customObjectKey)
urlWithOptions, err := addOptions(url, tmp)
body, err := z.get(ctx, urlWithOptions)

if err != nil {
return nil, Page{}, err
}
err = json.Unmarshal(body, &result)
if err != nil {
return nil, Page{}, err
}
return result.CustomObjectRecords, result.Page, nil
}

// ShowCustomObjectRecord returns a custom record for a specific object using a provided id.
// https://developer.zendesk.com/api-reference/custom-objects/custom_object_records/#show-custom-object-record
func (z *Client) ShowCustomObjectRecord(
ctx context.Context, customObjectKey string, customObjectRecordID string,
) (*CustomObjectRecord, error) {
var result struct {
CustomObjectRecord CustomObjectRecord `json:"custom_object_record"`
}

url := fmt.Sprintf("/custom_objects/%s/records/%s", customObjectKey, customObjectRecordID)
body, err := z.get(ctx, url)

if err != nil {
return nil, err
}
err = json.Unmarshal(body, &result)

if err != nil {
return nil, err
}
return &result.CustomObjectRecord, nil
}

// UpdateCustomObjectRecord Updates an individual custom object record
// https://developer.zendesk.com/api-reference/custom-objects/custom_object_records/#update-custom-object-record
func (z *Client) UpdateCustomObjectRecord(
ctx context.Context, customObjectKey string, customObjectRecordID string, record CustomObjectRecord,
) (*CustomObjectRecord, error) {
var data, result struct {
CustomObjectRecord CustomObjectRecord `json:"custom_object_record"`
}
data.CustomObjectRecord = record

url := fmt.Sprintf("/custom_objects/%s/records/%s", customObjectKey, customObjectRecordID)
body, err := z.patch(ctx, url, data)

if err != nil {
return nil, err
}
err = json.Unmarshal(body, &result)

if err != nil {
return nil, err
}
return &result.CustomObjectRecord, nil
}
77 changes: 77 additions & 0 deletions zendesk/mock/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions zendesk/zendesk.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,42 @@ func (z *Client) put(ctx context.Context, path string, data interface{}) ([]byte
return body, nil
}

// patch sends data to API and returns response body as []bytes
func (z *Client) patch(ctx context.Context, path string, data interface{}) ([]byte, error) {
bytes, err := json.Marshal(data)
if err != nil {
return nil, err
}

req, err := http.NewRequest(http.MethodPatch, z.baseURL.String()+path, strings.NewReader(string(bytes)))
if err != nil {
return nil, err
}

req = z.prepareRequest(ctx, req)

resp, err := z.httpClient.Do(req)
if err != nil {
return nil, err
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

// NOTE: some webhook mutation APIs return status No Content.
if !(resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNoContent) {
return nil, Error{
body: body,
resp: resp,
}
}

return body, nil
}

// delete sends data to API and returns an error if unsuccessful
func (z *Client) delete(ctx context.Context, path string) error {
req, err := http.NewRequest(http.MethodDelete, z.baseURL.String()+path, nil)
Expand Down