75 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			75 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
package calendar
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
	"text/template"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"kumoly.io/kumoly/app/store"
 | 
						|
)
 | 
						|
 | 
						|
const ics_base = `BEGIN:VCALENDAR
 | 
						|
PRODID:-//Kumoly//Kumoly App v0.0.1//EN
 | 
						|
VERSION:2.0
 | 
						|
CALSCALE:GREGORIAN
 | 
						|
METHOD:PUBLISH
 | 
						|
X-WR-CALNAME:{{.Name}}
 | 
						|
X-WR-TIMEZONE:Asia/Taipei
 | 
						|
X-WR-CALDESC:{{.Name}}{{/*
 | 
						|
BEGIN:VTIMEZONE
 | 
						|
TZID:{{.Timezone}}
 | 
						|
X-LIC-LOCATION:{{.Timezone}}
 | 
						|
BEGIN:STANDARD
 | 
						|
TZOFFSETFROM:+0800
 | 
						|
TZOFFSETTO:+0800
 | 
						|
TZNAME:CST
 | 
						|
DTSTART:19700101T000000
 | 
						|
END:STANDARD
 | 
						|
END:VTIMEZONE*/}}{{with .Events}}{{ if gt (len .) 0 }}{{ range $event := . }}
 | 
						|
BEGIN:VEVENT
 | 
						|
DTSTART:{{$event.Start|icstime}}
 | 
						|
DTEND:{{$event.End|icstime}}
 | 
						|
DTSTAMP:{{now|icstime}}
 | 
						|
UID:{{$event.ID}}
 | 
						|
CREATED:{{$event.CreatedAt|icstime}}
 | 
						|
DESCRIPTION:{{$event.ID}}
 | 
						|
LAST-MODIFIED:{{$event.UpdatedAt|icstime}}
 | 
						|
LOCATION:{{$event.Location}}
 | 
						|
SEQUENCE:0
 | 
						|
STATUS:CONFIRMED
 | 
						|
SUMMARY:{{$event.Name}}
 | 
						|
TRANSP:TRANSPARENT
 | 
						|
END:VEVENT{{end}}{{end}}{{end}}
 | 
						|
END:VCALENDAR`
 | 
						|
 | 
						|
var tmpl *template.Template
 | 
						|
 | 
						|
func init() {
 | 
						|
	tmpl = template.Must(template.New("").Funcs(template.FuncMap{
 | 
						|
		"icstime": icstime,
 | 
						|
		"now":     func() time.Time { return time.Now() },
 | 
						|
	}).Parse(ics_base))
 | 
						|
}
 | 
						|
 | 
						|
func ICS(cal_id string, from time.Time, to time.Time) (string, error) {
 | 
						|
	cal := &Calendar{}
 | 
						|
	store.DB.Preload("Events", `"start" > ? and "end" < ?`, from, to).
 | 
						|
		First(cal, "id = ?", cal_id)
 | 
						|
	buf := &bytes.Buffer{}
 | 
						|
	if err := tmpl.Execute(buf, cal); err != nil {
 | 
						|
		return "", err
 | 
						|
	}
 | 
						|
 | 
						|
	return strings.ReplaceAll(buf.String(), "\n", "\r\n"), nil
 | 
						|
}
 | 
						|
 | 
						|
func icstime(t time.Time) string {
 | 
						|
	return t.UTC().Format("20060102T150405Z")
 | 
						|
}
 | 
						|
 | 
						|
func offsetStr(offset int) string {
 | 
						|
	return fmt.Sprintf("%+05d", offset/36)
 | 
						|
}
 |