Initial commit
This commit is contained in:
commit
be29af436f
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# JetBrains IDEs
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# macOS stuff
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# go build output
|
||||||
|
spaceapid
|
48
ccchh-template.json
Normal file
48
ccchh-template.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
100
main.go
Normal file
100
main.go
Normal 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
44
types/v14.go
Normal 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"`
|
||||||
|
}
|
Loading…
Reference in a new issue