First implementation of an atom feed
This commit is contained in:
174
feed.go
Normal file
174
feed.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package atomfeed
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
|
||||
*CommonAttributes
|
||||
Authors []*Person `xml:"author,omitempty"`
|
||||
Categories []*Category `xml:"category,omitempty"`
|
||||
Contributors []*Person `xml:"contributor,omitempty"`
|
||||
Generator *Generator `xml:"generator,omitempty"`
|
||||
Icon *Icon `xml:"icon,omitempty"`
|
||||
ID *ID `xml:"id"`
|
||||
Links []*Link `xml:"link,omitempty"` // There should be one link with rel "self"
|
||||
Logo *Logo `xml:"logo,omitempty"`
|
||||
Rights *Text `xml:"rights,omitempty"`
|
||||
Subtitle *Text `xml:"subtitle,omitempty"`
|
||||
Title *Text `xml:"title"`
|
||||
Updated *Date `xml:"updated"`
|
||||
Extensions []*ExtensionElement `xml:",any"`
|
||||
Entries []*Entry `xml:"entry,omitempty"`
|
||||
}
|
||||
|
||||
func (f *Feed) Check() error {
|
||||
if f.ID == nil {
|
||||
return errors.New("no id element of feed")
|
||||
} else {
|
||||
if err := f.ID.Check(); err != nil {
|
||||
return fmt.Errorf("id element of feed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Authors == nil {
|
||||
for _, e := range f.Entries {
|
||||
if err := e.checkAuthors(); err != nil {
|
||||
return fmt.Errorf("no authors set in feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i, a := range f.Authors {
|
||||
if err := a.Check(); err != nil {
|
||||
return fmt.Errorf("author element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Categories != nil {
|
||||
for i, c := range f.Categories {
|
||||
if err := c.Check(); err != nil {
|
||||
return fmt.Errorf("category element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Contributors != nil {
|
||||
for i, c := range f.Contributors {
|
||||
if err := c.Check(); err != nil {
|
||||
return fmt.Errorf("contributor element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Generator != nil {
|
||||
if err := f.Generator.Check(); err != nil {
|
||||
return fmt.Errorf("generator element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Icon != nil {
|
||||
if err := f.Icon.Check(); err != nil {
|
||||
return fmt.Errorf("icon element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Links != nil {
|
||||
for i, l := range f.Links {
|
||||
if err := l.Check(); err != nil {
|
||||
return fmt.Errorf("link element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Logo != nil {
|
||||
if err := f.Logo.Check(); err != nil {
|
||||
return fmt.Errorf("logo element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Rights != nil {
|
||||
if err := (*f.Rights).Check(); err != nil {
|
||||
return fmt.Errorf("rights element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Subtitle != nil {
|
||||
if err := (*f.Subtitle).Check(); err != nil {
|
||||
return fmt.Errorf("subtitle element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Title == nil {
|
||||
return fmt.Errorf("no title element of feed %v", f.ID.URI)
|
||||
} else {
|
||||
if err := (*f.Title).Check(); err != nil {
|
||||
return fmt.Errorf("title element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Updated == nil {
|
||||
return fmt.Errorf("no updated element of feed %v", f.ID)
|
||||
} else {
|
||||
if err := f.Updated.Check(); err != nil {
|
||||
return fmt.Errorf("updated element of feed %v: %v", f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
if f.Extensions != nil {
|
||||
for i, x := range f.Extensions {
|
||||
if err := x.Check(); err != nil {
|
||||
return fmt.Errorf("extension element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Entries != nil {
|
||||
for i, n := range f.Entries {
|
||||
if err := n.Check(); err != nil {
|
||||
return fmt.Errorf("entry element %v of feed %v: %v", i, f.ID.URI, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Create complete link or delete
|
||||
func (f *Feed) Standardize() {
|
||||
if f.Links == nil {
|
||||
f.Links = make([]*Link, 1)
|
||||
f.Links[0] = &Link{Rel: "self"}
|
||||
} else {
|
||||
selfExists := false
|
||||
for _, l := range f.Links {
|
||||
if l.Rel == "self" {
|
||||
selfExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !selfExists {
|
||||
f.Links = append(f.Links, &Link{Rel: "self"})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Feed) AddExtension(name string, value any) {
|
||||
f.Extensions = append(f.Extensions, &ExtensionElement{XMLName: xml.Name{Local: name}, Value: value})
|
||||
}
|
||||
|
||||
func (f *Feed) ToXML(encoding string) (string, error) {
|
||||
if err := f.Check(); err != nil {
|
||||
return "", fmt.Errorf("error checking feed: %v", err)
|
||||
}
|
||||
|
||||
xml, err := xml.MarshalIndent(f, "", " ")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error xml encoding feed: %v", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintln(`<?xml version="1.0" encoding="`+encoding+`"?>`) + string(xml), nil
|
||||
}
|
Reference in New Issue
Block a user