Initial commit

This commit is contained in:
Bendodroid 2023-11-04 20:10:08 +01:00
commit be29af436f
Signed by: bendodroid
GPG key ID: 3EEE19A0F73D5FFC
5 changed files with 203 additions and 0 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# JetBrains IDEs
.idea/
# macOS stuff
.DS_Store
# go build output
spaceapid

48
ccchh-template.json Normal file
View file

@ -0,0 +1,48 @@
{
"api_compatibility": [
"14"
],
"space": "CCCHH",
"logo": "https://next.hamburg.ccc.de/images/logo.svg",
"ext_ccc": "erfa",
"url": "https://hamburg.ccc.de/",
"location": {
"address": "Zeiseweg 9, 22765 Hamburg, Germany",
"lon": 9.9445899999999998,
"lat": 53.55836
},
"state": {
"icon": {
"open": "https://hamburg.ccc.de/dooris/open.png",
"closed": "https://hamburg.ccc.de/dooris/close.png"
}
},
"contact": {
"phone": "",
"irc": "ircs://irc.hackint.org:9999/ccchh",
"mastodon": "@ccchh@chaos.social",
"email": "mail@hamburg.ccc.de",
"ml": "talk@hamburg.ccc.de",
"matrix": "#ccchh:hamburg.ccc.de"
},
"feeds": {
"blog": {
"type": "application/atom+xml",
"url": "https://hamburg.ccc.de/feed.xml"
},
"calendar": {
"type": "ical",
"url": "webcal://cloud.hamburg.ccc.de/remote.php/dav/public-calendars/QJAdExziSnNJEz5g/?export"
}
},
"links": [
{
"name": "Wiki",
"url": "https://wiki.ccchh.net"
},
{
"name": "GitLab",
"url": "https://gitlab.hamburg.ccc.de"
}
]
}

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module gitlab.hamburg.ccc.de/ccchh/spaceapid
go 1.21

100
main.go Normal file
View file

@ -0,0 +1,100 @@
package main
import (
"encoding/json"
"io"
"log"
"net/http"
"os"
"slices"
"strconv"
"time"
"gitlab.hamburg.ccc.de/ccchh/spaceapid/types"
)
func main() {
validUsername, success := os.LookupEnv("DOORIS_USERNAME")
if !success || validUsername == "" {
log.Fatalln("Could not retrieve DOORIS_API_KEY env variable or variable is empty")
}
validPassword, success := os.LookupEnv("DOORIS_PASSWORD")
if !success || validPassword == "" {
log.Fatalln("Could not retrieve DOORIS_API_KEY env variable or variable is empty")
}
initialJson, success := os.LookupEnv("SPACE_API_JSON")
if !success || initialJson == "" {
log.Fatalln("Could not retrieve SPACE_API_JSON env variable or variable is empty")
}
spaceApiResponse := new(types.SpaceAPIResponseV14)
err := json.Unmarshal([]byte(initialJson), spaceApiResponse)
if err != nil {
log.Fatalln("Could not parse provided JSON")
}
if !slices.Contains(spaceApiResponse.APICompatibility, "14") {
log.Fatalln("Provided JSON doesn't specify compatibility with API version 14")
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
log.Println("Wrong METHOD from", r.RemoteAddr)
w.WriteHeader(http.StatusMethodNotAllowed)
w.Header().Set("allow", http.MethodGet)
return
}
response, err := json.Marshal(spaceApiResponse)
if err != nil {
log.Println("Failed to serialize JSON response")
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write(response)
})
http.HandleFunc("/state/open", func(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok || username != validUsername || password != validPassword {
log.Println("Unauthorized request from", r.RemoteAddr)
w.WriteHeader(http.StatusUnauthorized)
w.Header().Set("www-authentication", "Basic realm=\"space-api\"")
return
}
if r.Method != http.MethodPut {
log.Println("Wrong METHOD from", r.RemoteAddr)
w.WriteHeader(http.StatusMethodNotAllowed)
w.Header().Set("allow", http.MethodPut)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
log.Println("Failed to read body status update request from", r.RemoteAddr)
w.WriteHeader(http.StatusInternalServerError)
_, _ = io.WriteString(w, "Failed reading HTTP request body")
return
}
newState, err := strconv.ParseBool(string(body))
if err != nil {
w.WriteHeader(http.StatusBadRequest)
_, _ = io.WriteString(w, "HTTP request body should either be true or false")
return
}
spaceApiResponse.State.Open = newState
spaceApiResponse.State.LastChange = time.Now().Unix()
w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, "Update Successful")
})
log.Println("Starting HTTP server...")
log.Fatalln(http.ListenAndServe(":8080", nil))
}

44
types/v14.go Normal file
View file

@ -0,0 +1,44 @@
package types
type SpaceAPIResponseV14 struct {
APICompatibility []string `json:"api_compatibility"`
Space string `json:"space"`
Logo string `json:"logo"`
ExtCcc string `json:"ext_ccc"`
URL string `json:"url"`
Location struct {
Address string `json:"address"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
} `json:"location"`
State struct {
Open bool `json:"open"`
LastChange int64 `json:"lastchange"`
Icon struct {
Closed string `json:"closed"`
Open string `json:"open"`
} `json:"icon"`
} `json:"state"`
Contact struct {
Phone string `json:"phone"`
Irc string `json:"irc"`
Mastodon string `json:"mastodon"`
Email string `json:"email"`
Ml string `json:"ml"`
Matrix string `json:"matrix"`
} `json:"contact"`
Feeds struct {
Blog struct {
Type string `json:"type"`
URL string `json:"url"`
} `json:"blog"`
Calendar struct {
Type string `json:"type"`
URL string `json:"url"`
} `json:"calendar"`
} `json:"feeds"`
Links []struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"links"`
}