chore(caldav): cleanup
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
cernst 2023-03-04 12:36:02 +01:00
parent f695042465
commit 30c1d698e9
4 changed files with 79 additions and 372 deletions

View File

@ -88,58 +88,6 @@ X-OUTLOOK-COLOR:` + color + `
X-FUNAMBOL-COLOR:` + color
}
// ParseEvents parses an array of caldav events and gives them back as string
func ParseEvents(config *Config, events []*Event) (caldavevents string) {
caldavevents += `BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:` + config.Name + `
PRODID:-//` + config.ProdID + `//EN` + getCaldavColor(config.Color)
for _, e := range events {
if e.UID == "" {
e.UID = makeCalDavTimeFromTimeStamp(e.Timestamp) + utils.Sha256(e.Summary)
}
formattedDescription := ""
if e.Description != "" {
re := regexp.MustCompile(`\r?\n`)
formattedDescription = re.ReplaceAllString(e.Description, "\\n")
}
caldavevents += `
BEGIN:VEVENT
UID:` + e.UID + `
SUMMARY:` + e.Summary + getCaldavColor(e.Color) + `
DESCRIPTION:` + formattedDescription + `
DTSTAMP:` + makeCalDavTimeFromTimeStamp(e.Timestamp) + `
DTSTART:` + makeCalDavTimeFromTimeStamp(e.Start) + `
DTEND:` + makeCalDavTimeFromTimeStamp(e.End)
for _, a := range e.Alarms {
if a.Description == "" {
a.Description = e.Summary
}
caldavevents += `
BEGIN:VALARM
TRIGGER:` + calcAlarmDateFromReminder(e.Start, a.Time) + `
ACTION:DISPLAY
DESCRIPTION:` + a.Description + `
END:VALARM`
}
caldavevents += `
END:VEVENT`
}
caldavevents += `
END:VCALENDAR` // Need a line break
return
}
func formatDuration(duration time.Duration) string {
seconds := duration.Seconds() - duration.Minutes()*60
minutes := duration.Minutes() - duration.Hours()*60

View File

@ -26,275 +26,6 @@ import (
"github.com/stretchr/testify/assert"
)
func TestParseEvents(t *testing.T) {
type args struct {
config *Config
events []*Event
}
tests := []struct {
name string
args args
wantCaldavevents string
}{
{
name: "Test caldavparsing without reminders",
args: args{
config: &Config{
Name: "test",
ProdID: "RandomProdID which is not random",
Color: "ffffff",
},
events: []*Event{
{
Summary: "Event #1",
Description: "Lorem Ipsum",
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543626724, 0).In(config.GetTimeZone()),
End: time.Unix(1543627824, 0).In(config.GetTimeZone()),
Color: "affffe",
},
{
Summary: "Event #2",
UID: "randommduidd",
Timestamp: time.Unix(1543726724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543726724, 0).In(config.GetTimeZone()),
End: time.Unix(1543738724, 0).In(config.GetTimeZone()),
},
{
Summary: "Event #3 with empty uid",
UID: "20181202T0600242aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83",
Timestamp: time.Unix(1543726824, 0).In(config.GetTimeZone()),
Start: time.Unix(1543726824, 0).In(config.GetTimeZone()),
End: time.Unix(1543727000, 0).In(config.GetTimeZone()),
},
},
},
wantCaldavevents: `BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:test
PRODID:-//RandomProdID which is not random//EN
X-APPLE-CALENDAR-COLOR:#ffffffFF
X-OUTLOOK-COLOR:#ffffffFF
X-FUNAMBOL-COLOR:#ffffffFF
BEGIN:VEVENT
UID:randommduid
SUMMARY:Event #1
X-APPLE-CALENDAR-COLOR:#affffeFF
X-OUTLOOK-COLOR:#affffeFF
X-FUNAMBOL-COLOR:#affffeFF
DESCRIPTION:Lorem Ipsum
DTSTAMP:20181201T011204Z
DTSTART:20181201T011204Z
DTEND:20181201T013024Z
END:VEVENT
BEGIN:VEVENT
UID:randommduidd
SUMMARY:Event #2
DESCRIPTION:
DTSTAMP:20181202T045844Z
DTSTART:20181202T045844Z
DTEND:20181202T081844Z
END:VEVENT
BEGIN:VEVENT
UID:20181202T0600242aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83
SUMMARY:Event #3 with empty uid
DESCRIPTION:
DTSTAMP:20181202T050024Z
DTSTART:20181202T050024Z
DTEND:20181202T050320Z
END:VEVENT
END:VCALENDAR`,
},
{
name: "Test caldavparsing with reminders",
args: args{
config: &Config{
Name: "test2",
ProdID: "RandomProdID which is not random",
},
events: []*Event{
{
Summary: "Event #1",
Description: "Lorem Ipsum",
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543626724, 0).In(config.GetTimeZone()),
End: time.Unix(1543627824, 0).In(config.GetTimeZone()),
Alarms: []Alarm{
{Time: time.Unix(1543626524, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626224, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626024, 0)},
},
},
{
Summary: "Event #2",
UID: "randommduidd",
Timestamp: time.Unix(1543726724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543726724, 0).In(config.GetTimeZone()),
End: time.Unix(1543738724, 0).In(config.GetTimeZone()),
Alarms: []Alarm{
{Time: time.Unix(1543626524, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626224, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626024, 0).In(config.GetTimeZone())},
},
},
{
Summary: "Event #3 with empty uid",
Timestamp: time.Unix(1543726824, 0).In(config.GetTimeZone()),
Start: time.Unix(1543726824, 0).In(config.GetTimeZone()),
End: time.Unix(1543727000, 0).In(config.GetTimeZone()),
Alarms: []Alarm{
{Time: time.Unix(1543626524, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626224, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543626024, 0).In(config.GetTimeZone())},
{Time: time.Unix(1543826824, 0).In(config.GetTimeZone())},
},
},
{
Summary: "Event #4 without any",
Timestamp: time.Unix(1543726824, 0),
Start: time.Unix(1543726824, 0),
End: time.Unix(1543727000, 0),
},
},
},
wantCaldavevents: `BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:test2
PRODID:-//RandomProdID which is not random//EN
BEGIN:VEVENT
UID:randommduid
SUMMARY:Event #1
DESCRIPTION:Lorem Ipsum
DTSTAMP:20181201T011204Z
DTSTART:20181201T011204Z
DTEND:20181201T013024Z
BEGIN:VALARM
TRIGGER:-PT3M20S
ACTION:DISPLAY
DESCRIPTION:Event #1
END:VALARM
BEGIN:VALARM
TRIGGER:-PT8M20S
ACTION:DISPLAY
DESCRIPTION:Event #1
END:VALARM
BEGIN:VALARM
TRIGGER:-PT11M40S
ACTION:DISPLAY
DESCRIPTION:Event #1
END:VALARM
END:VEVENT
BEGIN:VEVENT
UID:randommduidd
SUMMARY:Event #2
DESCRIPTION:
DTSTAMP:20181202T045844Z
DTSTART:20181202T045844Z
DTEND:20181202T081844Z
BEGIN:VALARM
TRIGGER:-PT27H50M0S
ACTION:DISPLAY
DESCRIPTION:Event #2
END:VALARM
BEGIN:VALARM
TRIGGER:-PT27H55M0S
ACTION:DISPLAY
DESCRIPTION:Event #2
END:VALARM
BEGIN:VALARM
TRIGGER:-PT27H58M20S
ACTION:DISPLAY
DESCRIPTION:Event #2
END:VALARM
END:VEVENT
BEGIN:VEVENT
UID:20181202T050024Z2aaef4a81d770c1e775e26bc5abebc87f1d3d7bffaa83
SUMMARY:Event #3 with empty uid
DESCRIPTION:
DTSTAMP:20181202T050024Z
DTSTART:20181202T050024Z
DTEND:20181202T050320Z
BEGIN:VALARM
TRIGGER:-PT27H51M40S
ACTION:DISPLAY
DESCRIPTION:Event #3 with empty uid
END:VALARM
BEGIN:VALARM
TRIGGER:-PT27H56M40S
ACTION:DISPLAY
DESCRIPTION:Event #3 with empty uid
END:VALARM
BEGIN:VALARM
TRIGGER:-PT28H0M0S
ACTION:DISPLAY
DESCRIPTION:Event #3 with empty uid
END:VALARM
BEGIN:VALARM
TRIGGER:PT27H46M40S
ACTION:DISPLAY
DESCRIPTION:Event #3 with empty uid
END:VALARM
END:VEVENT
BEGIN:VEVENT
UID:20181202T050024Zae7548ce9556df85038abe90dc674d4741a61ce74d1cf
SUMMARY:Event #4 without any
DESCRIPTION:
DTSTAMP:20181202T050024Z
DTSTART:20181202T050024Z
DTEND:20181202T050320Z
END:VEVENT
END:VCALENDAR`,
},
{
name: "Test caldavparsing with multiline description",
args: args{
config: &Config{
Name: "test",
ProdID: "RandomProdID which is not random",
},
events: []*Event{
{
Summary: "Event #1",
Description: `Lorem Ipsum
Dolor sit amet`,
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543626724, 0).In(config.GetTimeZone()),
End: time.Unix(1543627824, 0).In(config.GetTimeZone()),
},
},
},
wantCaldavevents: `BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:test
PRODID:-//RandomProdID which is not random//EN
BEGIN:VEVENT
UID:randommduid
SUMMARY:Event #1
DESCRIPTION:Lorem Ipsum\nDolor sit amet
DTSTAMP:20181201T011204Z
DTSTART:20181201T011204Z
DTEND:20181201T013024Z
END:VEVENT
END:VCALENDAR`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotCaldavevents := ParseEvents(tt.args.config, tt.args.events)
assert.Equal(t, gotCaldavevents, tt.wantCaldavevents)
})
}
}
func TestParseTodos(t *testing.T) {
type args struct {
config *Config
@ -531,15 +262,15 @@ END:VCALENDAR`,
},
todos: []*Todo{
{
Summary: "Todo #1",
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Summary: "Todo #1",
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Alarms: []Alarm{
{
Time: time.Unix(1543626724, 0).In(config.GetTimeZone()),
},
{
Time: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Time: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Description: "alarm description",
},
},

View File

@ -155,34 +155,37 @@ func parseVAlarm(vAlarm *ics.VAlarm, vTask *models.Task) {
if len(property.ICalParameters["VALUE"]) > 0 {
switch property.ICalParameters["VALUE"][0] {
case "DATE-TIME":
// TRIGGER;VALUE=DATE-TIME:20181201T011210Z
// Example: TRIGGER;VALUE=DATE-TIME:20181201T011210Z
vTask.Reminders = append(vTask.Reminders, caldavTimeToTimestamp(property.Value))
}
} else if len(property.ICalParameters["RELATED"]) > 0 {
duration := parseDuration(property.Value)
switch property.ICalParameters["RELATED"][0] {
case "START":
// TRIGGER;RELATED=START:-P2D
if !vTask.StartDate.IsZero() {
vTask.Reminders = append(vTask.Reminders, vTask.StartDate.Add(duration))
}
case "END":
// TRIGGER;RELATED=END:-P2D
if !vTask.EndDate.IsZero() {
vTask.Reminders = append(vTask.Reminders, vTask.EndDate.Add(duration))
} else if !vTask.DueDate.IsZero() {
vTask.Reminders = append(vTask.Reminders, vTask.DueDate.Add(duration))
}
}
} else {
duration := parseDuration(property.Value)
if duration != 0 {
// TRIGGER:-PT60M
if !vTask.DueDate.IsZero() {
vTask.Reminders = append(vTask.Reminders, vTask.DueDate.Add(duration))
}
}
// At the moment I don't think this should be merged. Relative triggers cannot
// be stored properly. This would result in missing or duplicate alarms on the
// client.
//
// } else if len(property.ICalParameters["RELATED"]) > 0 {
// duration := parseDuration(property.Value)
// switch property.ICalParameters["RELATED"][0] {
// case "START":
// // Example: TRIGGER;RELATED=START:-P2D
// if !vTask.StartDate.IsZero() {
// vTask.Reminders = append(vTask.Reminders, vTask.StartDate.Add(duration))
// }
// case "END":
// // Example: TRIGGER;RELATED=END:-P2D
// if !vTask.EndDate.IsZero() {
// vTask.Reminders = append(vTask.Reminders, vTask.EndDate.Add(duration))
// } else if !vTask.DueDate.IsZero() {
// vTask.Reminders = append(vTask.Reminders, vTask.DueDate.Add(duration))
// }
// }
// } else {
// duration := parseDuration(property.Value)
// if duration != 0 {
// // Example: TRIGGER:-PT60M
// if !vTask.DueDate.IsZero() {
// vTask.Reminders = append(vTask.Reminders, vTask.DueDate.Add(duration))
// }
// }
}
}
}
@ -212,7 +215,7 @@ func caldavTimeToTimestamp(tstring string) time.Time {
return t
}
// From https://stackoverflow.com/a/57617885; with support for negative durations added
// TODO: move to utils/time.go and share with ticktick.go
var durationRegex = regexp.MustCompile(`([-+])?P([\d\.]+Y)?([\d\.]+M)?([\d\.]+D)?T?([\d\.]+H)?([\d\.]+M)?([\d\.]+?S)?`)
// ParseDuration converts a ISO8601 duration into a time.Duration

View File

@ -119,7 +119,7 @@ END:VCALENDAR`,
},
},
{
name: "With alarm",
name: "With alarm (time trigger)",
args: args{content: `BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
@ -131,24 +131,10 @@ UID:randomuid
DTSTAMP:20181201T011204
SUMMARY:Todo #1
DESCRIPTION:Lorem Ipsum
DTSTART:20230228T170000Z
DUE:20230304T150000Z
BEGIN:VALARM
TRIGGER;VALUE=DATE-TIME:20181201T011210Z
ACTION:DISPLAY
END:VALARM
BEGIN:VALARM
TRIGGER:-PT60M
ACTION:DISPLAY
END:VALARM
BEGIN:VALARM
TRIGGER;RELATED=START:-P1D
ACTION:DISPLAY
END:VALARM
BEGIN:VALARM
TRIGGER;RELATED=END:-PT30M
ACTION:DISPLAY
END:VALARM
END:VTODO
END:VCALENDAR`,
},
@ -156,17 +142,56 @@ END:VCALENDAR`,
Title: "Todo #1",
UID: "randomuid",
Description: "Lorem Ipsum",
StartDate: time.Date(2023, 2, 28, 17, 0, 0, 0, config.GetTimeZone()),
DueDate: time.Date(2023, 3, 4, 15, 0, 0, 0, config.GetTimeZone()),
Reminders: []time.Time{
time.Date(2018, 12, 1, 1, 12, 10, 0, config.GetTimeZone()),
time.Date(2023, 3, 4, 14, 0, 0, 0, config.GetTimeZone()),
time.Date(2023, 2, 27, 17, 00, 0, 0, config.GetTimeZone()),
time.Date(2023, 3, 4, 14, 30, 0, 0, config.GetTimeZone()),
},
Updated: time.Unix(1543626724, 0).In(config.GetTimeZone()),
},
},
// {
// name: "With alarm (relative trigger)",
// args: args{content: `BEGIN:VCALENDAR
// VERSION:2.0
// METHOD:PUBLISH
// X-PUBLISHED-TTL:PT4H
// X-WR-CALNAME:test
// PRODID:-//RandomProdID which is not random//EN
// BEGIN:VTODO
// UID:randomuid
// DTSTAMP:20181201T011204
// SUMMARY:Todo #1
// DESCRIPTION:Lorem Ipsum
// DTSTART:20230228T170000Z
// DUE:20230304T150000Z
// BEGIN:VALARM
// TRIGGER:-PT60M
// ACTION:DISPLAY
// END:VALARM
// BEGIN:VALARM
// TRIGGER;RELATED=START:-P1D
// ACTION:DISPLAY
// END:VALARM
// BEGIN:VALARM
// TRIGGER;RELATED=END:-PT30M
// ACTION:DISPLAY
// END:VALARM
// END:VTODO
// END:VCALENDAR`,
// },
// wantVTask: &models.Task{
// Title: "Todo #1",
// UID: "randomuid",
// Description: "Lorem Ipsum",
// StartDate: time.Date(2023, 2, 28, 17, 0, 0, 0, config.GetTimeZone()),
// DueDate: time.Date(2023, 3, 4, 15, 0, 0, 0, config.GetTimeZone()),
// Reminders: []time.Time{
// time.Date(2023, 3, 4, 14, 0, 0, 0, config.GetTimeZone()),
// time.Date(2023, 2, 27, 17, 00, 0, 0, config.GetTimeZone()),
// time.Date(2023, 3, 4, 14, 30, 0, 0, config.GetTimeZone()),
// },
// Updated: time.Unix(1543626724, 0).In(config.GetTimeZone()),
// },
// },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {