diff options
| author | AKP <tom@tdpain.net> | 2022-04-14 21:11:59 +0100 |
|---|---|---|
| committer | AKP <tom@tdpain.net> | 2022-04-14 21:11:59 +0100 |
| commit | 9318987a49b698819edc9641c4d19637beb2131e (patch) | |
| tree | 8c4673e5eb26a57f6b99cadacf5f4aea6b41b865 | |
| parent | 06515b424c23862cf82220d97cb1380366c2e6d9 (diff) | |
Add support for OPML export
Signed-off-by: AKP <tom@tdpain.net>
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -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 |
6 files changed, 101 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index cb49c46..f8af81a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +* Support for OPML exports ## [0.1.0] - 2022-04-14 Initial release 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" |
