diff options
Diffstat (limited to 'atom.go')
-rw-r--r-- | atom.go | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/atom.go b/atom.go new file mode 100644 index 0000000..d905348 --- /dev/null +++ b/atom.go @@ -0,0 +1,129 @@ +// Atom feed synthesizer +// Copyright (C) 2022 Nguyễn Gia Phong +// +// This file is part of Phylactery. +// +// Phylactery is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Phylactery is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Phylactery. If not, see <https://www.gnu.org/licenses/>. + +package main + +import ( + "archive/zip" + "encoding/xml" + "net/http" + "os" + "path" + "path/filepath" + "strconv" + "strings" + "time" +) + +// Type Img represents an XHTML img tag. +type Img struct { + Src string `xml:"src,attr"` + Alt string `xml:"alt,attr"` +} + +// Type Div represents an XHTML div tag. +type Div struct { + NS string `xml:"xmlns,attr"` + Img []Img `xml:"img"` +} + +// Type AtomLink represents an atom:link element. +type AtomLink struct { + Rel string `xml:"rel,attr"` + Href string `xml:"href,attr"` +} + +// Type AtomContent represents an atom:content element. +type AtomContent struct { + Type string `xml:"type,attr"` + Div Div `xml:"div"` +} + +// Type AtomEntry represents an Atom Entry Document. +type AtomEntry struct { + Title string `xml:"title"` + ID string `xml:"id"` + Link []AtomLink `xml:"link"` + Updated time.Time `xml:"updated"` + Content AtomContent `xml:"content"` +} + +// Type AtomFeed represents an Atom Feed Document. +type AtomFeed struct { + XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"` + Title string `xml:"title"` + ID string `xml:"id"` + Link []AtomLink `xml:"link"` + Updated time.Time `xml:"updated"` + Author string `xml:"author>name"` + Entry []AtomEntry `xml:"entry"` +} + +// Function synthesizeAtom generates an Atom feed for given directory. +func synthesizeAtom(r *http.Request, dir string, updated time.Time) AtomFeed { + baseURL := "http://" + r.Host + if r.TLS != nil { + baseURL = "https" + baseURL[4:] + } + var entries []AtomEntry + filepath.WalkDir(dir, func(p string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() { + return nil + } + name := strings.TrimPrefix(p, dir)[1:] + u := escape(baseURL + path.Join(r.URL.Path, name)) + var images []Img + cbz, err := zip.OpenReader(p) + if err != nil { + return nil + } + defer cbz.Close() + for i, f := range cbz.File { + if isImageFile(f) { + continue + } + images = append(images, + Img{u + "?entry=" + strconv.Itoa(i), f.Name}) + } + + info, _ := d.Info() + entries = append(entries, AtomEntry{ + Title: name, + ID: name, + Link: []AtomLink{{"alternate", u}}, + Updated: info.ModTime(), + Content: AtomContent{ + "xhtml", + Div{"http://www.w3.org/1999/xhtml", images}, + }, + }) + return nil + }) + + id := escape(baseURL + r.URL.Path) + return AtomFeed{ + Title: r.URL.Path[1 : len(r.URL.Path)-1], + ID: id, + Link: []AtomLink{ + {"alternate", id}, + {"self", id + "?feed=atom"}, + }, + Updated: updated, + Entry: entries, + } +} |