package coreAPI import ( "bytes" "encoding/json" "errors" "fmt" "net/http" ) type ( // Update : Defines the data required to update a CORE ticket with a new message Update struct { Ticket string `json:"ticket"` Msg string `json:"msg"` Status string `json:"status"` BBCode bool `json:"bbcode"` CType string `json:"ctype"` } // Response : Defines the information returned from either a CreateTicket or UpdateTicket call Response struct { Number string `json:"number"` Status string `json:"status"` } // ticketInfoResponse: Used for json unmarshalling of a coreAPI response to a request for ticket information ticketInfoResponse struct { Result *Info `json:"result"` } // Info : Defines the details of a CORE Ticket Info struct { Account string `json:"account"` Assignee string `json:"assignee"` Created string `json:"created"` Devices []int `json:"devices"` HasPubicComment bool `json:"has_public_comment"` Messages Message `json:"messages"` Number string `json:"number"` Priority string `json:"priority"` PrivateTicket int `json:"private_ticket"` QueueName string `json:"queue_name"` StatusName string `json:"status_name"` Subject string `json:"subject"` SubTickets []string `json:"subtickets"` SuperTicket string `json:"superticket"` } // Message : Defines the structure of a message on a CORE ticket Message struct { Attribute string `json:"attribute"` Subattributes []struct { Datetime string `json:"datetime"` UserID string `json:"userid"` } `json:"subattributes"` } // CreateTicketPayload : Defines the parameters valid for the CreateTicket function CreateTicketPayload struct { // Devices to include on ticket Devices []int `json:"devices"` // Body of ticket Message string `json:"msg"` // Subject of Ticket Subject string `json:"subject"` // Indicates if the Message contains BBCode BBCode bool `json:"bbcode,omitempty"` // Comment Type, either "private" or "public" CType string `json:"ctype,omitempty"` // Queue name to place ticket in to. If not provided will be placed in Netsec queue for the segment the account is in (smb/enterprise/etc) Queue string `json:"queue,omitempty"` // Status to place ticket in initially. If not included will be placed in 'New' status Status string `json:"status,omitempty"` } ) // TicketUpdate : Adds a new message or changes the status of an existing ticket func (c Client) TicketUpdate(ticket, msg, status string, bbCode, public bool) (Response, error) { payload, err := json.Marshal(Update{ Ticket: ticket, Msg: msg, Status: status, BBCode: bbCode, CType: func() string { if public { return "public" } return "private" }(), }) if err != nil { return Response{}, err } req, err := http.NewRequest(http.MethodPost, URLBase+"/core/addMessage", bytes.NewReader(payload)) if err != nil { return Response{}, err } // Set the request headers c.reqHeaders(req) res, err := http.DefaultClient.Do(req) if res != nil { defer func() { if defErr := res.Body.Close(); defErr != nil { err = fmt.Errorf("%s:%s", err, defErr) } }() } if err != nil { return Response{}, err } if res.StatusCode != 200 { return Response{}, fmt.Errorf("coreAPI:TicketUpdate:%s", res.Status) } var tr Response if err := json.NewDecoder(res.Body).Decode(&tr); err != nil { return Response{}, err } return tr, err } // TicketCreate : Creates a new CORE ticket for a given device or list of devices func (c Client) TicketCreate(ps CreateTicketPayload) (Response, error) { var resp Response // required = devices, msg, subject if len(ps.Devices) == 0 { return resp, errors.New("devices slice can not be empty") } if ps.Message == "" { return resp, errors.New("msg can not be empty") } if ps.Subject == "" { return resp, errors.New("subject can not be empty") } jsonStr, err := json.Marshal(ps) if err != nil { return resp, err } req, err := http.NewRequest(http.MethodPost, URLBase+"/core/createTicket", bytes.NewReader(jsonStr)) if err != nil { return resp, err } // Set the request headers c.reqHeaders(req) res, err := http.DefaultClient.Do(req) if res != nil { defer func() { if defErr := res.Body.Close(); defErr != nil { err = fmt.Errorf("%s:%s", err, defErr) } }() } if err != nil { return resp, err } // Unmarshal the response if err := json.NewDecoder(res.Body).Decode(&resp); err != nil { return Response{}, err } // Return the data return resp, nil } // TicketInfo : Returns data on an existing ticket func (c Client) TicketInfo(ticket string) (*Info, error) { if c.Token == nil { return nil, errors.New("core token missing") } req, err := http.NewRequest(http.MethodGet, URLBase+"/core/ticket/"+ticket, nil) if err != nil { return nil, err } // Set the request headers c.reqHeaders(req) res, err := http.DefaultClient.Do(req) if res != nil { defer func() { if defErr := res.Body.Close(); defErr != nil { err = fmt.Errorf("%s:%s", err, defErr) } }() } if err != nil { return nil, err } if res.StatusCode != 200 { return nil, fmt.Errorf("error retrieving ticket information: %d - %s", res.StatusCode, res.Status) } var tr ticketInfoResponse if err := json.NewDecoder(res.Body).Decode(&tr); err != nil { return nil, err } if tr.Result == nil { return nil, fmt.Errorf("no ticket data found for %s", ticket) } return tr.Result, nil }