1package pagerduty
2
3import (
4	"encoding/json"
5	"fmt"
6
7	"github.com/google/go-querystring/query"
8)
9
10// Acknowledgement is the data structure of an acknoledgement of an incident.
11type Acknowledgement struct {
12	At           string
13	Acknowledger APIObject
14}
15
16// PendingAction is the data structure for any pending actions on an incident.
17type PendingAction struct {
18	Type string
19	At   string
20}
21
22// Assignment is the data structure for an assignment of an incident
23type Assignment struct {
24	At       string
25	Assignee APIObject
26}
27
28// Incident is a normalized, de-duplicated event generated by a PagerDuty integration.
29type Incident struct {
30	APIObject
31	IncidentNumber       uint              `json:"incident_number,omitempty"`
32	CreatedAt            string            `json:"created_at,omitempty"`
33	PendingActions       []PendingAction   `json:"pending_actions,omitempty"`
34	IncidentKey          string            `json:"incident_key,omitempty"`
35	Service              APIObject         `json:"service,omitempty"`
36	Assignments          []Assignment      `json:"assignments,omitempty"`
37	Acknowledgements     []Acknowledgement `json:"acknowledgements,omitempty"`
38	LastStatusChangeAt   string            `json:"last_status_change_at,omitempty"`
39	LastStatusChangeBy   APIObject         `json:"last_status_change_by,omitempty"`
40	FirstTriggerLogEntry APIObject         `json:"first_trigger_log_entry,omitempty"`
41	EscalationPolicy     APIObject         `json:"escalation_policy,omitempty"`
42	Teams                []APIObject       `json:"teams,omitempty"`
43	Urgency              string            `json:"urgency,omitempty"`
44	Status               string            `json:"status,omitempty"`
45	Id                   string            `json:"id,omitempty"`
46	Priority             APIObject         `json:"priority,omitempty"`
47}
48
49// ListIncidentsResponse is the response structure when calling the ListIncident API endpoint.
50type ListIncidentsResponse struct {
51	APIListObject
52	Incidents []Incident `json:"incidents,omitempty"`
53}
54
55// ListIncidentsOptions is the structure used when passing parameters to the ListIncident API endpoint.
56type ListIncidentsOptions struct {
57	APIListObject
58	Since       string   `url:"since,omitempty"`
59	Until       string   `url:"until,omitempty"`
60	DateRange   string   `url:"date_range,omitempty"`
61	Statuses    []string `url:"statuses,omitempty,brackets"`
62	IncidentKey string   `url:"incident_key,omitempty"`
63	ServiceIDs  []string `url:"service_ids,omitempty,brackets"`
64	TeamIDs     []string `url:"team_ids,omitempty,brackets"`
65	UserIDs     []string `url:"user_ids,omitempty,brackets"`
66	Urgencies   []string `url:"urgencies,omitempty,brackets"`
67	TimeZone    string   `url:"time_zone,omitempty"`
68	SortBy      string   `url:"sort_by,omitempty"`
69	Includes    []string `url:"include,omitempty,brackets"`
70}
71
72// ListIncidents lists existing incidents.
73func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, error) {
74	v, err := query.Values(o)
75	if err != nil {
76		return nil, err
77	}
78	resp, err := c.get("/incidents?" + v.Encode())
79	if err != nil {
80		return nil, err
81	}
82	var result ListIncidentsResponse
83	return &result, c.decodeJSON(resp, &result)
84}
85
86// CreateIncident is the structure POST'd to the incidents endpoint. It wraps a CreateIncidentValue
87type CreateIncident struct {
88	Incident CreateIncidentOptions `json:"incident"`
89}
90
91// createIncidentResponse is returned from the API when creating a response.
92type createIncidentResponse struct {
93	Incident Incident `json:incident`
94}
95
96// CreateIncidentOptions is the structure used when POSTing to the CreateIncident API endpoint.
97type CreateIncidentOptions struct {
98	Type             string       `json:"type"`
99	Title            string       `json:"title"`
100	Service          APIReference `json:"service"`
101	Priority         APIReference `json:"priority"`
102	IncidentKey      string       `json:"incident_key"`
103	Body             APIDetails   `json:"body"`
104	EscalationPolicy APIReference `json:"escalation_policy"`
105}
106
107// CreateIncident creates an incident synchronously without a corresponding event from a monitoring service.
108func (c *Client) CreateIncident(from string, i *CreateIncident) (*Incident, error) {
109	headers := make(map[string]string)
110	headers["From"] = from
111	resp, e := c.post("/incidents", i, &headers)
112	if e != nil {
113		return nil, e
114	}
115
116	var ii createIncidentResponse
117	e = json.NewDecoder(resp.Body).Decode(&ii)
118	if e != nil {
119		return nil, e
120	}
121
122	return &ii.Incident, nil
123}
124
125// ManageIncidents acknowledges, resolves, escalates, or reassigns one or more incidents.
126func (c *Client) ManageIncidents(from string, incidents []Incident) error {
127	r := make(map[string][]Incident)
128	headers := make(map[string]string)
129	headers["From"] = from
130	r["incidents"] = incidents
131	_, e := c.put("/incidents", r, &headers)
132	return e
133}
134
135// GetIncident shows detailed information about an incident.
136func (c *Client) GetIncident(id string) (*Incident, error) {
137	resp, err := c.get("/incidents/" + id)
138	if err != nil {
139		return nil, err
140	}
141	var result map[string]Incident
142	if err := c.decodeJSON(resp, &result); err != nil {
143		return nil, err
144	}
145	i, ok := result["incident"]
146	if !ok {
147		return nil, fmt.Errorf("JSON response does not have incident field")
148	}
149	return &i, nil
150}
151
152// IncidentNote is a note for the specified incident.
153type IncidentNote struct {
154	ID        string    `json:"id,omitempty"`
155	User      APIObject `json:"user,omitempty"`
156	Content   string    `json:"content,omitempty"`
157	CreatedAt string    `json:"created_at,omitempty"`
158}
159
160// ListIncidentNotes lists existing notes for the specified incident.
161func (c *Client) ListIncidentNotes(id string) ([]IncidentNote, error) {
162	resp, err := c.get("/incidents/" + id + "/notes")
163	if err != nil {
164		return nil, err
165	}
166	var result map[string][]IncidentNote
167	if err := c.decodeJSON(resp, &result); err != nil {
168		return nil, err
169	}
170	notes, ok := result["notes"]
171	if !ok {
172		return nil, fmt.Errorf("JSON response does not have notes field")
173	}
174	return notes, nil
175}
176
177// IncidentAlert is a alert for the specified incident.
178type IncidentAlert struct {
179	ID        string    `json:"id,omitempty"`
180	Summary	  string    `json:"summary,omitempty"`
181	CreatedAt string    `json:"created_at,omitempty"`
182	AlertKey  string    `json:"alert_key,omitempty"`
183}
184
185// ListIncidentAlerts lists existing alerts for the specified incident.
186func (c *Client) ListIncidentAlerts(id string) ([]IncidentAlert, error) {
187	resp, err := c.get("/incidents/"+id+"/alerts")
188	if err != nil {
189		return nil, err
190	}
191	var result map[string][]IncidentAlert
192	if err := c.decodeJSON(resp, &result); err != nil {
193		return nil, err
194	}
195	alerts, ok := result["alerts"]
196	if !ok {
197		return nil, fmt.Errorf("JSON response does not have alerts field")
198	}
199	return alerts, nil
200}
201
202// CreateIncidentNote creates a new note for the specified incident.
203func (c *Client) CreateIncidentNote(id string, note IncidentNote) error {
204	data := make(map[string]IncidentNote)
205	data["note"] = note
206	_, err := c.post("/incidents/"+id+"/notes", data, nil)
207	return err
208}
209
210// SnoozeIncident sets an incident to not alert for a specified period of time.
211func (c *Client) SnoozeIncident(id string, duration uint) error {
212	data := make(map[string]uint)
213	data["duration"] = duration
214	_, err := c.post("/incidents/"+id+"/snooze", data, nil)
215	return err
216}
217
218// ListIncidentLogEntriesResponse is the response structure when calling the ListIncidentLogEntries API endpoint.
219type ListIncidentLogEntriesResponse struct {
220	APIListObject
221	LogEntries []LogEntry `json:"log_entries,omitempty"`
222}
223
224// ListIncidentLogEntriesOptions is the structure used when passing parameters to the ListIncidentLogEntries API endpoint.
225type ListIncidentLogEntriesOptions struct {
226	APIListObject
227	Includes   []string `url:"include,omitempty,brackets"`
228	IsOverview bool     `url:"is_overview,omitempty"`
229	TimeZone   string   `url:"time_zone,omitempty"`
230}
231
232// ListIncidentLogEntries lists existing log entries for the specified incident.
233func (c *Client) ListIncidentLogEntries(id string, o ListIncidentLogEntriesOptions) (*ListIncidentLogEntriesResponse, error) {
234	v, err := query.Values(o)
235	if err != nil {
236		return nil, err
237	}
238	resp, err := c.get("/incidents/" + id + "/log_entries?" + v.Encode())
239	if err != nil {
240		return nil, err
241	}
242	var result ListIncidentLogEntriesResponse
243	return &result, c.decodeJSON(resp, &result)
244}
245