assign-notify/calendar/calendarevent.go

112 lines
2.8 KiB
Go
Raw Normal View History

2023-03-17 18:23:40 -07:00
package calendar
import (
"strings"
"time"
ics "github.com/arran4/golang-ical"
)
// CalendarClass is a class that represents what "class" the specified event is
//
// Currently, I have only observed this value as being `PUBLIC`, but other
// values are handled as panics
type CalendarClass byte
const (
ClassPublic CalendarClass = iota
)
func ParseClass(raw string) CalendarClass {
switch raw {
case "PUBLIC":
return ClassPublic
}
panic("Unknown class: " + raw)
}
func (cc CalendarClass) String() string {
switch cc {
case ClassPublic:
return "PUBLIC"
default:
panic("Unknown class")
}
}
// CalendarEvent represents a single event in a calendar that is tied to a certain date
type CalendarEvent struct {
UID string
// A summary of the event, including the name of the event
// This value is set every time as far as I can tell
Summary string
// A fescription of the event, including more specific information. Not always
// set, so don't rely on it
Description string
// Access class? of the event
Class CalendarClass
LastModified time.Time
DateStamp time.Time
StartTime time.Time
EndTime time.Time
// Every event comes with a category. This usually contains the name of the
// class, along with some other information (Semester code, CRN, sections)
Category struct {
ClassName string
OtherData string
}
}
const calendarTimeFormat = "20060102T150405Z"
// FromVEvent parses an ICS VEvent's format and outputs a specific calendar event, or an error
func FromVEvent(external *ics.VEvent) (event CalendarEvent, err error) {
if len(external.Components) > 0 {
panic("Event has unhandled components")
}
for _, prop := range external.Properties {
if len(prop.ICalParameters) > 0 {
panic("Property has unhandled ICalParameters")
}
switch prop.IANAToken {
case "UID":
event.UID = prop.Value
case "SUMMARY":
event.Summary = prop.Value
case "DESCRIPTION":
event.Description = prop.Value
case "CLASS":
event.Class = ParseClass(prop.Value)
case "LAST-MODIFIED":
event.LastModified, err = time.Parse(calendarTimeFormat, prop.Value)
if err != nil {
return event, err
}
case "DTSTAMP":
event.DateStamp, err = time.Parse(calendarTimeFormat, prop.Value)
if err != nil {
return event, err
}
case "DTSTART":
event.StartTime, err = time.Parse(calendarTimeFormat, prop.Value)
if err != nil {
return event, err
}
case "DTEND":
event.EndTime, err = time.Parse(calendarTimeFormat, prop.Value)
if err != nil {
return event, err
}
case "CATEGORIES":
dashIndex := strings.Index(prop.Value, "-")
event.Category.ClassName = prop.Value[:dashIndex]
event.Category.OtherData = prop.Value[dashIndex:]
default:
panic("Unknown token when parsing event: " + prop.IANAToken)
}
}
return event, nil
}