mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Optional inclusion of feeds into an opml file (#114)
This commit is contained in:
@@ -71,6 +71,7 @@ vimeo = "{VIMEO_API_TOKEN}"
|
||||
# max_height = "720" # Optional maximal height of video, example: 720, 1080, 1440, 2160, ...
|
||||
# cron_schedule = "@every 12h" # Optional cron expression format. If set then overwrite 'update_period'. See details below
|
||||
# filters = { title = "regex for title here" } # Optional Golang regexp format. If set, then only download episodes with matching titles.
|
||||
# opml = true|false # Optional inclusion of the feed in the OPML file (default value: false)
|
||||
# clean = { keep_last = 10 } # Keep last 10 episodes (order desc by PubDate)
|
||||
```
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ func (u *Updater) Update(ctx context.Context, feedConfig *config.Feed) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := u.buildOPML(ctx, feedConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := u.cleanup(ctx, feedConfig); err != nil {
|
||||
log.WithError(err).Error("cleanup failed")
|
||||
}
|
||||
@@ -247,6 +251,27 @@ func (u *Updater) buildXML(ctx context.Context, feedConfig *config.Feed) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Updater) buildOPML(ctx context.Context, feedConfig *config.Feed) error {
|
||||
|
||||
// Build OPML with data received from builder
|
||||
log.Debug("building podcast OPML")
|
||||
opml, err := feed.BuildOPML(ctx, u.config, u.db, u.fs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
reader = bytes.NewReader([]byte(opml))
|
||||
xmlName = fmt.Sprintf("%s.opml", "podsync")
|
||||
)
|
||||
|
||||
if _, err := u.fs.Create(ctx, "", xmlName, reader); err != nil {
|
||||
return errors.Wrap(err, "failed to upload OPML")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Updater) cleanup(ctx context.Context, feedConfig *config.Feed) error {
|
||||
var (
|
||||
feedID = feedConfig.ID
|
||||
|
||||
@@ -42,6 +42,8 @@ type Feed struct {
|
||||
Clean Cleanup `toml:"clean"`
|
||||
// Custom is a list of feed customizations
|
||||
Custom Custom `toml:"custom"`
|
||||
// Included in OPML file
|
||||
OPML bool `toml:"opml"`
|
||||
}
|
||||
|
||||
type Custom struct {
|
||||
|
||||
67
pkg/feed/opml.go
Normal file
67
pkg/feed/opml.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/mxpv/podsync/pkg/config"
|
||||
"github.com/mxpv/podsync/pkg/db"
|
||||
"github.com/mxpv/podsync/pkg/fs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type opml struct {
|
||||
XMLName xml.Name `xml:"opml"`
|
||||
Version string `xml:"version,attr"`
|
||||
Head head
|
||||
Body body
|
||||
}
|
||||
|
||||
type head struct {
|
||||
XMLName xml.Name `xml:"head"`
|
||||
Title string `xml:"title"`
|
||||
}
|
||||
|
||||
type body struct {
|
||||
XMLName xml.Name `xml:"body"`
|
||||
Outlines []outline `xml:"outline"`
|
||||
}
|
||||
|
||||
type outline struct {
|
||||
Text string `xml:"text,attr"`
|
||||
Title string `xml:"title,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
XMLURL string `xml:"xmlUrl,attr"`
|
||||
}
|
||||
|
||||
func BuildOPML(ctx context.Context, config *config.Config, db db.Storage, fs fs.Storage) (string, error) {
|
||||
|
||||
ou := make([]outline, 0)
|
||||
|
||||
for _, feed := range config.Feeds {
|
||||
|
||||
f, err := db.GetFeed(ctx, feed.ID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if feed.OPML {
|
||||
downloadURL, err := fs.URL(ctx, "", fmt.Sprintf("%s.xml", feed.ID))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to: obtain download URL for feed")
|
||||
}
|
||||
ou = append(ou, outline{Title: f.Title, Text: f.Title, Type: "rss", XMLURL: downloadURL})
|
||||
}
|
||||
}
|
||||
|
||||
op := opml{Version: "1.0"}
|
||||
op.Head = head{Title: "PodSync feeds"}
|
||||
op.Body = body{Outlines: ou}
|
||||
|
||||
out, _ := xml.MarshalIndent(op, " ", " ")
|
||||
|
||||
return xml.Header + string(out), nil
|
||||
|
||||
}
|
||||
@@ -80,6 +80,10 @@ func (l *Local) URL(ctx context.Context, ns string, fileName string) (string, er
|
||||
return "", errors.Wrap(err, "failed to check whether file exists")
|
||||
}
|
||||
|
||||
if ns == "" {
|
||||
return fmt.Sprintf("%s/%s", l.hostname, fileName), nil
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/%s", l.hostname, ns, fileName), nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user