Files
htwkalender/services/ical/service/ical/icalDescriptionGenerator.go
2024-10-19 16:36:43 +02:00

140 lines
4.7 KiB
Go

//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
//Copyright (C) 2024 HTWKalender support@htwkalender.de
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU Affero General Public License for more details.
//You should have received a copy of the GNU Affero General Public License
//along with this program. If not, see <https://www.gnu.org/licenses/>.
package ical
import (
ics "github.com/arran4/golang-ical"
"htwkalender/ical/model"
"htwkalender/ical/service/functions"
"log/slog"
"net/url"
"strings"
_ "time/tzdata"
)
const (
Thunderbird = "Thunderbird"
GoogleCalendar = "Google-Calendar-Importer"
)
// Adds a user-agent specific description and ALTREP to the calendar event.
func addUserAgentSpecificDescription(vEvent *ics.VEvent, event model.Event, userAgent string) {
description, altrep := generateDescription(event, userAgent)
if userAgentType := identifyUserAgent(userAgent); userAgentType == Thunderbird && altrep != "" {
vEvent.AddProperty(ics.ComponentPropertyDescription, description, ics.WithAlternativeRepresentation(buildDataURL(altrep)))
} else {
vEvent.AddProperty(ics.ComponentPropertyDescription, description)
}
}
// Generates a description and ALTREP (alternative representation) based on the user agent.
func generateDescription(event model.Event, userAgent string) (string, string) {
plainDescription := buildPlainTextDescription(event)
switch identifyUserAgent(userAgent) {
case Thunderbird:
htmlDescription := generateHTMLDescriptionForThunderbird(event)
altrep := "text/html," + url.PathEscape(htmlDescription)
return plainDescription, altrep
case GoogleCalendar:
plainDescription += generateRoomLinksForGoogleCalendar(event.Rooms)
}
return plainDescription, ""
}
// Builds a plain text description of the event details.
func buildPlainTextDescription(event model.Event) string {
var description strings.Builder
if !functions.OnlyWhitespace(event.Prof) {
description.WriteString("Profs: " + event.Prof + "\n")
}
if !functions.OnlyWhitespace(event.Course) {
description.WriteString("Gruppen: " + event.Course + "\n")
}
if !functions.OnlyWhitespace(event.EventType) {
description.WriteString("Typ: " + event.EventType + event.Compulsory + "\n")
}
if !functions.OnlyWhitespace(event.Notes) {
description.WriteString("Notizen: " + event.Notes + "\n")
}
return description.String()
}
// Generates an HTML description for Thunderbird users.
func generateHTMLDescriptionForThunderbird(event model.Event) string {
var htmlDescription strings.Builder
if !functions.OnlyWhitespace(event.Prof) {
htmlDescription.WriteString("Profs: " + event.Prof + "<br>")
}
if !functions.OnlyWhitespace(event.Course) {
htmlDescription.WriteString("Gruppen: " + event.Course + "<br>")
}
if !functions.OnlyWhitespace(event.EventType) {
htmlDescription.WriteString("Typ: " + event.EventType + event.Compulsory + "<br>")
}
if !functions.OnlyWhitespace(event.Rooms) {
htmlDescription.WriteString("Orte: ")
for _, room := range functions.SeperateRoomString(event.Rooms) {
roomLink := functions.MapRoom(room, true)
_, err := htmlDescription.WriteString("<a href=\"https://map.htwk-leipzig.de/room/" + roomLink + "\">" + room + "</a> ")
if err != nil {
slog.Error("Error while writing to HTML description", "error", err)
return ""
}
}
}
return htmlDescription.String()
}
// Generates room links formatted for Google Calendar.
func generateRoomLinksForGoogleCalendar(rooms string) string {
var description strings.Builder
roomList := functions.SeperateRoomString(rooms)
if !functions.OnlyWhitespace(rooms) {
description.WriteString("Orte: ")
for _, room := range roomList {
roomLink := functions.MapRoom(room, true)
description.WriteString("<a href=\"https://map.htwk-leipzig.de/room/" + roomLink + "\"> " + room + " </a> ")
}
}
return description.String()
}
// Identifies the user agent type (e.g., Thunderbird or Google Calendar).
func identifyUserAgent(userAgent string) string {
if strings.Contains(userAgent, Thunderbird) {
return Thunderbird
}
if strings.Contains(userAgent, GoogleCalendar) {
return GoogleCalendar
}
return ""
}
// Constructs a data URL for the ALTREP representation.
func buildDataURL(data string) *url.URL {
return &url.URL{Scheme: "data", Opaque: data}
}