Add Calendar Events widget, integrate ICS calendar parsing, and refine related UI components
This commit is contained in:
89
apis/calendar/main.go
Normal file
89
apis/calendar/main.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"ArinDash/config"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/arran4/golang-ical"
|
||||
)
|
||||
|
||||
type configFile struct {
|
||||
Calendar calendarConfig
|
||||
}
|
||||
|
||||
type calendarConfig struct {
|
||||
ICS []ICS
|
||||
Icon string
|
||||
}
|
||||
|
||||
type ICS struct {
|
||||
Icon string
|
||||
URL string
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
UID string
|
||||
Summary string
|
||||
Description string
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Location string
|
||||
Icon string
|
||||
}
|
||||
|
||||
func FetchEvents() []Event {
|
||||
cfg := &configFile{}
|
||||
config.LoadConfig(cfg)
|
||||
|
||||
events := make([]Event, 0)
|
||||
for _, ic := range cfg.Calendar.ICS {
|
||||
cal, err := ics.ParseCalendarFromUrl(ic.URL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, event := range cal.Events() {
|
||||
startAt, err := event.GetStartAt()
|
||||
if err != nil {
|
||||
startAt = time.Now()
|
||||
}
|
||||
endAt, err := event.GetEndAt()
|
||||
if err != nil {
|
||||
endAt = startAt
|
||||
}
|
||||
events = append(events, Event{
|
||||
UID: getValue(event, ics.ComponentPropertyUniqueId),
|
||||
Icon: ic.Icon,
|
||||
Summary: getValue(event, ics.ComponentPropertySummary),
|
||||
Description: getValue(event, ics.ComponentPropertyDescription),
|
||||
Start: startAt,
|
||||
End: endAt,
|
||||
Location: getValue(event, ics.ComponentPropertyLocation),
|
||||
})
|
||||
}
|
||||
}
|
||||
result := filter(events, func(i Event) bool {
|
||||
return i.End.After(time.Now())
|
||||
})
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].Start.Before(result[j].Start)
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
func getValue(event *ics.VEvent, property ics.ComponentProperty) string {
|
||||
ianaProperty := event.GetProperty(property)
|
||||
if ianaProperty == nil {
|
||||
return ""
|
||||
}
|
||||
return ianaProperty.Value
|
||||
}
|
||||
|
||||
func filter[T any](ss []T, test func(T) bool) (ret []T) {
|
||||
for _, s := range ss {
|
||||
if test(s) {
|
||||
ret = append(ret, s)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -84,6 +84,7 @@ func knownDevices() map[string]Device {
|
||||
}
|
||||
|
||||
func arpDevices() map[string]Device {
|
||||
exec.Command("ip", "n", "show")
|
||||
arp := exec.Command("arp", "-a")
|
||||
var out bytes.Buffer
|
||||
arp.Stdout = &out
|
||||
|
||||
@@ -47,9 +47,17 @@ func FetchNews() News {
|
||||
config.LoadConfig(cfg)
|
||||
client := &http.Client{}
|
||||
|
||||
if cfg.News.ApiKey == "" {
|
||||
return News{
|
||||
Status: "No API key provided",
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", apiBaseURL+"?sources="+cfg.News.Sources+"&pageSize=100&apiKey="+cfg.News.ApiKey, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return News{
|
||||
Status: err.Error(),
|
||||
}
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
|
||||
@@ -23,6 +23,11 @@ func FetchCurrentWeather() CurrentWeather {
|
||||
config.LoadConfig(cfg)
|
||||
client := &http.Client{}
|
||||
currentWeather := &CurrentWeather{}
|
||||
if cfg.OpenWeatherMap.ApiKey == "" {
|
||||
return CurrentWeather{
|
||||
ErrorMessage: "No API key provided",
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", apiBaseURL+"?id="+cfg.OpenWeatherMap.LocationId+"&units=metric&lang=en&APPID="+cfg.OpenWeatherMap.ApiKey, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -78,6 +78,9 @@ func Connect() PiHConnector {
|
||||
cfg := &configFile{}
|
||||
config.LoadConfig(cfg)
|
||||
client := &http.Client{}
|
||||
if cfg.Pihole.Host == "" {
|
||||
return PiHConnector{}
|
||||
}
|
||||
req, err := http.NewRequest("POST", "http://"+cfg.Pihole.Host+"/api/auth", strings.NewReader("{\"password\": \""+cfg.Pihole.Password+"\"}"))
|
||||
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user