Skip to content

Commit c2cc3ed

Browse files
committed
chore(.gitignore): add __debug_bin* to ignore list to prevent clutter in the repository
feat(launch.json): add new launch configuration for getting calendar data to streamline development feat(calendar.go): enhance calendar event formatting with styles for better readability fix(calendar.go): improve event sorting logic to handle simultaneous start times correctly fix(ical_client.go): enhance error logging with additional context for easier debugging refactor(ical_client.go): rename saveIcalParse to safeIcalParse for clarity in function purpose
1 parent bc80097 commit c2cc3ed

6 files changed

Lines changed: 175 additions & 23 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.pio
2+
__debug_bin*
23
.vscode/.browse.c_cpp.db*
34
.vscode/c_cpp_properties.json
45
.vscode/launch.json

.vscode/launch.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
"serve"
1515
]
1616

17+
},
18+
{
19+
"name": "get calendar",
20+
"type": "go",
21+
"request": "launch",
22+
"mode": "auto",
23+
"program": "${workspaceFolder}/src/main.go",
24+
"args": [
25+
"get", "calendar", "--server", "127.0.0.1", "--debug", "--grpcPort", "50051"
26+
]
27+
1728
}
1829
]
1930
}

src/cmd/calendar.go

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/SpechtLabs/CalendarAPI/pkg/api"
1010
pb "github.com/SpechtLabs/CalendarAPI/pkg/protos"
11+
"github.com/charmbracelet/lipgloss"
1112
"github.com/spechtlabs/go-otel-utils/otelzap"
1213
"github.com/spf13/cobra"
1314
"go.uber.org/zap"
@@ -97,29 +98,124 @@ var getCalendarCmd = &cobra.Command{
9798
}
9899

