Cybersecurity-Projects/PROJECTS/intermediate/security-news-scraper/internal/parse/parse.go

75 lines
1.5 KiB
Go

// ©AngelaMos | 2026
// parse.go
package parse
import (
"fmt"
"io"
"strings"
"time"
"github.com/mmcdole/gofeed"
)
type Item struct {
Title string
Link string
Summary string
Body string
Author string
Published time.Time
Categories []string
}
var timeLayouts = []string{time.RFC1123Z, time.RFC1123, time.RFC822Z, time.RFC822, time.RFC3339}
func Feed(r io.Reader) ([]Item, error) {
feed, err := gofeed.NewParser().Parse(r)
if err != nil {
return nil, fmt.Errorf("parse: %w", err)
}
items := make([]Item, 0, len(feed.Items))
for _, it := range feed.Items {
items = append(items, Item{
Title: strings.TrimSpace(it.Title),
Link: strings.TrimSpace(it.Link),
Summary: it.Description,
Body: it.Content,
Author: author(it),
Published: published(it),
Categories: it.Categories,
})
}
return items, nil
}
func author(it *gofeed.Item) string {
if it.Author != nil && it.Author.Name != "" {
return it.Author.Name
}
if len(it.Authors) > 0 {
return it.Authors[0].Name
}
return ""
}
func published(it *gofeed.Item) time.Time {
if it.PublishedParsed != nil {
return it.PublishedParsed.UTC()
}
if it.UpdatedParsed != nil {
return it.UpdatedParsed.UTC()
}
raw := strings.TrimSpace(it.Published)
if raw == "" {
raw = strings.TrimSpace(it.Updated)
}
for _, layout := range timeLayouts {
if t, err := time.Parse(layout, raw); err == nil {
return t.UTC()
}
}
return time.Time{}
}