A webmail client. Forked from https://git.sr.ht/~migadu/alps
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

140 lines
3.2 KiB

  1. package alpscaldav
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "time"
  7. "git.sr.ht/~emersion/alps"
  8. "github.com/emersion/go-webdav/caldav"
  9. )
  10. type CalendarRenderData struct {
  11. alps.BaseRenderData
  12. Time time.Time
  13. Calendar *caldav.Calendar
  14. Events []caldav.CalendarObject
  15. PrevPage, NextPage string
  16. }
  17. type EventRenderData struct {
  18. alps.BaseRenderData
  19. Calendar *caldav.Calendar
  20. Event *caldav.CalendarObject
  21. }
  22. var monthPageLayout = "2006-01"
  23. func registerRoutes(p *alps.GoPlugin, u *url.URL) {
  24. p.GET("/calendar", func(ctx *alps.Context) error {
  25. var start time.Time
  26. if s := ctx.QueryParam("month"); s != "" {
  27. var err error
  28. start, err = time.Parse(monthPageLayout, s)
  29. if err != nil {
  30. return fmt.Errorf("failed to parse month: %v", err)
  31. }
  32. } else {
  33. now := time.Now()
  34. start = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
  35. }
  36. end := start.AddDate(0, 1, 0)
  37. // TODO: multi-calendar support
  38. c, calendar, err := getCalendar(u, ctx.Session)
  39. if err != nil {
  40. return err
  41. }
  42. query := caldav.CalendarQuery{
  43. CompRequest: caldav.CalendarCompRequest{
  44. Name: "VCALENDAR",
  45. Props: []string{"VERSION"},
  46. Comps: []caldav.CalendarCompRequest{{
  47. Name: "VEVENT",
  48. Props: []string{
  49. "SUMMARY",
  50. "UID",
  51. "DTSTART",
  52. "DTEND",
  53. "DURATION",
  54. },
  55. }},
  56. },
  57. CompFilter: caldav.CompFilter{
  58. Name: "VCALENDAR",
  59. Comps: []caldav.CompFilter{{
  60. Name: "VEVENT",
  61. Start: start,
  62. End: end,
  63. }},
  64. },
  65. }
  66. events, err := c.QueryCalendar(calendar.Path, &query)
  67. if err != nil {
  68. return fmt.Errorf("failed to query calendar: %v", err)
  69. }
  70. return ctx.Render(http.StatusOK, "calendar.html", &CalendarRenderData{
  71. BaseRenderData: *alps.NewBaseRenderData(ctx),
  72. Time: start,
  73. Calendar: calendar,
  74. Events: events,
  75. PrevPage: start.AddDate(0, -1, 0).Format(monthPageLayout),
  76. NextPage: start.AddDate(0, 1, 0).Format(monthPageLayout),
  77. })
  78. })
  79. p.GET("/calendar/:uid", func(ctx *alps.Context) error {
  80. uid := ctx.Param("uid")
  81. c, calendar, err := getCalendar(u, ctx.Session)
  82. if err != nil {
  83. return err
  84. }
  85. query := caldav.CalendarQuery{
  86. CompRequest: caldav.CalendarCompRequest{
  87. Name: "VCALENDAR",
  88. Props: []string{"VERSION"},
  89. Comps: []caldav.CalendarCompRequest{{
  90. Name: "VEVENT",
  91. Props: []string{
  92. "SUMMARY",
  93. "DESCRIPTION",
  94. "UID",
  95. "DTSTART",
  96. "DTEND",
  97. "DURATION",
  98. },
  99. }},
  100. },
  101. CompFilter: caldav.CompFilter{
  102. Name: "VCALENDAR",
  103. Comps: []caldav.CompFilter{{
  104. Name: "VEVENT",
  105. Props: []caldav.PropFilter{{
  106. Name: "UID",
  107. TextMatch: &caldav.TextMatch{Text: uid},
  108. }},
  109. }},
  110. },
  111. }
  112. events, err := c.QueryCalendar(calendar.Path, &query)
  113. if err != nil {
  114. return fmt.Errorf("failed to query calendar: %v", err)
  115. }
  116. if len(events) != 1 {
  117. return fmt.Errorf("expected exactly one calendar object with UID %q, got %v", uid, len(events))
  118. }
  119. event := &events[0]
  120. return ctx.Render(http.StatusOK, "event.html", &EventRenderData{
  121. BaseRenderData: *alps.NewBaseRenderData(ctx),
  122. Calendar: calendar,
  123. Event: event,
  124. })
  125. })
  126. }