diff options
Diffstat (limited to 'icalproxy.go')
-rw-r--r-- | icalproxy.go | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/icalproxy.go b/icalproxy.go index 0a3ea36..152eed6 100644 --- a/icalproxy.go +++ b/icalproxy.go | |||
@@ -5,6 +5,7 @@ import ( | |||
5 | "log" | 5 | "log" |
6 | "net/http" | 6 | "net/http" |
7 | "net/url" | 7 | "net/url" |
8 | "strings" | ||
8 | "time" | 9 | "time" |
9 | 10 | ||
10 | "github.com/emersion/go-ical" | 11 | "github.com/emersion/go-ical" |
@@ -15,10 +16,16 @@ func main() { | |||
15 | cfg := loadConfig() | 16 | cfg := loadConfig() |
16 | printConfig(&cfg) | 17 | printConfig(&cfg) |
17 | 18 | ||
19 | amsTz, err := time.LoadLocation("Europe/Amsterdam") | ||
20 | if err != nil { | ||
21 | log.Fatalln("Failed to load time zone", err) | ||
22 | } | ||
23 | |||
18 | handler := handler{ | 24 | handler := handler{ |
19 | calURL: url.URL(cfg.CalendarURL.v), | 25 | calURL: url.URL(cfg.CalendarURL.v), |
20 | ignore: cfg.Ignore, | 26 | ignore: cfg.Ignore, |
21 | tokens: cfg.UserTokens, | 27 | tokens: cfg.UserTokens, |
28 | amsTz: amsTz, | ||
22 | } | 29 | } |
23 | 30 | ||
24 | mux := http.ServeMux{} | 31 | mux := http.ServeMux{} |
@@ -40,6 +47,7 @@ type handler struct { | |||
40 | ignore ignoreRules | 47 | ignore ignoreRules |
41 | tokens map[string]userToken | 48 | tokens map[string]userToken |
42 | calURL url.URL | 49 | calURL url.URL |
50 | amsTz *time.Location | ||
43 | } | 51 | } |
44 | 52 | ||
45 | func (h handler) makeTokenURL(token string) string { | 53 | func (h handler) makeTokenURL(token string) string { |
@@ -72,6 +80,7 @@ func (h handler) handle(w http.ResponseWriter, r *http.Request) { | |||
72 | } | 80 | } |
73 | 81 | ||
74 | filter(h.ignore, cal.Component) | 82 | filter(h.ignore, cal.Component) |
83 | skewMidnightDeadlines(h.amsTz, cal.Component) | ||
75 | 84 | ||
76 | if err = ical.NewEncoder(w).Encode(cal); err != nil { | 85 | if err = ical.NewEncoder(w).Encode(cal); err != nil { |
77 | log.Println("Error writing calendar:", err) | 86 | log.Println("Error writing calendar:", err) |
@@ -108,6 +117,51 @@ func filter(ignore ignoreRules, c *ical.Component) { | |||
108 | c.Children = c.Children[:j] | 117 | c.Children = c.Children[:j] |
109 | } | 118 | } |
110 | 119 | ||
120 | // We often see events which are scheduled for exactly 'end of day', i.e. | ||
121 | // 23:59:59, with no difference between the start/end time. Unfortunately, | ||
122 | // these are not shown properly in two open-source Android calendar apps, so we | ||
123 | // monkey-hack the event to start at 23:30 and add a note to the description :) | ||
124 | func skewMidnightDeadlines(ams *time.Location, c *ical.Component) { | ||
125 | for _, child := range c.Children { | ||
126 | if child.Name == ical.CompEvent { | ||
127 | if summary := child.Props.Get(ical.PropSummary); summary != nil && | ||
128 | strings.HasSuffix(summary.Value, " - Due") { | ||
129 | |||
130 | // Modify the start time of the event | ||
131 | startTime, stErr := c.Props.DateTime(ical.PropDateTimeStart, ams) | ||
132 | endTime, etErr := c.Props.DateTime(ical.PropDateTimeEnd, ams) | ||
133 | if stErr != nil || etErr != nil || startTime.IsZero() || | ||
134 | endTime.IsZero() || !startTime.Equal(endTime) || | ||
135 | startTime.Hour() != 23 || startTime.Minute() != 59 || | ||
136 | startTime.Second() != 59 { | ||
137 | continue | ||
138 | } | ||
139 | newStartTime := time.Date(startTime.Year(), startTime.Month(), | ||
140 | startTime.Day(), 23, 30, 0, 0, ams) | ||
141 | child.Props.SetDateTime(ical.PropDateTimeStart, newStartTime) | ||
142 | |||
143 | // Update the event description to notify about the change | ||
144 | descProp := child.Props.Get(ical.PropDescription) | ||
145 | if descProp == nil { | ||
146 | descProp = ical.NewProp(ical.PropDescription) | ||
147 | } | ||
148 | |||
149 | curText, err := descProp.Text() | ||
150 | if err != nil { | ||
151 | // forget about editing the text, at least we 'fixed' the | ||
152 | // event time :) | ||
153 | continue | ||
154 | } | ||
155 | curText = "+++ ICALPROXY: DEADLINE MOVED FROM 23:59:59 TO" + | ||
156 | "23:30:00 (Europe/Amsterdam) +++\n\n" + curText | ||
157 | descProp.SetText(curText) | ||
158 | |||
159 | child.Props.Set(descProp) | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | |||
111 | func userOK(tokens map[string]userToken, id string, token []byte) bool { | 165 | func userOK(tokens map[string]userToken, id string, token []byte) bool { |
112 | info, ok := tokens[id] | 166 | info, ok := tokens[id] |
113 | if !ok { | 167 | if !ok { |