mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 21:19:19 +00:00
opml tweaks & fixes
This commit is contained in:
parent
62e2ca4c16
commit
391ce61362
@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
Title string
|
Title string
|
||||||
Folders []*Folder
|
Folders []Folder
|
||||||
Feeds []*Feed
|
Feeds []Feed
|
||||||
}
|
}
|
||||||
|
|
||||||
type Feed struct {
|
type Feed struct {
|
||||||
@ -18,16 +18,8 @@ type Feed struct {
|
|||||||
SiteUrl string
|
SiteUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFolder(title string) *Folder {
|
func (f Folder) AllFeeds() []Feed {
|
||||||
return &Folder{
|
feeds := make([]Feed, 0)
|
||||||
Title: title,
|
|
||||||
Folders: make([]*Folder, 0),
|
|
||||||
Feeds: make([]*Feed, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Folder) AllFeeds() []*Feed {
|
|
||||||
feeds := make([]*Feed, 0)
|
|
||||||
feeds = append(feeds, f.Feeds...)
|
feeds = append(feeds, f.Feeds...)
|
||||||
for _, subfolder := range f.Folders {
|
for _, subfolder := range f.Folders {
|
||||||
feeds = append(feeds, subfolder.AllFeeds()...)
|
feeds = append(feeds, subfolder.AllFeeds()...)
|
||||||
@ -39,7 +31,7 @@ var e = html.EscapeString
|
|||||||
var indent = " "
|
var indent = " "
|
||||||
var nl = "\n"
|
var nl = "\n"
|
||||||
|
|
||||||
func (f *Folder) outline(level int) string {
|
func (f Folder) outline(level int) string {
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
prefix := strings.Repeat(indent, level)
|
prefix := strings.Repeat(indent, level)
|
||||||
|
|
||||||
@ -58,14 +50,14 @@ func (f *Folder) outline(level int) string {
|
|||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Feed) outline(level int) string {
|
func (f Feed) outline(level int) string {
|
||||||
return strings.Repeat(indent, level) + fmt.Sprintf(
|
return strings.Repeat(indent, level) + fmt.Sprintf(
|
||||||
`<outline type="rss" text="%s" xmlUrl="%s" htmlUrl="%s"/>` + nl,
|
`<outline type="rss" text="%s" xmlUrl="%s" htmlUrl="%s"/>` + nl,
|
||||||
e(f.Title), e(f.FeedUrl), e(f.SiteUrl),
|
e(f.Title), e(f.FeedUrl), e(f.SiteUrl),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Folder) OPML() string {
|
func (f Folder) OPML() string {
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
builder.WriteString(`<?xml version="1.0" encoding="UTF-8"?>` + nl)
|
builder.WriteString(`<?xml version="1.0" encoding="UTF-8"?>` + nl)
|
||||||
builder.WriteString(`<opml version="1.1">` + nl)
|
builder.WriteString(`<opml version="1.1">` + nl)
|
||||||
|
@ -7,31 +7,31 @@ import (
|
|||||||
|
|
||||||
|
|
||||||
func TestOPML(t *testing.T) {
|
func TestOPML(t *testing.T) {
|
||||||
have := (&Folder{
|
have := (Folder{
|
||||||
Title: "",
|
Title: "",
|
||||||
Feeds: []*Feed{
|
Feeds: []Feed{
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "title1",
|
Title: "title1",
|
||||||
FeedUrl: "https://baz.com/feed.xml",
|
FeedUrl: "https://baz.com/feed.xml",
|
||||||
SiteUrl: "https://baz.com/",
|
SiteUrl: "https://baz.com/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Folders: []*Folder{
|
Folders: []Folder{
|
||||||
&Folder{
|
Folder{
|
||||||
Title: "sub",
|
Title: "sub",
|
||||||
Feeds: []*Feed{
|
Feeds: []Feed{
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "subtitle1",
|
Title: "subtitle1",
|
||||||
FeedUrl: "https://foo.com/feed.xml",
|
FeedUrl: "https://foo.com/feed.xml",
|
||||||
SiteUrl: "https://foo.com/",
|
SiteUrl: "https://foo.com/",
|
||||||
},
|
},
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "&>",
|
Title: "&>",
|
||||||
FeedUrl: "https://bar.com/feed.xml",
|
FeedUrl: "https://bar.com/feed.xml",
|
||||||
SiteUrl: "https://bar.com/",
|
SiteUrl: "https://bar.com/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Folders: []*Folder{},
|
Folders: []Folder{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).OPML()
|
}).OPML()
|
||||||
|
@ -18,11 +18,11 @@ type outline struct {
|
|||||||
Outlines []outline `xml:"outline,omitempty"`
|
Outlines []outline `xml:"outline,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildFolder(title string, outlines []outline) *Folder {
|
func buildFolder(title string, outlines []outline) Folder {
|
||||||
folder := NewFolder(title)
|
folder := Folder{Title: title}
|
||||||
for _, outline := range outlines {
|
for _, outline := range outlines {
|
||||||
if outline.Type == "rss" {
|
if outline.Type == "rss" {
|
||||||
folder.Feeds = append(folder.Feeds, &Feed{
|
folder.Feeds = append(folder.Feeds, Feed{
|
||||||
Title: outline.Title,
|
Title: outline.Title,
|
||||||
FeedUrl: outline.FeedUrl,
|
FeedUrl: outline.FeedUrl,
|
||||||
SiteUrl: outline.SiteUrl,
|
SiteUrl: outline.SiteUrl,
|
||||||
@ -35,7 +35,7 @@ func buildFolder(title string, outlines []outline) *Folder {
|
|||||||
return folder
|
return folder
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(r io.Reader) (*Folder, error) {
|
func Parse(r io.Reader) (Folder, error) {
|
||||||
val := new(opml)
|
val := new(opml)
|
||||||
decoder := xml.NewDecoder(r)
|
decoder := xml.NewDecoder(r)
|
||||||
decoder.Entity = xml.HTMLEntity
|
decoder.Entity = xml.HTMLEntity
|
||||||
@ -43,7 +43,7 @@ func Parse(r io.Reader) (*Folder, error) {
|
|||||||
|
|
||||||
err := decoder.Decode(&val)
|
err := decoder.Decode(&val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return Folder{}, err
|
||||||
}
|
}
|
||||||
return buildFolder("", val.Outlines), nil
|
return buildFolder("", val.Outlines), nil
|
||||||
}
|
}
|
||||||
|
@ -24,31 +24,30 @@ func TestParse(t *testing.T) {
|
|||||||
</body>
|
</body>
|
||||||
</opml>
|
</opml>
|
||||||
`))
|
`))
|
||||||
want := &Folder{
|
want := Folder{
|
||||||
Title: "",
|
Title: "",
|
||||||
Feeds: []*Feed{
|
Feeds: []Feed{
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "title1",
|
Title: "title1",
|
||||||
FeedUrl: "https://baz.com/feed.xml",
|
FeedUrl: "https://baz.com/feed.xml",
|
||||||
SiteUrl: "https://baz.com/",
|
SiteUrl: "https://baz.com/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Folders: []*Folder{
|
Folders: []Folder{
|
||||||
&Folder{
|
Folder{
|
||||||
Title: "sub",
|
Title: "sub",
|
||||||
Feeds: []*Feed{
|
Feeds: []Feed{
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "subtitle1",
|
Title: "subtitle1",
|
||||||
FeedUrl: "https://foo.com/feed.xml",
|
FeedUrl: "https://foo.com/feed.xml",
|
||||||
SiteUrl: "https://foo.com/",
|
SiteUrl: "https://foo.com/",
|
||||||
},
|
},
|
||||||
&Feed{
|
Feed{
|
||||||
Title: "&>",
|
Title: "&>",
|
||||||
FeedUrl: "https://bar.com/feed.xml",
|
FeedUrl: "https://bar.com/feed.xml",
|
||||||
SiteUrl: "https://bar.com/",
|
SiteUrl: "https://bar.com/",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Folders: []*Folder{},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,18 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/nkanaev/yarr/src/assets"
|
|
||||||
"github.com/nkanaev/yarr/src/auth"
|
|
||||||
"github.com/nkanaev/yarr/src/router"
|
|
||||||
"github.com/nkanaev/yarr/src/storage"
|
|
||||||
"github.com/nkanaev/yarr/src/opml"
|
|
||||||
"github.com/nkanaev/yarr/src/worker"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/nkanaev/yarr/src/assets"
|
||||||
|
"github.com/nkanaev/yarr/src/auth"
|
||||||
|
"github.com/nkanaev/yarr/src/opml"
|
||||||
|
"github.com/nkanaev/yarr/src/router"
|
||||||
|
"github.com/nkanaev/yarr/src/storage"
|
||||||
|
"github.com/nkanaev/yarr/src/worker"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) handler() http.Handler {
|
func (s *Server) handler() http.Handler {
|
||||||
@ -331,14 +332,13 @@ func (s *Server) handleOPMLImport(c *router.Context) {
|
|||||||
c.Out.WriteHeader(http.StatusBadRequest)
|
c.Out.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range doc.Feeds {
|
for _, f := range doc.Feeds {
|
||||||
s.db.CreateFeed(f.Title, "", f.SiteUrl, f.FeedUrl, nil)
|
s.db.CreateFeed(f.Title, "", f.SiteUrl, f.FeedUrl, nil)
|
||||||
}
|
}
|
||||||
for _, f := range doc.Folders {
|
for _, f := range doc.Folders {
|
||||||
folder := s.db.CreateFolder(f.Title)
|
folder := s.db.CreateFolder(f.Title)
|
||||||
for _, ff := range f.AllFeeds() {
|
for _, ff := range f.AllFeeds() {
|
||||||
s.db.CreateFeed(f.Title, "", ff.SiteUrl, ff.FeedUrl, &folder.Id)
|
s.db.CreateFeed(ff.Title, "", ff.SiteUrl, ff.FeedUrl, &folder.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,13 +354,13 @@ func (s *Server) handleOPMLExport(c *router.Context) {
|
|||||||
c.Out.Header().Set("Content-Type", "application/xml; charset=utf-8")
|
c.Out.Header().Set("Content-Type", "application/xml; charset=utf-8")
|
||||||
c.Out.Header().Set("Content-Disposition", `attachment; filename="subscriptions.opml"`)
|
c.Out.Header().Set("Content-Disposition", `attachment; filename="subscriptions.opml"`)
|
||||||
|
|
||||||
doc := opml.NewFolder("")
|
doc := opml.Folder{}
|
||||||
|
|
||||||
feedsByFolderID := make(map[int64][]*storage.Feed)
|
feedsByFolderID := make(map[int64][]*storage.Feed)
|
||||||
for _, feed := range s.db.ListFeeds() {
|
for _, feed := range s.db.ListFeeds() {
|
||||||
feed := feed
|
feed := feed
|
||||||
if feed.FolderId == nil {
|
if feed.FolderId == nil {
|
||||||
doc.Feeds = append(doc.Feeds, &opml.Feed{
|
doc.Feeds = append(doc.Feeds, opml.Feed{
|
||||||
Title: feed.Title,
|
Title: feed.Title,
|
||||||
FeedUrl: feed.FeedLink,
|
FeedUrl: feed.FeedLink,
|
||||||
SiteUrl: feed.Link,
|
SiteUrl: feed.Link,
|
||||||
@ -376,14 +376,15 @@ func (s *Server) handleOPMLExport(c *router.Context) {
|
|||||||
if len(folderFeeds) == 0 {
|
if len(folderFeeds) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
opmlfolder := opml.NewFolder(folder.Title)
|
opmlfolder := opml.Folder{Title: folder.Title}
|
||||||
for _, feed := range folderFeeds {
|
for _, feed := range folderFeeds {
|
||||||
opmlfolder.Feeds = append(opmlfolder.Feeds, &opml.Feed{
|
opmlfolder.Feeds = append(opmlfolder.Feeds, opml.Feed{
|
||||||
Title: feed.Title,
|
Title: feed.Title,
|
||||||
FeedUrl: feed.FeedLink,
|
FeedUrl: feed.FeedLink,
|
||||||
SiteUrl: feed.Link,
|
SiteUrl: feed.Link,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
doc.Folders = append(doc.Folders, opmlfolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Out.Write([]byte(doc.OPML()))
|
c.Out.Write([]byte(doc.OPML()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user