diff --git a/internal/calendar/calendar.go b/internal/calendar/calendar.go index 6771e3f..017fecb 100644 --- a/internal/calendar/calendar.go +++ b/internal/calendar/calendar.go @@ -80,7 +80,18 @@ func (cal Calendar) GetEventsOn(date time.Time) ([]ical.Event, error) { start2, _ := events[j].DateTimeStart(cal.tz) return start1.Before(start2) }) - return events, nil + + // check for doubles via uid + uids := make(map[string]struct{}) + dedupedEvents := make([]ical.Event, 0) + for _, e := range events { + uid := e.Props.Get(ical.PropUID).Value + if _, ok := uids[uid]; !ok { + dedupedEvents = append(dedupedEvents, e) + uids[uid] = struct{}{} + } + } + return dedupedEvents, nil } func GetDateWithoutTime(date time.Time) time.Time { diff --git a/internal/calendar/calendar_test.go b/internal/calendar/calendar_test.go index a2bd3b1..7a73cdd 100644 --- a/internal/calendar/calendar_test.go +++ b/internal/calendar/calendar_test.go @@ -14,15 +14,22 @@ const ( xHainDump_1 = "testData.txt" ) -func NewWantedCalendarEventWithUIDSet(uid string) ical.Event { +func NewWantedCalendarEventWithUIDAndSummary(uid string, summary string) ical.Event { return ical.Event{ Component: &ical.Component{ Name: ical.CompEvent, Props: ical.Props{ + ical.PropSummary: []ical.Prop{ + { + Name: ical.PropSummary, + Params: make(ical.Params), + Value: summary, + }, + }, ical.PropUID: []ical.Prop{ { Name: ical.PropUID, - Params: make(ical.Params, 0), + Params: make(ical.Params), Value: uid, }, }, @@ -51,45 +58,67 @@ func TestCalendar_GetEventsOn(t *testing.T) { name: "LED Workshop recurring", testDataFile: getCalendarDataFromFile(xHainDump_1), args: args{ - date: time.Date(2023, 02, 23, 0, 0, 0, 0, time.Local), + date: time.Date(2023, 2, 23, 0, 0, 0, 0, time.Local), + }, + wantErr: false, + want: []ical.Event{ + NewWantedCalendarEventWithUIDAndSummary("dae1e4eb-7213-4620-bc9f-1bdb8a023af9", "Workshop - Learn PCB design with KiCad"), + }, + }, + { + name: "LED Workshop recurring exception", + testDataFile: getCalendarDataFromFile(xHainDump_1), + args: args{ + date: time.Date(2023, 3, 2, 0, 0, 0, 0, time.Local), + }, + wantErr: false, + want: []ical.Event{ + NewWantedCalendarEventWithUIDAndSummary("66adcfc4-6827-45a2-a5b4-655923d5dd62", "How to use the latest AIs in your daily workflow - for... everything?"), + }, + }, + { + name: "Gespräch unter Bäumen instances", + testDataFile: getCalendarDataFromFile(xHainDump_1), + args: args{ + date: time.Date(2023, 3, 21, 0, 0, 0, 0, time.Local), }, wantErr: false, want: []ical.Event{ - NewWantedCalendarEventWithUIDSet("dae1e4eb-7213-4620-bc9f-1bdb8a023af9"), + NewWantedCalendarEventWithUIDAndSummary("5fb7f276-54d6-4c30-a993-92cfe962e41b", "Gespräch unter Bäumen (mit Elisa Filevich)"), }, }, { name: "Drones' night", testDataFile: getCalendarDataFromFile(xHainDump_1), args: args{ - date: time.Date(2023, 02, 24, 0, 0, 0, 0, time.Local), + date: time.Date(2023, 2, 24, 0, 0, 0, 0, time.Local), }, wantErr: false, want: []ical.Event{ - NewWantedCalendarEventWithUIDSet("1ec26b84-60e1-437d-a455-db6404dff879"), + NewWantedCalendarEventWithUIDAndSummary("1ec26b84-60e1-437d-a455-db6404dff879", "Drones' night"), }, }, { name: "offener Montag", testDataFile: getCalendarDataFromFile(xHainDump_1), args: args{ - date: time.Date(2023, 02, 27, 0, 0, 0, 0, time.Local), + date: time.Date(2023, 2, 27, 0, 0, 0, 0, time.Local), }, wantErr: false, want: []ical.Event{ - NewWantedCalendarEventWithUIDSet("c9158eec-083a-4798-9860-99c4a83cce0f"), + NewWantedCalendarEventWithUIDAndSummary("c9158eec-083a-4798-9860-99c4a83cce0f", "offener Montag"), }, }, { name: "Multiple events: XMPP/Wednesday Meeting", testDataFile: getCalendarDataFromFile(xHainDump_1), args: args{ - date: time.Date(2023, 02, 8, 0, 0, 0, 0, time.Local), + date: time.Date(2023, 2, 8, 0, 0, 0, 0, time.Local), }, wantErr: false, want: []ical.Event{ - NewWantedCalendarEventWithUIDSet("3591c731-0e27-4902-9ae0-8748d46841f3"), - NewWantedCalendarEventWithUIDSet("1695d4c9-aa37-4b52-bda9-2132ac92e3a2"), + NewWantedCalendarEventWithUIDAndSummary("3591c731-0e27-4902-9ae0-8748d46841f3", "XMPP-Meetup"), + NewWantedCalendarEventWithUIDAndSummary("1695d4c9-aa37-4b52-bda9-2132ac92e3a2", "xHain Wednesday meeting"), }, }, { @@ -100,8 +129,8 @@ func TestCalendar_GetEventsOn(t *testing.T) { }, wantErr: false, want: []ical.Event{ - NewWantedCalendarEventWithUIDSet("290b69b7-aaaf-47d4-88d1-d42366e36163"), - NewWantedCalendarEventWithUIDSet("77b564a3-4e8c-4e3b-b9db-990e622d04ff"), + NewWantedCalendarEventWithUIDAndSummary("290b69b7-aaaf-47d4-88d1-d42366e36163", "Kindernachmittag"), + NewWantedCalendarEventWithUIDAndSummary("77b564a3-4e8c-4e3b-b9db-990e622d04ff", "xHain @ Camp23 Brainstorming"), }, }, } @@ -117,7 +146,7 @@ func TestCalendar_GetEventsOn(t *testing.T) { cal := Calendar{ url: "file", tz: time.Local, - Logger: log.New(os.Stdout, "[TEST]", log.Ldate|log.Ltime|log.Lmsgprefix|log.Lshortfile), + Logger: log.New(os.Stdout, "[TEST] ", log.Ldate|log.Ltime|log.Lmsgprefix|log.Lshortfile), Calendar: calendar, } got, err := cal.GetEventsOn(tt.args.date) diff --git a/internal/calendar/testData.txt b/internal/calendar/testData.txt index a9e8be1..dbc0e9d 100644 --- a/internal/calendar/testData.txt +++ b/internal/calendar/testData.txt @@ -1016,6 +1016,21 @@ STATUS:CONFIRMED SUMMARY:Online: Jugendhackt Internationaler Frauentag / Community Talk END:VEVENT BEGIN:VEVENT +CREATED:20230224T152336Z +DTSTAMP:20230227T115419Z +LAST-MODIFIED:20230227T115419Z +SEQUENCE:3 +UID:4cf5a2ae-420f-4cba-93d2-434faf0de11a +DTSTART;TZID=Europe/Berlin:20230311T110000 +DTEND;TZID=Europe/Berlin:20230311T190000 +STATUS:CONFIRMED +SUMMARY:infrastructure and dinner +DESCRIPTION:Let's meet once a month to work on infrastructure things\, may + it be sorting screws\, cleaning the space or building cool things. It's a + nice way to also get to know each other and have a nice lunch/dinner toget + her afterwards. +END:VEVENT +BEGIN:VEVENT CREATED:20210920T095652Z DTSTAMP:20211128T172320Z LAST-MODIFIED:20211128T172320Z @@ -1263,6 +1278,20 @@ RRULE:FREQ=DAILY;INTERVAL=14;UNTIL=20220604T115959Z EXDATE;TZID=Europe/Berlin:20220521T140000 END:VEVENT BEGIN:VEVENT +CREATED:20230305T144015Z +DTSTAMP:20230305T144107Z +LAST-MODIFIED:20230305T144107Z +SEQUENCE:2 +UID:7edc3d9d-3445-4e17-b8d8-1abe1ede9635 +DTSTART;TZID=Europe/Berlin:20230309T180000 +DTEND;TZID=Europe/Berlin:20230309T200000 +STATUS:CONFIRMED +SUMMARY:Fusion360/CNC work shop +DESCRIPTION:We will probably focus on how to import and scale 2d file types + (dxf and jpg) and some tips to work around the issues with some DXF file + s. +END:VEVENT +BEGIN:VEVENT CREATED:20220210T155604Z DTSTAMP:20220210T155619Z LAST-MODIFIED:20220210T155619Z @@ -1330,6 +1359,17 @@ DTEND;TZID=Europe/Berlin:20221007T230000 STATUS:CONFIRMED END:VEVENT BEGIN:VEVENT +CREATED:20230311T224036Z +DTSTAMP:20230311T224049Z +LAST-MODIFIED:20230311T224049Z +SEQUENCE:2 +UID:2448da04-5d7f-4518-870f-f786e6c93c7a +DTSTART;TZID=Europe/Berlin:20230415T110000 +DTEND;TZID=Europe/Berlin:20230415T190000 +STATUS:CONFIRMED +SUMMARY:Infrastructure and Dinner +END:VEVENT +BEGIN:VEVENT CREATED:20221019T114653Z DTSTAMP:20221019T114902Z LAST-MODIFIED:20221019T114902Z @@ -1364,6 +1404,47 @@ DTEND;TZID=Europe/Berlin:20221002T170000 STATUS:CONFIRMED END:VEVENT BEGIN:VEVENT +CREATED:20230209T105507Z +DTSTAMP:20230314T151728Z +LAST-MODIFIED:20230314T151728Z +SEQUENCE:2 +UID:892e3abe-3eca-40a6-9b87-4be7da3b10bd +DTSTART;TZID=Europe/Berlin:20230309T183000 +DTEND;TZID=Europe/Berlin:20230309T203000 +STATUS:CONFIRMED +SUMMARY:Beginners workshop - How to plan & build your own LED project +LOCATION:xHain +DESCRIPTION:Learn how to plan and build a simple LED project\, while learni + ng the basics of LEDs\, soldering and how to build an awesome looking LED + project. No experience needed.\n\nMore details and other LED related event + s: https://events.glowingkitty.com +RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TH +RELATED-TO;RELTYPE=SIBLING:a50acfcb-b86f-4aa4-8613-a1a7ccc23892 +EXDATE;TZID=Europe/Berlin:20230309T183000 +EXDATE;TZID=Europe/Berlin:20230406T183000 +END:VEVENT +BEGIN:VEVENT +CREATED:20230303T102215Z +DTSTAMP:20230303T102215Z +LAST-MODIFIED:20230303T102215Z +SEQUENCE:1 +UID:892e3abe-3eca-40a6-9b87-4be7da3b10bd +DTSTART;TZID=Europe/Berlin:20230323T183000 +DTEND;TZID=Europe/Berlin:20230323T203000 +STATUS:CONFIRMED +SUMMARY:Workshop - Learn PCB design with KiCad +LOCATION:xHain +DESCRIPTION:A beginner friendly introduction to learn PCB design with KiCad + . It's not as complicated as you think!:) Basic electronics knowledge reco + mmended. \n\nWhat you should bring with you:\nPlease being your laptop. Wi + th Windows\, macOS\, or Linux.\nAnd prepare for the workshop by downloadin + g this repo and follow the "Workshop preparation" part of the README:\nhtt + p://pcb-workshop.glowingkitty.com/\n\nMore details & other LED related eve + nts: https://events.glowingkitty.com +RELATED-TO;RELTYPE=SIBLING:a50acfcb-b86f-4aa4-8613-a1a7ccc23892 +RECURRENCE-ID;TZID=Europe/Berlin:20230323T183000 +END:VEVENT +BEGIN:VEVENT CREATED:20220210T154859Z DTSTAMP:20220510T085054Z LAST-MODIFIED:20220510T085054Z @@ -1477,6 +1558,20 @@ STATUS:CONFIRMED SUMMARY:CoderDojo: Lötworkshop END:VEVENT BEGIN:VEVENT +CREATED:20230317T095716Z +DTSTAMP:20230317T095955Z +LAST-MODIFIED:20230317T095955Z +SEQUENCE:2 +UID:5baeeb24-e843-4143-bab8-13ceb8ad0c96 +DTSTART;TZID=Europe/Berlin:20230326T150000 +DTEND;TZID=Europe/Berlin:20230326T180000 +STATUS:CONFIRMED +SUMMARY:Hackaday Tour +DESCRIPTION:On March 25th Hackaday Berlin celebrates makers and hackers at + MotionLab. After a Brunch and badge hacking session on Sunday everyone is + invited by Dave to a tour to see our hackspace +END:VEVENT +BEGIN:VEVENT CREATED:20230103T120550Z DTSTAMP:20230109T071116Z LAST-MODIFIED:20230109T071116Z @@ -1495,6 +1590,17 @@ DESCRIPTION:Am Sonntag dem 22.1. öffnet der xHain extra für Kinder. Du ka . Diese sind hier zu finden https://www.berlin.de/sen/bjf/corona/schule. END:VEVENT BEGIN:VEVENT +CREATED:20230317T223320Z +DTSTAMP:20230317T223327Z +LAST-MODIFIED:20230317T223327Z +SEQUENCE:2 +UID:f2f00a51-ee5c-476c-989f-f1cb227f45fb +DTSTART;TZID=Europe/Berlin:20230422T110000 +DTEND;TZID=Europe/Berlin:20230422T140000 +STATUS:CONFIRMED +SUMMARY:coderdojo soldering workshop +END:VEVENT +BEGIN:VEVENT CREATED:20221118T143132Z DTSTAMP:20221118T143414Z LAST-MODIFIED:20221118T143414Z @@ -1636,6 +1742,14 @@ RELATED-TO;RELTYPE=SIBLING:bcc1ce94-d111-4cd6-9083-6a1901755f71 RECURRENCE-ID;TZID=Europe/Berlin:20230302T183000 END:VEVENT BEGIN:VEVENT +DTSTAMP:20230309T091817Z +UID:45893fe8-b6f7-4841-8fb3-78a6a1bbf8ff +SUMMARY:xHain binge watching night +DTSTART;TZID=Europe/Berlin:20230319T180000 +DTEND;TZID=Europe/Berlin:20230319T235900 +STATUS:CONFIRMED +END:VEVENT +BEGIN:VEVENT CREATED:20221119T180415Z DTSTAMP:20221119T182255Z LAST-MODIFIED:20221119T182255Z @@ -1820,6 +1934,17 @@ DESCRIPTION:Learn how to 3D model your LED project in Fusion360. For better RECURRENCE-ID;TZID=Europe/Berlin:20230112T183000 END:VEVENT BEGIN:VEVENT +CREATED:20230320T121638Z +DTSTAMP:20230320T121725Z +LAST-MODIFIED:20230320T121725Z +SEQUENCE:2 +UID:c0dd944a-5319-40eb-9da3-e1428874c0f8 +DTSTART;TZID=Europe/Berlin:20230325T133700 +DTEND;TZID=Europe/Berlin:20230325T235900 +STATUS:CONFIRMED +SUMMARY:open hackspace day +END:VEVENT +BEGIN:VEVENT DTSTAMP:20230121T083814Z UID:d2186fb2-a58f-420e-8d11-84b0efd55ee9 SUMMARY:Critical making workshop @@ -1841,7 +1966,7 @@ SUMMARY:JungHacker:innen Tag DESCRIPTION:https://coderdojo.red/posts/junghackerinnentag// END:VEVENT BEGIN:VEVENT -DTSTAMP:20230131T204914Z +DTSTAMP:20230308T105105Z UID:3591c731-0e27-4902-9ae0-8748d46841f3 SUMMARY:XMPP-Meetup DTSTART;TZID=Europe/Berlin:20230208T180000 @@ -1850,26 +1975,9 @@ RRULE:FREQ=MONTHLY;BYDAY=2WE STATUS:CONFIRMED RELATED-TO;RELTYPE=SIBLING:95b1aba9-c5fe-417d-8ddc-f425ff09a119 CREATED:20230131T204914Z -LAST-MODIFIED:20230131T204914Z -SEQUENCE:0 -END:VEVENT -BEGIN:VEVENT -CREATED:20230209T105507Z -DTSTAMP:20230209T105507Z -LAST-MODIFIED:20230209T105507Z -SEQUENCE:0 -UID:892e3abe-3eca-40a6-9b87-4be7da3b10bd -DTSTART;TZID=Europe/Berlin:20230309T183000 -DTEND;TZID=Europe/Berlin:20230309T203000 -STATUS:CONFIRMED -SUMMARY:Beginners workshop - How to plan & build your own LED project -LOCATION:xHain -DESCRIPTION:Learn how to plan and build a simple LED project\, while learni - ng the basics of LEDs\, soldering and how to build an awesome looking LED - project. No experience needed.\n\nMore details and other LED related event - s: https://events.glowingkitty.com -RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TH -RELATED-TO;RELTYPE=SIBLING:a50acfcb-b86f-4aa4-8613-a1a7ccc23892 +LAST-MODIFIED:20230308T105105Z +SEQUENCE:1 +EXDATE;TZID=Europe/Berlin:20230308T180000 END:VEVENT BEGIN:VEVENT CREATED:20230216T092448Z @@ -2240,15 +2348,4 @@ DTSTART;TZID=Europe/Berlin:20221008T110000 DTEND;TZID=Europe/Berlin:20221008T140000 STATUS:CONFIRMED END:VEVENT -BEGIN:VEVENT -CREATED:20230224T152336Z -DTSTAMP:20230224T152402Z -LAST-MODIFIED:20230224T152402Z -SEQUENCE:2 -UID:4cf5a2ae-420f-4cba-93d2-434faf0de11a -DTSTART;TZID=Europe/Berlin:20230311T110000 -DTEND;TZID=Europe/Berlin:20230311T190000 -STATUS:CONFIRMED -SUMMARY:infrastructure and dinner -END:VEVENT END:VCALENDAR