Skip to content

Commit 672185c

Browse files
committed
feat: Allow proxy to fetch all Luma data
Signed-off-by: Felicitas Pojtinger <felicitas@pojtinger.com>
1 parent 19b8b12 commit 672185c

1 file changed

Lines changed: 140 additions & 61 deletions

File tree

main.go

Lines changed: 140 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import (
1010
"os"
1111
)
1212

13+
const defaultLumaAPIBase = "https://api.luma.com/calendar/get-items"
14+
1315
type LumaEvent struct {
14-
Name string `json:"name"`
15-
StartAt string `json:"start_at"`
16-
URL string `json:"url"`
17-
GeoAddr *struct {
16+
Name string `json:"name"`
17+
StartAt string `json:"start_at"`
18+
URL string `json:"url"`
19+
CoverURL string `json:"cover_url"`
20+
GeoAddr *struct {
1821
Address string `json:"address"`
1922
ShortAddress string `json:"short_address"`
2023
} `json:"geo_address_info"`
@@ -28,78 +31,144 @@ type LumaResponse struct {
2831
Entries []LumaEntry `json:"entries"`
2932
}
3033

31-
type NextEvent struct {
34+
type EventItem struct {
3235
Name string `json:"name"`
3336
StartAt string `json:"start_at"`
3437
URL string `json:"url"`
3538
Location string `json:"location"`
39+
CoverURL string `json:"cover_url"`
3640
}
3741

3842
type Output struct {
39-
Entries []NextEvent `json:"entries"`
43+
Entries []EventItem `json:"entries"`
4044
}
4145

42-
func NextEventHandler(w http.ResponseWriter, r *http.Request) {
43-
cal := r.URL.Query().Get("calendar")
44-
if cal == "" {
45-
w.Write([]byte("missing calendar query parameter"))
46+
func NextEventHandler(apiBase string) http.HandlerFunc {
47+
return func(w http.ResponseWriter, r *http.Request) {
48+
cal := r.URL.Query().Get("calendar")
49+
if cal == "" {
50+
w.Write([]byte("missing calendar query parameter"))
4651

47-
panic("missing calendar query parameter")
48-
}
52+
panic("missing calendar query parameter")
53+
}
4954

50-
u := "https://api.luma.com/calendar/get-items?" + url.Values{
51-
"calendar_api_id": {cal},
52-
"period": {"future"},
53-
"pagination_limit": {"1"},
54-
}.Encode()
55+
u := apiBase + "?" + url.Values{
56+
"calendar_api_id": {cal},
57+
"period": {"future"},
58+
"pagination_limit": {"1"},
59+
}.Encode()
5560

56-
resp, err := http.Get(u)
57-
if err != nil {
58-
panic(err)
59-
}
60-
defer resp.Body.Close()
61+
resp, err := http.Get(u)
62+
if err != nil {
63+
panic(err)
64+
}
65+
defer resp.Body.Close()
6166

62-
body, err := io.ReadAll(resp.Body)
63-
if err != nil {
64-
panic(err)
65-
}
67+
body, err := io.ReadAll(resp.Body)
68+
if err != nil {
69+
panic(err)
70+
}
6671

67-
var lr LumaResponse
68-
if err := json.Unmarshal(body, &lr); err != nil {
69-
panic(err)
70-
}
72+
var lr LumaResponse
73+
if err := json.Unmarshal(body, &lr); err != nil {
74+
panic(err)
75+
}
7176

72-
output := Output{}
77+
output := Output{}
7378

74-
if len(lr.Entries) > 0 {
75-
evt := lr.Entries[0].Event
79+
if len(lr.Entries) > 0 {
80+
evt := lr.Entries[0].Event
7681

77-
loc := ""
78-
if evt.GeoAddr != nil {
79-
loc = evt.GeoAddr.Address
80-
if loc == "" {
81-
loc = evt.GeoAddr.ShortAddress
82+
loc := ""
83+
if evt.GeoAddr != nil {
84+
loc = evt.GeoAddr.Address
85+
if loc == "" {
86+
loc = evt.GeoAddr.ShortAddress
87+
}
8288
}
89+
90+
output.Entries = []EventItem{{
91+
Name: evt.Name,
92+
StartAt: evt.StartAt,
93+
URL: evt.URL,
94+
Location: loc,
95+
CoverURL: evt.CoverURL,
96+
}}
8397
}
8498

85-
output.Entries = []NextEvent{{
86-
Name: evt.Name,
87-
StartAt: evt.StartAt,
88-
URL: evt.URL,
89-
Location: loc,
90-
}}
91-
}
99+
j, err := json.Marshal(output)
100+
if err != nil {
101+
panic(err)
102+
}
92103

93-
j, err := json.Marshal(output)
94-
if err != nil {
95-
panic(err)
104+
fmt.Fprintf(w, "%v", string(j))
96105
}
106+
}
107+
108+
func EventsHandler(apiBase string) http.HandlerFunc {
109+
return func(w http.ResponseWriter, r *http.Request) {
110+
cal := r.URL.Query().Get("calendar")
111+
if cal == "" {
112+
w.Write([]byte("missing calendar query parameter"))
113+
114+
panic("missing calendar query parameter")
115+
}
116+
117+
u := apiBase + "?" + url.Values{
118+
"calendar_api_id": {cal},
119+
"period": {"future"},
120+
"pagination_limit": {"20"},
121+
}.Encode()
97122

98-
fmt.Fprintf(w, "%v", string(j))
123+
resp, err := http.Get(u)
124+
if err != nil {
125+
panic(err)
126+
}
127+
defer resp.Body.Close()
128+
129+
body, err := io.ReadAll(resp.Body)
130+
if err != nil {
131+
panic(err)
132+
}
133+
134+
var lr LumaResponse
135+
if err := json.Unmarshal(body, &lr); err != nil {
136+
panic(err)
137+
}
138+
139+
output := Output{}
140+
141+
for _, entry := range lr.Entries {
142+
evt := entry.Event
143+
144+
loc := ""
145+
if evt.GeoAddr != nil {
146+
loc = evt.GeoAddr.Address
147+
if loc == "" {
148+
loc = evt.GeoAddr.ShortAddress
149+
}
150+
}
151+
152+
output.Entries = append(output.Entries, EventItem{
153+
Name: evt.Name,
154+
StartAt: evt.StartAt,
155+
URL: evt.URL,
156+
Location: loc,
157+
CoverURL: evt.CoverURL,
158+
})
159+
}
160+
161+
j, err := json.Marshal(output)
162+
if err != nil {
163+
panic(err)
164+
}
165+
166+
fmt.Fprintf(w, "%v", string(j))
167+
}
99168
}
100169

101170
func Handler(w http.ResponseWriter, r *http.Request) {
102-
NextEventHandler(w, r)
171+
NextEventHandler(defaultLumaAPIBase).ServeHTTP(w, r)
103172
}
104173

105174
func main() {
@@ -113,20 +182,30 @@ func main() {
113182
origin = "*"
114183
}
115184

116-
http.HandleFunc("/next-event", func(w http.ResponseWriter, r *http.Request) {
117-
w.Header().Set("Access-Control-Allow-Origin", origin)
118-
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
119-
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
120-
w.Header().Set("Content-Type", "application/json")
121-
w.Header().Set("Cache-Control", "public, max-age=300")
185+
apiBase := os.Getenv("LUMA_API_BASE")
186+
if apiBase == "" {
187+
apiBase = defaultLumaAPIBase
188+
}
189+
190+
cors := func(next http.HandlerFunc) http.HandlerFunc {
191+
return func(w http.ResponseWriter, r *http.Request) {
192+
w.Header().Set("Access-Control-Allow-Origin", origin)
193+
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
194+
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
195+
w.Header().Set("Content-Type", "application/json")
196+
w.Header().Set("Cache-Control", "public, max-age=300")
197+
198+
if r.Method == http.MethodOptions {
199+
w.WriteHeader(http.StatusNoContent)
200+
return
201+
}
122202

123-
if r.Method == http.MethodOptions {
124-
w.WriteHeader(http.StatusNoContent)
125-
return
203+
next(w, r)
126204
}
205+
}
127206

128-
Handler(w, r)
129-
})
207+
http.HandleFunc("/next-event", cors(NextEventHandler(apiBase)))
208+
http.HandleFunc("/events", cors(EventsHandler(apiBase)))
130209

131210
log.Printf("listening on :%s", port)
132211
if err := http.ListenAndServe(fmt.Sprintf(":%s", port), nil); err != nil {

0 commit comments

Comments
 (0)