github.com/wtfutil/wtf@v0.43.0/modules/pagerduty/widget.go (about) 1 package pagerduty 2 3 import ( 4 "fmt" 5 "sort" 6 "time" 7 8 "github.com/PagerDuty/go-pagerduty" 9 "github.com/rivo/tview" 10 "github.com/wtfutil/wtf/utils" 11 "github.com/wtfutil/wtf/view" 12 ) 13 14 const ( 15 onCallTimeAPILayout = "2006-01-02T15:04:05Z" 16 onCallTimeDisplayLayout = "Jan 2, 2006" 17 ) 18 19 type Widget struct { 20 view.TextWidget 21 22 settings *Settings 23 } 24 25 // NewWidget creates and returns an instance of PagerDuty widget 26 func NewWidget(tviewApp *tview.Application, redrawChan chan bool, settings *Settings) *Widget { 27 widget := Widget{ 28 TextWidget: view.NewTextWidget(tviewApp, redrawChan, nil, settings.Common), 29 30 settings: settings, 31 } 32 33 return &widget 34 } 35 36 /* -------------------- Exported Functions -------------------- */ 37 38 func (widget *Widget) Refresh() { 39 var onCalls []pagerduty.OnCall 40 var incidents []pagerduty.Incident 41 42 var err1 error 43 var err2 error 44 45 if widget.settings.showIncidents { 46 teamIDs := utils.ToStrs(widget.settings.teamIDs) 47 userIDs := utils.ToStrs(widget.settings.userIDs) 48 incidents, err2 = GetIncidents(widget.settings.apiKey, teamIDs, userIDs) 49 } 50 51 if widget.settings.showSchedules { 52 scheduleIDs := utils.ToStrs(widget.settings.scheduleIDs) 53 onCalls, err1 = GetOnCalls(widget.settings.apiKey, scheduleIDs) 54 } 55 56 var content string 57 wrap := false 58 if err1 != nil || err2 != nil { 59 wrap = true 60 if err1 != nil { 61 content += err1.Error() 62 } 63 if err2 != nil { 64 content += err2.Error() 65 } 66 } else { 67 widget.View.SetWrap(false) 68 content = widget.contentFrom(onCalls, incidents) 69 } 70 71 widget.Redraw(func() (string, string, bool) { return widget.CommonSettings().Title, content, wrap }) 72 } 73 74 /* -------------------- Unexported Functions -------------------- */ 75 76 func (widget *Widget) contentFrom(onCalls []pagerduty.OnCall, incidents []pagerduty.Incident) string { 77 var str string 78 79 // Incidents 80 81 if widget.settings.showIncidents { 82 str += fmt.Sprintf("[%s] Incidents[white]\n", widget.settings.Colors.Subheading) 83 84 if len(incidents) > 0 { 85 for _, incident := range incidents { 86 str += fmt.Sprintf("\n [%s]%s[white]\n", widget.settings.Colors.Label, tview.Escape(incident.Summary)) 87 str += fmt.Sprintf(" Status: %s\n", incident.Status) 88 str += fmt.Sprintf(" Service: %s\n", incident.Service.Summary) 89 str += fmt.Sprintf(" Escalation: %s\n", incident.EscalationPolicy.Summary) 90 str += fmt.Sprintf(" Link: %s\n", incident.HTMLURL) 91 } 92 } else { 93 str += "\n No open incidents\n" 94 } 95 96 str += "\n" 97 } 98 99 onCallTree := make(map[string][]pagerduty.OnCall) 100 101 filter := make(map[string]bool) 102 for _, item := range widget.settings.escalationFilter { 103 filter[item.(string)] = true 104 } 105 106 // OnCalls 107 108 for _, onCall := range onCalls { 109 summary := onCall.EscalationPolicy.Summary 110 if len(widget.settings.escalationFilter) == 0 || filter[summary] { 111 onCallTree[summary] = append(onCallTree[summary], onCall) 112 } 113 } 114 115 // We want to sort our escalation policies for predictability/ease of finding 116 keys := make([]string, 0, len(onCallTree)) 117 for k := range onCallTree { 118 keys = append(keys, k) 119 } 120 121 sort.Strings(keys) 122 123 if len(keys) > 0 { 124 str += fmt.Sprintf("[%s] Schedules[white]\n", widget.settings.Colors.Subheading) 125 126 // Print out policies, and escalation order of users 127 for _, key := range keys { 128 str += fmt.Sprintf( 129 "\n [%s]%s\n", 130 widget.settings.Colors.Label, 131 key, 132 ) 133 134 values := onCallTree[key] 135 sort.Sort(ByEscalationLevel(values)) 136 137 for _, onCall := range values { 138 str += fmt.Sprintf( 139 " [%s]%d - %s\n", 140 widget.settings.Colors.Text, 141 onCall.EscalationLevel, 142 widget.userSummary(&onCall), 143 ) 144 145 onCallEnd := widget.onCallEndSummary(&onCall) 146 if onCallEnd != "" { 147 str += fmt.Sprintf( 148 " %s\n", 149 onCallEnd, 150 ) 151 } 152 } 153 } 154 } 155 156 return str 157 } 158 159 // onCallEndSummary may or may not return the date that the specified onCall schedule ends 160 func (widget *Widget) onCallEndSummary(onCall *pagerduty.OnCall) string { 161 if !widget.settings.showOnCallEnd { 162 return "" 163 } 164 165 if onCall.End == "" { 166 return "" 167 } 168 169 end, err := time.Parse(onCallTimeAPILayout, onCall.End) 170 if err != nil { 171 return "" 172 } 173 174 return end.Format(onCallTimeDisplayLayout) 175 } 176 177 // userSummary returns the name of the person assigned to the specified onCall schedule 178 func (widget *Widget) userSummary(onCall *pagerduty.OnCall) string { 179 summary := onCall.User.Summary 180 181 if summary == widget.settings.myName { 182 summary = fmt.Sprintf("[::b]%s", summary) 183 } 184 185 return summary 186 }