| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
- // SPDX-License-Identifier: Apache-2.0
- package opml // import "miniflux.app/v2/internal/reader/opml"
- import (
- "encoding/xml"
- "fmt"
- "strconv"
- "strings"
- )
- const minifluxOPMLNamespace = "https://miniflux.app/opml"
- // Specs: http://opml.org/spec2.opml
- type opmlDocument struct {
- XMLName xml.Name `xml:"opml"`
- Version string `xml:"version,attr"`
- MinifluxNamespace string `xml:"xmlns:miniflux,attr,omitempty"`
- Header opmlHeader `xml:"head"`
- Outlines opmlOutlineCollection `xml:"body>outline"`
- }
- type opmlHeader struct {
- Title string `xml:"title,omitempty"`
- DateCreated string `xml:"dateCreated,omitempty"`
- OwnerName string `xml:"ownerName,omitempty"`
- }
- type opmlOutline struct {
- Title string `xml:"title,attr,omitempty"`
- Text string `xml:"text,attr"`
- FeedURL string `xml:"xmlUrl,attr,omitempty"`
- SiteURL string `xml:"htmlUrl,attr,omitempty"`
- Description string `xml:"description,attr,omitempty"`
- Outlines opmlOutlineCollection `xml:"outline,omitempty"`
- // Miniflux-specific feed settings
- ScraperRules string `xml:"miniflux:scraperRules,attr,omitempty"`
- RewriteRules string `xml:"miniflux:rewriteRules,attr,omitempty"`
- UrlRewriteRules string `xml:"miniflux:urlRewriteRules,attr,omitempty"`
- BlocklistRules string `xml:"miniflux:blocklistRules,attr,omitempty"`
- KeeplistRules string `xml:"miniflux:keeplistRules,attr,omitempty"`
- BlockFilterEntryRules string `xml:"miniflux:blockFilterEntryRules,attr,omitempty"`
- KeepFilterEntryRules string `xml:"miniflux:keepFilterEntryRules,attr,omitempty"`
- UserAgent string `xml:"miniflux:userAgent,attr,omitempty"`
- Crawler bool `xml:"miniflux:crawler,attr,omitempty"`
- IgnoreHTTPCache bool `xml:"miniflux:ignoreHTTPCache,attr,omitempty"`
- FetchViaProxy bool `xml:"miniflux:fetchViaProxy,attr,omitempty"`
- Disabled bool `xml:"miniflux:disabled,attr,omitempty"`
- NoMediaPlayer bool `xml:"miniflux:noMediaPlayer,attr,omitempty"`
- HideGlobally bool `xml:"miniflux:hideGlobally,attr,omitempty"`
- AllowSelfSignedCertificates bool `xml:"miniflux:allowSelfSignedCertificates,attr,omitempty"`
- DisableHTTP2 bool `xml:"miniflux:disableHTTP2,attr,omitempty"`
- IgnoreEntryUpdates bool `xml:"miniflux:ignoreEntryUpdates,attr,omitempty"`
- }
- func (o opmlOutline) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- type opmlOutlineXml opmlOutline
- outlineType := ""
- if o.IsSubscription() {
- outlineType = "rss"
- }
- return e.EncodeElement(struct {
- opmlOutlineXml
- Type string `xml:"type,attr,omitempty"`
- }{
- opmlOutlineXml: opmlOutlineXml(o),
- Type: outlineType,
- }, start)
- }
- func (o *opmlOutline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- *o = opmlOutline{}
- type opmlOutlineAlias opmlOutline
- if err := d.DecodeElement((*opmlOutlineAlias)(o), &start); err != nil {
- return err
- }
- for _, attr := range start.Attr {
- if attr.Name.Space == minifluxOPMLNamespace {
- if err := o.setMinifluxAttribute(attr.Name.Local, attr.Value); err != nil {
- return err
- }
- }
- }
- return nil
- }
- func (o opmlOutline) IsSubscription() bool {
- return strings.TrimSpace(o.FeedURL) != ""
- }
- func (o opmlOutline) GetTitle() string {
- if o.Title != "" {
- return o.Title
- }
- if o.Text != "" {
- return o.Text
- }
- if o.SiteURL != "" {
- return o.SiteURL
- }
- if o.FeedURL != "" {
- return o.FeedURL
- }
- return ""
- }
- func (o opmlOutline) GetSiteURL() string {
- if o.SiteURL != "" {
- return o.SiteURL
- }
- return o.FeedURL
- }
- type opmlOutlineCollection []opmlOutline
- func (o opmlOutlineCollection) HasChildren() bool {
- return len(o) > 0
- }
- func (o *opmlOutline) setMinifluxAttribute(name, value string) error {
- switch name {
- case "scraperRules":
- o.ScraperRules = value
- case "rewriteRules":
- o.RewriteRules = value
- case "urlRewriteRules":
- o.UrlRewriteRules = value
- case "blocklistRules":
- o.BlocklistRules = value
- case "keeplistRules":
- o.KeeplistRules = value
- case "blockFilterEntryRules":
- o.BlockFilterEntryRules = value
- case "keepFilterEntryRules":
- o.KeepFilterEntryRules = value
- case "userAgent":
- o.UserAgent = value
- case "crawler":
- return setMinifluxBoolAttribute(name, value, &o.Crawler)
- case "ignoreHTTPCache":
- return setMinifluxBoolAttribute(name, value, &o.IgnoreHTTPCache)
- case "fetchViaProxy":
- return setMinifluxBoolAttribute(name, value, &o.FetchViaProxy)
- case "disabled":
- return setMinifluxBoolAttribute(name, value, &o.Disabled)
- case "noMediaPlayer":
- return setMinifluxBoolAttribute(name, value, &o.NoMediaPlayer)
- case "hideGlobally":
- return setMinifluxBoolAttribute(name, value, &o.HideGlobally)
- case "allowSelfSignedCertificates":
- return setMinifluxBoolAttribute(name, value, &o.AllowSelfSignedCertificates)
- case "disableHTTP2":
- return setMinifluxBoolAttribute(name, value, &o.DisableHTTP2)
- case "ignoreEntryUpdates":
- return setMinifluxBoolAttribute(name, value, &o.IgnoreEntryUpdates)
- }
- return nil
- }
- func setMinifluxBoolAttribute(name, value string, target *bool) error {
- parsedValue, err := strconv.ParseBool(value)
- if err != nil {
- return fmt.Errorf("opml: invalid miniflux attribute %q: %w", name, err)
- }
- *target = parsedValue
- return nil
- }
|