gator/internal/rss/rss.go

82 lines
1.7 KiB
Go
Raw Permalink Normal View History

2024-10-01 01:12:12 +01:00
package rss
import (
"context"
"encoding/xml"
"fmt"
"html"
"io"
"net/http"
)
type Feed struct {
Channel Channel `xml:"channel"`
}
type Channel struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
Items []Item `xml:"item"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
PubDate string `xml:"pubDate"`
}
func FetchFeed(ctx context.Context, url string) (*Feed, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("received an error creating the HTTP request: %w", err)
}
request.Header.Set("User-Agent", "Gator/0.0.0")
client := http.Client{}
response, err := client.Do(request)
if err != nil {
return nil, fmt.Errorf("error getting the response from the server: %w", err)
}
defer response.Body.Close()
if response.StatusCode >= 400 {
return nil, fmt.Errorf(
"received a bad status from %s: (%d) %s",
url,
response.StatusCode,
response.Status,
)
}
data, err := io.ReadAll(response.Body)
if err != nil {
return nil, fmt.Errorf(
"unable to read the response from the server: %w",
err,
)
}
var feed Feed
if err := xml.Unmarshal(data, &feed); err != nil {
return nil, fmt.Errorf(
"unable to decode the XML data: %w",
err,
)
}
feed.Channel.Title = html.UnescapeString(feed.Channel.Title)
feed.Channel.Description = html.UnescapeString(feed.Channel.Description)
for _, item := range feed.Channel.Items {
item.Title = html.UnescapeString(item.Title)
item.Description = html.UnescapeString(item.Description)
}
return &feed, nil
}