99100
func formatText(resp *pb.CalendarResponse) string {
100-
outStr := fmt.Sprintf("Got Calendar (last refreshed: %s)\n\n", time.Unix(resp.LastUpdated, 0).Format(time.RFC822))
101+
now := time.Now()
102+
103+
// Styles
104+
headerStyle := lipgloss.NewStyle().Bold(true).Underline(true)
105+
contextStyle := lipgloss.NewStyle().Italic(true).Foreground(lipgloss.Color("#999999"))
106+
importantStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#FF0000")).Bold(true)
107+
freeStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#999999"))
108+
tentativeStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#FFA500")).Italic(true)
109+
outOfOfficeStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#800080")).Bold(true)
110+
defaultStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#FFFFFF"))
111+
strikeThroughStyle := lipgloss.NewStyle().Strikethrough(true).Foreground(lipgloss.Color("#666666"))
112+
113+
outStr := ""
114+
outStr += contextStyle.Render(fmt.Sprintf("(last refreshed: %s)", time.Unix(resp.LastUpdated, 0).Format(time.TimeOnly)))
115+
outStr += "\n\n"
116+
117+
outStr += fmt.Sprintf("Calendar: %s Date: %s",
118+
headerStyle.Render(resp.CalendarName),
119+
headerStyle.Render(time.Unix(resp.LastUpdated, 0).Format(time.DateOnly)),
120+
)
121+
122+
outStr += "\n"
123+
124+
// Separate all-day from timed events
125+
allDayEntries := []*pb.CalendarEntry{}
126+
normalEntries := []*pb.CalendarEntry{}
127+
showCalendarName := false
128+
for _, e := range resp.Entries {
129+
if e.CalendarName != resp.CalendarName {
130+
showCalendarName = true
131+
}
132+
if e.AllDay {
133+
allDayEntries = append(allDayEntries, e)
134+
} else {
135+
normalEntries = append(normalEntries, e)
136+
}
137+
}
101138

102-
for idx, item := range resp.Entries {
103-
outStr += fmt.Sprintf("%d) ", idx)
139+
idx := 1
140+
// Show all-day first
141+
for _, item := range allDayEntries {
142+
outStr += renderEntry(item, idx, now, showCalendarName, strikeThroughStyle, importantStyle,
143+
freeStyle, tentativeStyle, outOfOfficeStyle, defaultStyle, contextStyle)
144+
idx++
145+
}
104146

105-
if item.Important {
106-
outStr += "!"
107-
}
147+
// Then timed events
148+
for _, item := range normalEntries {
149+
outStr += renderEntry(item, idx, now, showCalendarName, strikeThroughStyle, importantStyle,
150+
freeStyle, tentativeStyle, outOfOfficeStyle, defaultStyle, contextStyle)
151+
idx++
152+
}
108153

109-
outStr += fmt.Sprintf("%s: [%s to %s] - %s", item.Title, time.Unix(item.Start, 0).Format(time.RFC822), time.Unix(item.End, 0).Format(time.RFC822), item.Busy.String())
154+
return outStr
155+
}
110156

111-
if item.AllDay {
112-
outStr += " (all day)"
113-
}
157+
func renderEntry(
158+
item *pb.CalendarEntry,
159+
idx int,
160+
now time.Time,
161+
showCalendarName bool,
162+
strikeThroughStyle, importantStyle, freeStyle,
163+
tentativeStyle, outOfOfficeStyle, defaultStyle,
164+
contextStyle lipgloss.Style,
165+
) string {
166+
start := time.Unix(item.Start, 0)
167+
end := time.Unix(item.End, 0)
168+
169+
// Base line (without styling yet)
170+
var line string
171+
172+
// 1. Add Index
173+
line = fmt.Sprintf("%2d) ", idx)
174+
175+
// 2. Add status (only for tentative, OOO, or working elsewhere)
176+
switch item.Busy {
177+
case pb.BusyState_Tentative:
178+
fallthrough
179+
case pb.BusyState_OutOfOffice:
180+
fallthrough
181+
case pb.BusyState_WorkingElsewhere:
182+
line += fmt.Sprintf("[%s]", item.Busy.String())
183+
}
114184

115-
if len(item.Message) > 0 {
116-
outStr += fmt.Sprintf(": %s", item.Message)
117-
}
185+
if item.AllDay {
186+
line += fmt.Sprintf("%s (all day)", item.Title)
187+
} else {
188+
line += fmt.Sprintf("%s: <%s - %s>", item.Title, start.Format(time.Kitchen), end.Format(time.Kitchen))
189+
}
118190

119-
outStr += "\n"
191+
if len(item.Message) > 0 {
192+
line += fmt.Sprintf(" - %s", item.Message)
120193
}
121194

122-
return outStr
195+
// Past event? Strike through
196+
if end.Before(now) {
197+
return strikeThroughStyle.Render(line) + strikeThroughStyle.Italic(true).Render(fmt.Sprintf(" (%s)", item.CalendarName)) + "\n"
198+
}
199+
200+
// Apply styles based on attributes
201+
switch {
202+
case item.Important:
203+
line = importantStyle.Render(line)
204+
case item.Busy == pb.BusyState_Free:
205+
line = freeStyle.Render(line)
206+
case item.Busy == pb.BusyState_Tentative:
207+
line = tentativeStyle.Render(line)
208+
case item.Busy == pb.BusyState_OutOfOffice || item.Busy == pb.BusyState_WorkingElsewhere:
209+
line = outOfOfficeStyle.Render(line)
210+
default:
211+
line = defaultStyle.Render(line)
212+
}
213+
214+
if showCalendarName {
215+
line += contextStyle.Render(fmt.Sprintf(" (%s)", item.CalendarName))
216+
}
217+
218+
return line + "\n"
123219
}
124220

125221
func init() {

src/go.mod

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,17 @@ require (
2626
require (
2727
github.com/ChannelMeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 // indirect
2828
github.com/aws/smithy-go v1.22.5 // indirect
29+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
2930
github.com/beorn7/perks v1.0.1 // indirect
3031
github.com/bytedance/sonic v1.14.0 // indirect
3132
github.com/bytedance/sonic/loader v0.3.0 // indirect
3233
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
3334
github.com/cespare/xxhash/v2 v2.3.0 // indirect
35+
github.com/charmbracelet/colorprofile v0.3.2 // indirect
36+
github.com/charmbracelet/lipgloss v1.1.0 // indirect
37+
github.com/charmbracelet/x/ansi v0.10.1 // indirect
38+
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
39+
github.com/charmbracelet/x/term v0.2.1 // indirect
3440
github.com/cloudwego/base64x v0.1.6 // indirect
3541
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
3642
github.com/gin-contrib/sse v1.1.0 // indirect
@@ -47,15 +53,19 @@ require (
4753
github.com/json-iterator/go v1.1.12 // indirect
4854
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
4955
github.com/leodido/go-urn v1.4.0 // indirect
56+
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
5057
github.com/mattn/go-isatty v0.0.20 // indirect
58+
github.com/mattn/go-runewidth v0.0.16 // indirect
5159
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
5260
github.com/modern-go/reflect2 v1.0.2 // indirect
61+
github.com/muesli/termenv v0.16.0 // indirect
5362
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
5463
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
5564
github.com/prometheus/client_golang v1.23.0 // indirect
5665
github.com/prometheus/client_model v0.6.2 // indirect
5766
github.com/prometheus/common v0.65.0 // indirect
5867
github.com/prometheus/procfs v0.17.0 // indirect
68+
github.com/rivo/uniseg v0.4.7 // indirect
5969
github.com/sagikazarmark/locafero v0.10.0 // indirect
6070
github.com/sirupsen/logrus v1.9.3 // indirect
6171
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
@@ -65,6 +75,7 @@ require (
6575
github.com/subosito/gotenv v1.6.0 // indirect
6676
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
6777
github.com/ugorji/go/codec v1.3.0 // indirect
78+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
6879
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
6980
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.13.0 // indirect
7081
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0 // indirect
@@ -80,7 +91,7 @@ require (
8091
golang.org/x/arch v0.20.0 // indirect
8192
golang.org/x/crypto v0.41.0 // indirect
8293
golang.org/x/net v0.43.0 // indirect
83-
golang.org/x/sys v0.35.0 // indirect
94+
golang.org/x/sys v0.36.0 // indirect
8495
golang.org/x/text v0.28.0 // indirect
8596
google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect
8697
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect

src/go.sum

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/apognu/gocal v0.9.1 h1:e3vlb+YV5wXvqBxYsC6GvkuUAEnRipkvoA1P79gwspM=
44
github.com/apognu/gocal v0.9.1/go.mod h1:5tNvJsQGJHwS3KqWxHAFZzavC4k42jrJ3ouVmOzS/AM=
55
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
66
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
7+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
8+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
79
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
810
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
911
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
@@ -16,6 +18,16 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
1618
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
1719
github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 h1:o64h9XF42kVEUuhuer2ehqrlX8rZmvQSU0+Vpj1rF6Q=
1820
github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:Rp8e0DCtEKwXFOC6JPJQVTz8tuGoGvw6Xfexggh/ed0=
21+
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
22+
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
23+
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
24+
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
25+
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
26+
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
27+
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
28+
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
29+
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
30+
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
1931
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
2032
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
2133
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
@@ -76,15 +88,21 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
7688
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
7789
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
7890
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
91+
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
92+
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
7993
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
8094
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
95+
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
96+
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
8197
github.com/mcuadros/go-gin-prometheus v0.1.0 h1:JNoWKvw/u9tyRJ8BL9ZJvfiXU8IHUw8gCvcf/5L8tnI=
8298
github.com/mcuadros/go-gin-prometheus v0.1.0/go.mod h1:ezECAsiHtCRIa+6Ii8THg7G7RJvpO4S19d499UkEE3s=
8399
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
84100
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
85101
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
86102
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
87103
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
104+
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
105+
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
88106
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
89107
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
90108
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
@@ -99,6 +117,9 @@ github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2
99117
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
100118
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
101119
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
120+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
121+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
122+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
102123
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
103124
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
104125
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -141,6 +162,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
141162
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
142163
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
143164
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
165+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
166+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
144167
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
145168
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
146169
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.62.0 h1:fZNpsQuTwFFSGC96aJexNOBrCD7PjD9Tm/HyHtXhmnk=
@@ -195,6 +218,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
195218
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
196219
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
197220
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
221+
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
222+
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
198223
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
199224
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
200225
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=

src/pkg/client/ical_client.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (e *ICalClient) FetchEvents(ctx context.Context) {
117117
events, err := e.loadEvents(ctx, name, from, url, rules)
118118
stop := time.Now()
119119
if err != nil {
120-
otelzap.L().WithError(err).Ctx(ctx).Error("Unable to load events")
120+
otelzap.L().WithError(err).Ctx(ctx).Error("Unable to load events", zap.String("calendar", name), zap.String("from", from), zap.String("url", url))
121121
}
122122

123123
eventsMux.Lock()
@@ -129,14 +129,22 @@ func (e *ICalClient) FetchEvents(ctx context.Context) {
129129
}()
130130
}
131131

132+
wg.Wait()
133+
132134
// Sort Events by start-date (makes our live easier down the line)
133135
sort.Slice(response.Entries, func(i int, j int) bool {
134-
left := time.Unix(response.Entries[i].Start, 0)
135-
right := time.Unix(response.Entries[j].Start, 0)
136-
return left.Before(right)
136+
leftStart := time.Unix(response.Entries[i].Start, 0)
137+
rightStart := time.Unix(response.Entries[j].Start, 0)
138+
leftEnd := time.Unix(response.Entries[i].End, 0)
139+
rightEnd := time.Unix(response.Entries[j].End, 0)
140+
141+
if leftStart.Equal(rightStart) {
142+
return leftEnd.Before(rightEnd)
143+
}
144+
145+
return leftStart.Before(rightStart)
137146
})
138147

139-
wg.Wait()
140148
e.cacheMux.Lock()
141149
e.cache = response
142150
e.cacheMux.Unlock()
@@ -232,7 +240,7 @@ func (e *ICalClient) SetCustomStatus(ctx context.Context, req *pb.SetCustomStatu
232240
e.CustomStatus[req.CalendarName] = req.Status
233241
}
234242

235-
func saveIcalParse(ical io.ReadCloser) (events []gocal.Event, err humane.Error) {
243+
func safeIcalParse(ical io.ReadCloser) (events []gocal.Event, err humane.Error) {
236244
// Filter to TODAY only
237245
today, _ := time.Parse(time.DateOnly, time.Now().Format(time.DateOnly))
238246
eod := today.Add(23*time.Hour + 59*time.Minute + 59*time.Second)
@@ -280,7 +288,7 @@ func (e *ICalClient) loadEvents(ctx context.Context, calName string, from string
280288
}
281289
}(ical)
282290

283-
calEvents, err := saveIcalParse(ical)
291+
calEvents, err := safeIcalParse(ical)
284292
if err != nil {
285293
return nil, humane.Wrap(err, "failed to parse iCal calendar file")
286294
}

0 commit comments

Comments
 (0)