diff options
Diffstat (limited to 'walrss/internal')
| -rw-r--r-- | walrss/internal/core/feeds.go | 13 | ||||
| -rw-r--r-- | walrss/internal/core/opml/opml.go | 60 | ||||
| -rw-r--r-- | walrss/internal/http/exportImport.go | 21 | ||||
| -rw-r--r-- | walrss/internal/http/http.go | 2 | ||||
| -rw-r--r-- | walrss/internal/urls/urls.go | 3 |
5 files changed, 99 insertions, 0 deletions
diff --git a/walrss/internal/core/feeds.go b/walrss/internal/core/feeds.go index c9e4022..3aefd4c 100644 --- a/walrss/internal/core/feeds.go +++ b/walrss/internal/core/feeds.go @@ -2,6 +2,7 @@ package core import ( "errors" + "github.com/codemicro/walrss/walrss/internal/core/opml" "github.com/codemicro/walrss/walrss/internal/db" "github.com/codemicro/walrss/walrss/internal/state" "github.com/lithammer/shortuuid/v4" @@ -74,3 +75,15 @@ func UpdateFeed(st *state.State, feed *db.Feed) error { } return nil } + +func ExportFeedsForUser(st *state.State, userID string) ([]byte, error) { + var feeds []*db.Feed + user, err := GetUserByID(st, userID) + if err != nil { + return nil, err + } + if err := st.Data.Find(&feeds, bh.Where("UserID").Eq(userID)); err != nil { + return nil, err + } + return opml.FromFeeds(feeds, user.Email).ToBytes() +} diff --git a/walrss/internal/core/opml/opml.go b/walrss/internal/core/opml/opml.go new file mode 100644 index 0000000..809a6b8 --- /dev/null +++ b/walrss/internal/core/opml/opml.go @@ -0,0 +1,60 @@ +package opml + +import ( + "encoding/xml" + "github.com/codemicro/walrss/walrss/internal/db" + "time" +) + +type OPML struct { + XMLName xml.Name `xml:"opml"` + Version string `xml:"version,attr"` + Head struct { + Title string `xml:"title"` + DateCreated time.Time `xml:"dateCreated,omitempty"` + OwnerEmail string `xml:"ownerEmail,omitempty"` + } `xml:"head"` + Body struct { + Outlines []*Outline `xml:"outline"` + } `xml:"body"` +} + +// Outline holds all information about an outline. +type Outline struct { + Outlines []*Outline `xml:"outline"` + Text string `xml:"text,attr"` + Title string `xml:"title,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + XMLURL string `xml:"xmlUrl,attr,omitempty"` +} + +func FromBytes(x []byte) (*OPML, error) { + o := new(OPML) + if err := xml.Unmarshal(x, o); err != nil { + return nil, err + } + return o, nil +} + +func (o *OPML) ToBytes() ([]byte, error) { + return xml.Marshal(o) +} + +func FromFeeds(feeds []*db.Feed, userEmailAddress string) *OPML { + o := new(OPML) + o.Version = "2.0" + o.Head.Title = "Walrss feed export" + o.Head.OwnerEmail = userEmailAddress + o.Head.DateCreated = time.Now().UTC() + + for _, feed := range feeds { + o.Body.Outlines = append(o.Body.Outlines, &Outline{ + Text: feed.Name, + Title: feed.Name, + Type: "rss", + XMLURL: feed.URL, + }) + } + + return o +} diff --git a/walrss/internal/http/exportImport.go b/walrss/internal/http/exportImport.go new file mode 100644 index 0000000..89b2ecf --- /dev/null +++ b/walrss/internal/http/exportImport.go @@ -0,0 +1,21 @@ +package http + +import ( + "github.com/codemicro/walrss/walrss/internal/core" + "github.com/gofiber/fiber/v2" +) + +func (s *Server) exportAsOPML(ctx *fiber.Ctx) error { + currentUserID := getCurrentUserID(ctx) + if currentUserID == "" { + return requestStandardSignIn(ctx) + } + + exported, err := core.ExportFeedsForUser(s.state, currentUserID) + if err != nil { + return err + } + + ctx.Set(fiber.HeaderContentType, "application/xml") + return ctx.Send(exported) +} diff --git a/walrss/internal/http/http.go b/walrss/internal/http/http.go index 72a8634..295a91f 100644 --- a/walrss/internal/http/http.go +++ b/walrss/internal/http/http.go @@ -91,6 +91,8 @@ func (s *Server) registerHandlers() { s.app.Post(urls.SendTestEmail, s.sendTestEmail) + s.app.Get(urls.ExportAsOPML, s.exportAsOPML) + s.app.Use(urls.Statics, static.NewHandler()) } diff --git a/walrss/internal/urls/urls.go b/walrss/internal/urls/urls.go index 2edcc2e..835bbc7 100644 --- a/walrss/internal/urls/urls.go +++ b/walrss/internal/urls/urls.go @@ -18,6 +18,9 @@ const ( EditFeedItem = Edit + "/feed/:id" CancelEditFeedItem = Edit + "/feed/:id/cancel" + Export = "/export" + ExportAsOPML = Export + "/opml" + New = "/new" NewFeedItem = New + "/feed" |
