Add paddock briefing RSS backend spike

This commit is contained in:
2026-05-25 12:02:18 -04:00
parent 79b0b9f469
commit 84a8827244
12 changed files with 804 additions and 2 deletions

View File

@@ -115,6 +115,24 @@ func (s *Server) handleSessions(w http.ResponseWriter, r *http.Request) {
writeJSON(w, sessions)
}
// --- /api/v1/news ---
func (s *Server) handleNews(w http.ResponseWriter, r *http.Request) {
if !s.hasLocalQuery() {
writeJSON(w, []query.NewsItem{})
return
}
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
source := strings.TrimSpace(r.URL.Query().Get("source"))
items, err := s.query.ListNews(limit, source)
if err != nil {
writeError(w, err, http.StatusInternalServerError, false)
return
}
writeJSON(w, items)
}
// --- /api/v1/drivers ---
func (s *Server) handleDrivers(w http.ResponseWriter, r *http.Request) {

View File

@@ -192,6 +192,52 @@ func TestHandleSeasonsWithData(t *testing.T) {
}
}
func TestHandleNewsWithLocalData(t *testing.T) {
st := openTestStore(t)
now := time.Unix(1800000000, 0).UTC()
published := now.Add(-30 * time.Minute)
if err := st.UpsertNewsSource(store.NewsSource{
Source: "racefans-f1",
Name: "RaceFans F1",
FeedURL: "https://www.racefans.net/category/f1-news/feed/",
Category: "news",
Enabled: true,
UpdatedAt: now,
}); err != nil {
t.Fatalf("UpsertNewsSource() error = %v", err)
}
if err := st.UpsertNewsItem(store.NewsItem{
URL: "https://example.com/story",
Source: "racefans-f1",
Title: "RaceFans story",
PublishedAt: &published,
Summary: "Brief summary",
Category: "news",
FetchedAt: now,
}); err != nil {
t.Fatalf("UpsertNewsItem() error = %v", err)
}
srv := testServer(t, st)
req := httptest.NewRequest(http.MethodGet, "/api/v1/news?source=racefans-f1&limit=5", nil)
rec := httptest.NewRecorder()
srv.handleNews(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
var items []query.NewsItem
if err := json.Unmarshal(rec.Body.Bytes(), &items); err != nil {
t.Fatalf("decode response: %v", err)
}
if len(items) != 1 {
t.Fatalf("items len = %d, want 1", len(items))
}
if items[0].Source != "racefans-f1" || items[0].Title != "RaceFans story" {
t.Fatalf("items[0] = %+v, want seeded item", items[0])
}
}
func TestHandleWeekendNotFound(t *testing.T) {
st := openTestStore(t)
srv := testServer(t, st)

View File

@@ -64,6 +64,7 @@ func (s *Server) routes() (http.Handler, error) {
mux.HandleFunc("/api/v1/race-hub", s.handleRaceHub)
mux.HandleFunc("/api/v1/seasons", s.handleSeasons)
mux.HandleFunc("/api/v1/weekend", s.handleWeekend)
mux.HandleFunc("/api/v1/news", s.handleNews)
mux.HandleFunc("/api/v1/meetings", s.handleMeetings)
mux.HandleFunc("/api/v1/sessions", s.handleSessions)
mux.HandleFunc("/api/v1/drivers", s.handleDrivers)