summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go274
1 files changed, 274 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..08b9050
--- /dev/null
+++ b/main.go
@@ -0,0 +1,274 @@
+package main
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "github.com/arran4/golang-ical"
+ "io"
+ "net/http"
+ "strings"
+ "time"
+)
+
+const (
+ API_URL = "https://api.events.ccc.de/congress/2024"
+)
+
+var ROOMS []Room
+
+type Token struct {
+ Token string `json:"token"`
+}
+
+type Auth struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+}
+
+type Event struct {
+ ID string `json:"id"`
+ Kind string `json:"kind"`
+ Name string `json:"name"`
+ Slug string `json:"slug"`
+ URL string `json:"url"`
+ Track string `json:"track"`
+ Assembly string `json:"assembly"`
+ Room string `json:"room"`
+ Location string `json:"location"`
+ Language string `json:"language"`
+ Description string `json:"description"`
+ ScheduleStart time.Time `json:"schedule_start"`
+ ScheduleDuration string `json:"schedule_duration"`
+ ScheduleEnd time.Time `json:"schedule_end"`
+}
+
+// Link represents the structure of the "links" array in the JSON
+type Link struct {
+ Type string `json:"type"`
+ Name string `json:"name"`
+ URI string `json:"uri"`
+ URL string `json:"url"`
+}
+
+// Room represents the structure of the main JSON object
+type Room struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Slug string `json:"slug"`
+ RoomType string `json:"room_type"`
+ Capacity int `json:"capacity"`
+ Links []Link `json:"links"`
+ Assembly string `json:"assembly"`
+ PublicURL string `json:"public_url"`
+}
+
+func scrape_hub() ([]Event, error) {
+ println("scrape hub")
+ resp, err := http.Get(fmt.Sprintf("%s/events", API_URL))
+ if err != nil {
+ fmt.Println("Error making GET request:", err)
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error reading response body:", err)
+ return nil, err
+ }
+
+ var events []Event
+
+ if err := json.Unmarshal(body, &events); err != nil {
+ fmt.Println("Error unmarshalling JSON:", err)
+ return nil, err
+ }
+
+ // Use the events slice here
+ fmt.Println("Number of events:", len(events))
+ return events, nil
+}
+
+func get_rooms() ([]Room, error) {
+ println("get rooms")
+ resp, err := http.Get(fmt.Sprintf("%s/rooms", API_URL))
+ if err != nil {
+ fmt.Println("Error making GET request:", err)
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error reading response body:", err)
+ return nil, err
+ }
+
+ var rooms []Room
+
+ if err := json.Unmarshal(body, &rooms); err != nil {
+ fmt.Println("Error unmarshalling JSON:", err)
+ return nil, err
+ }
+
+ // Use the events slice here
+ fmt.Println("Number of rooms:", len(rooms))
+ return rooms, nil
+}
+
+func get_token(username string, password string) (string, error) {
+ println("get token")
+
+ jsonBytes, err := json.Marshal(Auth{Username: username, Password: password})
+ if err != nil {
+ fmt.Println("Error unmarshalling JSON:", err)
+ return "", err
+ }
+
+ resp, err := http.Post(
+ fmt.Sprintf("%s/auth/get-token", API_URL),
+ "application/json",
+ bytes.NewBuffer(jsonBytes),
+ )
+ if err != nil {
+ fmt.Println("Error getting Token:", err)
+ return "", err
+ }
+ defer resp.Body.Close()
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error reading response body:", err)
+ return "", err
+ }
+ var token Token
+ if err := json.Unmarshal(body, &token); err != nil {
+ fmt.Println("Error unmarshalling JSON:", err)
+ return "", err
+ }
+ println(token.Token)
+ return token.Token, nil
+}
+
+func get_me_events(token string) ([]string, error) {
+ println("get personal events")
+
+ req, err := http.NewRequest(
+ "GET",
+ fmt.Sprintf("%s/me/events", API_URL),
+ nil,
+ )
+ req.Header.Set("Authorization", fmt.Sprintf("Token %s", token))
+
+ resp, err := (&http.Client{}).Do(req)
+ if err != nil {
+ fmt.Println("Error fetching personal events:", err)
+ return nil, err
+ }
+ defer resp.Body.Close()
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ fmt.Println("Error reading response body:", err)
+ return nil, err
+ }
+ println(string(body))
+ var uuids []string
+ if err := json.Unmarshal(body, &uuids); err != nil {
+ fmt.Println("Error unmarshalling JSON:", err)
+ return nil, err
+ }
+ return uuids, nil
+}
+
+func get_schedule(w http.ResponseWriter, r *http.Request) {
+ println("/event.ics")
+ auth_header := r.Header.Get("Authorization")
+ println(auth_header)
+ if auth_header == "" {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+ credentials_encoded := auth_header[len("Basic "):]
+ credentials, err := base64.StdEncoding.DecodeString(credentials_encoded)
+ if err != nil {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+ auth := strings.SplitN(string(credentials), ":", 2)
+ if len(auth) != 2 {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+ username := auth[0]
+ password := auth[1]
+
+ println(username, password)
+
+ token, err := get_token(username, password)
+ if err != nil {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+ ids, err := get_me_events(token)
+ if err != nil {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+ schedule, err := scrape_hub()
+ if err != nil {
+ http.Error(w, "Unauthorized", http.StatusUnauthorized)
+ return
+ }
+
+ var my_events []Event
+ for _, event := range schedule {
+ for _, id := range ids {
+ if event.ID == id {
+ my_events = append(my_events, event)
+ break
+ }
+ }
+ }
+
+ cal := ics.NewCalendar()
+ cal.SetMethod(ics.MethodRequest)
+ for _, event := range my_events {
+ var location = ""
+ for _, room := range ROOMS {
+ if event.Room == room.ID {
+ location = room.Name
+ }
+ }
+
+ cal_event := cal.AddEvent(event.ID)
+ cal_event.SetStartAt(event.ScheduleStart)
+ cal_event.SetEndAt(event.ScheduleEnd)
+ cal_event.SetSummary(event.Name)
+ cal_event.SetLocation(location)
+ cal_event.SetDescription(ics.ToText(strings.ReplaceAll(event.Description, "\r\n", "\n")))
+ cal_event.SetURL(event.URL)
+ cal_event.SetOrganizer(event.Assembly)
+ }
+
+ ics := cal.Serialize()
+
+ w.Header().Set("Content-Type", "text/calendar; charset=utf-8")
+ w.Write([]byte(ics))
+}
+
+func main() {
+ rooms, err := get_rooms()
+ if err != nil {
+ return
+ }
+ ROOMS = rooms
+
+ println("Stating Server")
+ // Start a web server to serve the iCal file
+ http.HandleFunc("/events.ics", get_schedule)
+ err = http.ListenAndServe("127.0.0.1:8080", nil)
+ if err != nil {
+ println(err)
+ }
+}