eintopf.info@v0.13.16/service/rss/transport.go (about) 1 // Copyright (C) 2022 The Eintopf authors 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16 package rss 17 18 import ( 19 "context" 20 "encoding/xml" 21 "fmt" 22 "net/http" 23 24 "github.com/go-chi/chi/v5" 25 26 "eintopf.info/internal/plausible" 27 "eintopf.info/internal/xhttp" 28 "eintopf.info/service/eventsearch" 29 ) 30 31 func Routes(service Service, plausibleClient *plausible.Client) func(r chi.Router) { 32 router := router{service: service} 33 return func(r chi.Router) { 34 r.Use(plausible.MiddlewareWithName(plausibleClient, "rss")) 35 r.Get("/rss", router.getEventsRSSFeed) 36 r.Get("/groups/{id}/rss", router.getGroupRSSFeed) 37 r.Get("/places/{id}/rss", router.getPlaceRSSFeed) 38 } 39 } 40 41 type router struct { 42 service Service 43 } 44 45 func (router router) getEventsRSSFeed(w http.ResponseWriter, r *http.Request) { 46 opts, err := eventsearch.OptionsFromRequest(r) 47 if err != nil { 48 xhttp.WriteBadRequest(r.Context(), w, err) 49 return 50 } 51 feed, err := router.service.Feed(r.Context(), opts, &Channel{Title: "events"}) 52 if err != nil { 53 xhttp.WriteError(r.Context(), w, err) 54 return 55 } 56 err = writeFeed(r.Context(), w, feed) 57 if err != nil { 58 xhttp.WriteInternalError(r.Context(), w, err) 59 return 60 } 61 } 62 63 func (router router) getGroupRSSFeed(w http.ResponseWriter, r *http.Request) { 64 id := chi.URLParam(r, "id") 65 if id == "" { 66 xhttp.WriteBadRequest(r.Context(), w, fmt.Errorf("empty id")) 67 return 68 } 69 feed, err := router.service.GroupFeed(r.Context(), id) 70 if err != nil { 71 xhttp.WriteError(r.Context(), w, err) 72 return 73 } 74 err = writeFeed(r.Context(), w, feed) 75 if err != nil { 76 xhttp.WriteInternalError(r.Context(), w, err) 77 return 78 } 79 } 80 81 func (router router) getPlaceRSSFeed(w http.ResponseWriter, r *http.Request) { 82 id := chi.URLParam(r, "id") 83 if id == "" { 84 xhttp.WriteBadRequest(r.Context(), w, fmt.Errorf("empty id")) 85 return 86 } 87 feed, err := router.service.PlaceFeed(r.Context(), id) 88 if err != nil { 89 xhttp.WriteError(r.Context(), w, err) 90 return 91 } 92 err = writeFeed(r.Context(), w, feed) 93 if err != nil { 94 xhttp.WriteInternalError(r.Context(), w, err) 95 return 96 } 97 } 98 99 func writeFeed(ctx context.Context, w http.ResponseWriter, feed *Feed) error { 100 feedXML, err := xml.Marshal(feed) 101 if err != nil { 102 return err 103 } 104 w.Header().Add("Content-Type", "application/rss+xml") 105 w.Header().Add("Content-Disposition", "inline; filename=eintopf.rss") 106 _, err = w.Write(feedXML) 107 if err != nil { 108 return err 109 } 110 return nil 111 }