{-# OPTIONS -fno-warn-incomplete-patterns #-}

--------------------------------------------------------------------
-- |
-- Module    : Text.Feed.Constructor
-- Copyright : (c) Galois, Inc. 2008,
--             (c) Sigbjorn Finne 2009-
-- License   : BSD3
--
-- Maintainer: Sigbjorn Finne <sof@forkIO.com>
-- Stability : provisional
-- Description: Module for an abstraction layer between different kinds of feeds.
--
--------------------------------------------------------------------
module Text.Feed.Constructor
  ( FeedKind(..)
  , newFeed -- :: FeedKind  -> Feed
  , feedFromRSS -- :: RSS       -> Feed
  , feedFromAtom -- :: Atom.Feed -> Feed
  , feedFromRDF -- :: RSS1.Feed -> Feed
  , feedFromXML -- :: Element   -> Feed
  , getFeedKind -- :: Feed      -> FeedKind
  , FeedSetter -- type _ a = a -> Feed -> Feed
  , addItem -- :: FeedSetter Item
  , withFeedTitle -- :: FeedSetter Text
  , withFeedHome -- :: FeedSetter URLString
  , withFeedHTML -- :: FeedSetter URLString
  , withFeedDescription -- :: FeedSetter Text
  , withFeedPubDate -- :: FeedSetter DateString
  , withFeedLastUpdate -- :: FeedSetter DateString
  , withFeedDate -- :: FeedSetter DateString
  , withFeedLogoLink -- :: FeedSetter URLString
  , withFeedLanguage -- :: FeedSetter Text
  , withFeedCategories -- :: FeedSetter [(Text, Maybe Text)]
  , withFeedGenerator -- :: FeedSetter Text
  , withFeedItems -- :: FeedSetter [Item]
  , newItem -- :: FeedKind   -> Item
  , getItemKind -- :: Item       -> FeedKind
  , atomEntryToItem -- :: Atom.Entry -> Item
  , rssItemToItem -- :: RSS.Item   -> Item
  , rdfItemToItem -- :: RSS1.Item  -> Item
  , ItemSetter -- type _ a = a -> Item -> Item
  , withItemTitle -- :: ItemSetter Text
  , withItemLink -- :: ItemSetter URLString
  , withItemPubDate -- :: ItemSetter DateString
  , withItemDate -- :: ItemSetter DateString
  , withItemAuthor -- :: ItemSetter Text
  , withItemCommentLink -- :: ItemSetter Text
  , withItemEnclosure -- :: Text -> Maybe Text -> ItemSetter Integer
  , withItemFeedLink -- :: Text -> ItemSetter Text
  , withItemId -- :: Bool   -> ItemSetter Text
  , withItemCategories -- :: ItemSetter [(Text, Maybe Text)]
  , withItemDescription -- :: ItemSetter Text
  , withItemRights -- :: ItemSetter Text
  ) where

import Prelude.Compat

import Text.Feed.Types as Feed.Types

import Text.Atom.Feed as Atom
import Text.DublinCore.Types
import Text.RSS.Syntax as RSS
import Text.RSS1.Syntax as RSS1

import Data.XML.Compat
import Data.XML.Types as XML

import Data.Char (toLower)
import Data.Maybe (fromMaybe, mapMaybe)
import Data.Text (Text, pack)

-- ToDo:
--
--  - complete set of constructors over feeds
--  - provide a unified treatment of date string reps.
--    (i.e., I know they differ across formats, but ignorant what
--    the constraints are at the moment.)
-- | Construct an empty feed document, intending to output it in
-- the 'fk' feed format.
newFeed :: FeedKind -> Feed.Types.Feed
newFeed :: FeedKind -> Feed
newFeed fk :: FeedKind
fk =
  case FeedKind
fk of
    AtomKind ->
      Feed -> Feed
AtomFeed
        (URI -> TextContent -> URI -> Feed
Atom.nullFeed
           "feed-id-not-filled-in"
           (URI -> TextContent
TextString "dummy-title")
           "dummy-and-bogus-update-date")
    RSSKind mbV :: Maybe URI
mbV ->
      let def :: RSS
def = URI -> URI -> RSS
RSS.nullRSS "dummy-title" "default-channel-url"
       in RSS -> Feed
RSSFeed (RSS -> Feed) -> RSS -> Feed
forall a b. (a -> b) -> a -> b
$ RSS -> (URI -> RSS) -> Maybe URI -> RSS
forall b a. b -> (a -> b) -> Maybe a -> b
maybe RSS
def (\v :: URI
v -> RSS
def {rssVersion :: URI
RSS.rssVersion = URI
v}) Maybe URI
mbV
    RDFKind mbV :: Maybe URI
mbV ->
      let def :: Feed
def = URI -> URI -> Feed
RSS1.nullFeed "default-channel-url" "dummy-title"
       in Feed -> Feed
RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$ Feed -> (URI -> Feed) -> Maybe URI -> Feed
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Feed
def (\v :: URI
v -> Feed
def {feedVersion :: URI
RSS1.feedVersion = URI
v}) Maybe URI
mbV

feedFromRSS :: RSS.RSS -> Feed.Types.Feed
feedFromRSS :: RSS -> Feed
feedFromRSS = RSS -> Feed
RSSFeed

feedFromAtom :: Atom.Feed -> Feed.Types.Feed
feedFromAtom :: Feed -> Feed
feedFromAtom = Feed -> Feed
AtomFeed

feedFromRDF :: RSS1.Feed -> Feed.Types.Feed
feedFromRDF :: Feed -> Feed
feedFromRDF = Feed -> Feed
RSS1Feed

feedFromXML :: XML.Element -> Feed.Types.Feed
feedFromXML :: Element -> Feed
feedFromXML = Element -> Feed
XMLFeed

getFeedKind :: Feed.Types.Feed -> FeedKind
getFeedKind :: Feed -> FeedKind
getFeedKind f :: Feed
f =
  case Feed
f of
    Feed.Types.AtomFeed {} -> FeedKind
AtomKind
    Feed.Types.RSSFeed r :: RSS
r ->
      Maybe URI -> FeedKind
RSSKind
        (case RSS -> URI
RSS.rssVersion RSS
r of
           "2.0" -> Maybe URI
forall a. Maybe a
Nothing
           v :: URI
v -> URI -> Maybe URI
forall a. a -> Maybe a
Just URI
v)
    Feed.Types.RSS1Feed r :: Feed
r ->
      Maybe URI -> FeedKind
RDFKind
        (case Feed -> URI
RSS1.feedVersion Feed
r of
           "1.0" -> Maybe URI
forall a. Maybe a
Nothing
           v :: URI
v -> URI -> Maybe URI
forall a. a -> Maybe a
Just URI
v)
    Feed.Types.XMLFeed {} -> Maybe URI -> FeedKind
RSSKind (URI -> Maybe URI
forall a. a -> Maybe a
Just "2.0") -- for now, just a hunch..

addItem :: Feed.Types.Item -> Feed.Types.Feed -> Feed.Types.Feed
addItem :: Item -> Feed -> Feed
addItem it :: Item
it f :: Feed
f =
  case (Item
it, Feed
f) of
    (Feed.Types.AtomItem e :: Entry
e, Feed.Types.AtomFeed fe :: Feed
fe) ->
      Feed -> Feed
Feed.Types.AtomFeed Feed
fe {feedEntries :: [Entry]
Atom.feedEntries = Entry
e Entry -> [Entry] -> [Entry]
forall a. a -> [a] -> [a]
: Feed -> [Entry]
Atom.feedEntries Feed
fe}
    (Feed.Types.RSSItem e :: RSSItem
e, Feed.Types.RSSFeed r :: RSS
r) ->
      RSS -> Feed
Feed.Types.RSSFeed
        RSS
r {rssChannel :: RSSChannel
RSS.rssChannel = (RSS -> RSSChannel
RSS.rssChannel RSS
r) {rssItems :: [RSSItem]
RSS.rssItems = RSSItem
e RSSItem -> [RSSItem] -> [RSSItem]
forall a. a -> [a] -> [a]
: RSSChannel -> [RSSItem]
RSS.rssItems (RSS -> RSSChannel
RSS.rssChannel RSS
r)}}
    (Feed.Types.RSS1Item e :: Item
e, Feed.Types.RSS1Feed r :: Feed
r)
         -- note: do not update the channel item URIs at this point;
         -- will delay doing so until serialization.
     -> Feed -> Feed
Feed.Types.RSS1Feed Feed
r {feedItems :: [Item]
RSS1.feedItems = Item
e Item -> [Item] -> [Item]
forall a. a -> [a] -> [a]
: Feed -> [Item]
RSS1.feedItems Feed
r}
    _ ->
      [Char] -> Feed
forall a. HasCallStack => [Char] -> a
error "addItem: currently unable to automatically convert items from one feed type to another"

withFeedItems :: FeedSetter [Feed.Types.Item]
withFeedItems :: FeedSetter [Item]
withFeedItems is :: [Item]
is fe :: Feed
fe =
  (Item -> Feed -> Feed) -> Feed -> [Item] -> Feed
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
    Item -> Feed -> Feed
addItem
    (case Feed
fe of
       Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedEntries :: [Entry]
Atom.feedEntries = []}
       Feed.Types.RSSFeed f :: RSS
f -> RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssItems :: [RSSItem]
rssItems = []}}
       Feed.Types.RSS1Feed f :: Feed
f -> Feed -> Feed
Feed.Types.RSS1Feed Feed
f {feedItems :: [Item]
feedItems = []})
    [Item]
is

newItem :: FeedKind -> Feed.Types.Item
newItem :: FeedKind -> Item
newItem fk :: FeedKind
fk =
  case FeedKind
fk of
    AtomKind ->
      Entry -> Item
Feed.Types.AtomItem (Entry -> Item) -> Entry -> Item
forall a b. (a -> b) -> a -> b
$
      URI -> TextContent -> URI -> Entry
Atom.nullEntry
        "entry-id-not-filled-in"
        (URI -> TextContent
TextString "dummy-entry-title")
        "dummy-and-bogus-entry-update-date"
    RSSKind {} -> RSSItem -> Item
Feed.Types.RSSItem (RSSItem -> Item) -> RSSItem -> Item
forall a b. (a -> b) -> a -> b
$ URI -> RSSItem
RSS.nullItem "dummy-rss-item-title"
    RDFKind {} ->
      Item -> Item
Feed.Types.RSS1Item (Item -> Item) -> Item -> Item
forall a b. (a -> b) -> a -> b
$ URI -> URI -> URI -> Item
RSS1.nullItem "dummy-item-uri" "dummy-item-title" "dummy-item-link"

getItemKind :: Feed.Types.Item -> FeedKind
getItemKind :: Item -> FeedKind
getItemKind f :: Item
f =
  case Item
f of
    Feed.Types.AtomItem {} -> FeedKind
AtomKind
    Feed.Types.RSSItem {} -> Maybe URI -> FeedKind
RSSKind (URI -> Maybe URI
forall a. a -> Maybe a
Just "2.0") -- good guess..
    Feed.Types.RSS1Item {} -> Maybe URI -> FeedKind
RDFKind (URI -> Maybe URI
forall a. a -> Maybe a
Just "1.0")
    Feed.Types.XMLItem {} -> Maybe URI -> FeedKind
RSSKind (URI -> Maybe URI
forall a. a -> Maybe a
Just "2.0")

type FeedSetter a = a -> Feed.Types.Feed -> Feed.Types.Feed

withFeedTitle :: FeedSetter Text
withFeedTitle :: FeedSetter URI
withFeedTitle tit :: URI
tit fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedTitle :: TextContent
feedTitle = URI -> TextContent
TextString URI
tit}
    Feed.Types.RSSFeed f :: RSS
f -> RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssTitle :: URI
rssTitle = URI
tit}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed Feed
f {feedChannel :: Channel
feedChannel = (Feed -> Channel
feedChannel Feed
f) {channelTitle :: URI
channelTitle = URI
tit}}
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "title"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "title" URI
tit)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f

withFeedHome :: FeedSetter URLString
withFeedHome :: FeedSetter URI
withFeedHome url :: URI
url fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedLinks :: [Link]
feedLinks = Link
newSelf Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: Feed -> [Link]
Atom.feedLinks Feed
f}
      -- ToDo: fix, the <link> element is for the HTML home of the channel, not the
      -- location of the feed itself. Struggling to find if there is a common way
      -- to represent this outside of RSS 2.0 standard elements..
    Feed.Types.RSSFeed f :: RSS
f -> RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssLink :: URI
rssLink = URI
url}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed Feed
f {feedChannel :: Channel
feedChannel = (Feed -> Channel
feedChannel Feed
f) {channelURI :: URI
channelURI = URI
url}}
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "link"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "link" URI
url)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    newSelf :: Link
newSelf = (URI -> Link
nullLink URI
url) {linkRel :: Maybe (Either URI URI)
linkRel = Either URI URI -> Maybe (Either URI URI)
forall a. a -> Maybe a
Just (URI -> Either URI URI
forall a b. a -> Either a b
Left "self"), linkType :: Maybe URI
linkType = URI -> Maybe URI
forall a. a -> Maybe a
Just "application/atom+xml"}

-- | 'withFeedHTML' sets the URL where an HTML version of the
-- feed is published.
withFeedHTML :: FeedSetter URLString
withFeedHTML :: FeedSetter URI
withFeedHTML url :: URI
url fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedLinks :: [Link]
feedLinks = Link
newAlt Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: Feed -> [Link]
Atom.feedLinks Feed
f}
    Feed.Types.RSSFeed f :: RSS
f -> RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssLink :: URI
rssLink = URI
url}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed Feed
f {feedChannel :: Channel
feedChannel = (Feed -> Channel
feedChannel Feed
f) {channelLink :: URI
channelLink = URI
url}}
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "link"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "link" URI
url)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    newAlt :: Link
newAlt = (URI -> Link
nullLink URI
url) {linkRel :: Maybe (Either URI URI)
linkRel = Either URI URI -> Maybe (Either URI URI)
forall a. a -> Maybe a
Just (URI -> Either URI URI
forall a b. a -> Either a b
Left "alternate"), linkType :: Maybe URI
linkType = URI -> Maybe URI
forall a. a -> Maybe a
Just "text/html"}

-- | 'withFeedHTML' sets the URL where an HTML version of the
-- feed is published.
withFeedDescription :: FeedSetter Text
withFeedDescription :: FeedSetter URI
withFeedDescription desc :: URI
desc fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedSubtitle :: Maybe TextContent
feedSubtitle = TextContent -> Maybe TextContent
forall a. a -> Maybe a
Just (URI -> TextContent
TextString URI
desc)}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssDescription :: URI
rssDescription = URI
desc}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed Feed
f {feedChannel :: Channel
feedChannel = (Feed -> Channel
feedChannel Feed
f) {channelDesc :: URI
channelDesc = URI
desc}}
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "description"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "description" URI
desc)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f

withFeedPubDate :: FeedSetter Text
withFeedPubDate :: FeedSetter URI
withFeedPubDate dateStr :: URI
dateStr fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedUpdated :: URI
feedUpdated = URI
dateStr}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssPubDate :: Maybe URI
rssPubDate = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
dateStr}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isDate ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f) of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f) {channelDC :: [DCItem]
RSS1.channelDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
dateStr} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
            }
        (_, []) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f)
                  { channelDC :: [DCItem]
RSS1.channelDC =
                      DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Date, dcText :: URI
dcText = URI
dateStr} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
:
                      Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f)
                  }
            }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "pubDate"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "pubDate" URI
dateStr)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    isDate :: DCItem -> Bool
isDate dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Date

withFeedLastUpdate :: FeedSetter DateString
withFeedLastUpdate :: FeedSetter URI
withFeedLastUpdate dateStr :: URI
dateStr fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedUpdated :: URI
feedUpdated = URI
dateStr}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssLastUpdate :: Maybe URI
rssLastUpdate = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
dateStr}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isDate ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f) of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f) {channelDC :: [DCItem]
RSS1.channelDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
dateStr} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
            }
        (_, []) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f)
                  { channelDC :: [DCItem]
RSS1.channelDC =
                      DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Date, dcText :: URI
dcText = URI
dateStr} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
:
                      Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f)
                  }
            }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "lastUpdate"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "lastUpdate" URI
dateStr)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    isDate :: DCItem -> Bool
isDate dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Date

-- | 'withFeedDate dt' is the composition of 'withFeedPubDate'
-- and 'withFeedLastUpdate', setting both publication date and
-- last update date to 'dt'. Notice that RSS2.0 is the only format
-- supporting both pub and last-update.
withFeedDate :: FeedSetter DateString
withFeedDate :: FeedSetter URI
withFeedDate dt :: URI
dt f :: Feed
f = FeedSetter URI
withFeedPubDate URI
dt (FeedSetter URI
withFeedLastUpdate URI
dt Feed
f)

withFeedLogoLink :: URLString -> FeedSetter URLString
withFeedLogoLink :: URI -> FeedSetter URI
withFeedLogoLink imgURL :: URI
imgURL lnk :: URI
lnk fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f ->
      Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedLogo :: Maybe URI
feedLogo = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
imgURL, feedLinks :: [Link]
feedLinks = Link
newSelf Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: Feed -> [Link]
Atom.feedLinks Feed
f}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed
        RSS
f
          { rssChannel :: RSSChannel
rssChannel =
              (RSS -> RSSChannel
rssChannel RSS
f) {rssImage :: Maybe RSSImage
rssImage = RSSImage -> Maybe RSSImage
forall a. a -> Maybe a
Just (RSSImage -> Maybe RSSImage) -> RSSImage -> Maybe RSSImage
forall a b. (a -> b) -> a -> b
$ URI -> URI -> URI -> RSSImage
RSS.nullImage URI
imgURL (RSSChannel -> URI
rssTitle (RSS -> RSSChannel
rssChannel RSS
f)) URI
lnk}
          }
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      Feed
f
        { feedImage :: Maybe Image
feedImage = Image -> Maybe Image
forall a. a -> Maybe a
Just (Image -> Maybe Image) -> Image -> Maybe Image
forall a b. (a -> b) -> a -> b
$ URI -> URI -> URI -> Image
RSS1.nullImage URI
imgURL (Channel -> URI
RSS1.channelTitle (Feed -> Channel
RSS1.feedChannel Feed
f)) URI
lnk
        , feedChannel :: Channel
feedChannel = (Feed -> Channel
feedChannel Feed
f) {channelImageURI :: Maybe URI
channelImageURI = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
imgURL}
        }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "image"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just
                                   (Name -> [Element] -> Element
forall t. ToNode t => Name -> t -> Element
unode
                                      "image"
                                      [Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "url" URI
imgURL, Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "title" URI
title, Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "link" URI
lnk])
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
      where title :: URI
title =
              case (Element -> Maybe Element)
-> Maybe Element -> Maybe (Maybe Element)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Name -> Element -> Maybe Element
findChild "title") (Name -> Element -> Maybe Element
findChild "channel" Element
f) of
                Just (Just e1 :: Element
e1) -> Element -> URI
strContent Element
e1
                _ -> "feed_title" -- shouldn't happen..
  where
    newSelf :: Link
newSelf = (URI -> Link
nullLink URI
lnk) {linkRel :: Maybe (Either URI URI)
linkRel = Either URI URI -> Maybe (Either URI URI)
forall a. a -> Maybe a
Just (URI -> Either URI URI
forall a b. a -> Either a b
Left "self"), linkType :: Maybe URI
linkType = URI -> Maybe URI
forall a. a -> Maybe a
Just "application/atom+xml"}

withFeedLanguage :: FeedSetter Text
withFeedLanguage :: FeedSetter URI
withFeedLanguage lang :: URI
lang fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f -> Feed -> Feed
Feed.Types.AtomFeed Feed
f {feedAttrs :: [Attr]
Atom.feedAttrs = Attr
langAttr Attr -> [Attr] -> [Attr]
forall a. a -> [a] -> [a]
: Feed -> [Attr]
Atom.feedAttrs Feed
f}
      where langAttr :: Attr
langAttr = (Name
name, [URI -> Content
ContentText URI
lang])
            name :: Name
name = Name :: URI -> Maybe URI -> Maybe URI -> Name
Name {nameLocalName :: URI
nameLocalName = "lang", nameNamespace :: Maybe URI
nameNamespace = Maybe URI
forall a. Maybe a
Nothing, namePrefix :: Maybe URI
namePrefix = URI -> Maybe URI
forall a. a -> Maybe a
Just "xml"}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssLanguage :: Maybe URI
rssLanguage = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
lang}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isLang ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f) of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f) {channelDC :: [DCItem]
RSS1.channelDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
lang} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
            }
        (_, []) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f)
                  { channelDC :: [DCItem]
RSS1.channelDC =
                      DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Language, dcText :: URI
dcText = URI
lang} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
:
                      Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f)
                  }
            }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "language"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "language" URI
lang)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    isLang :: DCItem -> Bool
isLang dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Language

withFeedCategories :: FeedSetter [(Text, Maybe Text)]
withFeedCategories :: FeedSetter [(URI, Maybe URI)]
withFeedCategories cats :: [(URI, Maybe URI)]
cats fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f ->
      Feed -> Feed
Feed.Types.AtomFeed
        Feed
f
          { feedCategories :: [Category]
Atom.feedCategories =
              ((URI, Maybe URI) -> Category) -> [(URI, Maybe URI)] -> [Category]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, mb :: Maybe URI
mb) -> (URI -> Category
Atom.newCategory URI
t) {catScheme :: Maybe URI
Atom.catScheme = Maybe URI
mb}) [(URI, Maybe URI)]
cats [Category] -> [Category] -> [Category]
forall a. [a] -> [a] -> [a]
++ Feed -> [Category]
feedCategories Feed
f
          }
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed
        RSS
f
          { rssChannel :: RSSChannel
rssChannel =
              (RSS -> RSSChannel
rssChannel RSS
f)
                { rssCategories :: [RSSCategory]
RSS.rssCategories =
                    ((URI, Maybe URI) -> RSSCategory)
-> [(URI, Maybe URI)] -> [RSSCategory]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, mb :: Maybe URI
mb) -> (URI -> RSSCategory
RSS.newCategory URI
t) {rssCategoryDomain :: Maybe URI
RSS.rssCategoryDomain = Maybe URI
mb}) [(URI, Maybe URI)]
cats [RSSCategory] -> [RSSCategory] -> [RSSCategory]
forall a. [a] -> [a] -> [a]
++
                    RSSChannel -> [RSSCategory]
RSS.rssCategories (RSS -> RSSChannel
rssChannel RSS
f)
                }
          }
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed
        Feed
f
          { feedChannel :: Channel
feedChannel =
              (Feed -> Channel
feedChannel Feed
f)
                { channelDC :: [DCItem]
RSS1.channelDC =
                    ((URI, Maybe URI) -> DCItem) -> [(URI, Maybe URI)] -> [DCItem]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, _) -> DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Subject, dcText :: URI
dcText = URI
t}) [(URI, Maybe URI)]
cats [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++
                    Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
feedChannel Feed
f)
                }
          }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    (((URI, Maybe URI) -> Element -> Element)
-> Element -> [(URI, Maybe URI)] -> Element
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
                       (\(t :: URI
t, mb :: Maybe URI
mb) acc :: Element
acc ->
                          Element -> Element -> Element
addChild
                            (Name -> [Attr] -> Element
forall t. ToNode t => Name -> t -> Element
unode
                               "category"
                               ((Attr -> [Attr])
-> (URI -> Attr -> [Attr]) -> Maybe URI -> Attr -> [Attr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Attr -> [Attr] -> [Attr]
forall a. a -> [a] -> [a]
: []) (\v :: URI
v x :: Attr
x -> [URI -> URI -> Attr
mkAttr "domain" URI
v, Attr
x]) Maybe URI
mb (URI -> URI -> Attr
mkAttr "term" URI
t)))
                            Element
acc)
                       Element
e
                       [(URI, Maybe URI)]
cats)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f

withFeedGenerator :: FeedSetter (Text, Maybe URLString)
withFeedGenerator :: FeedSetter (URI, Maybe URI)
withFeedGenerator (gen :: URI
gen, mbURI :: Maybe URI
mbURI) fe :: Feed
fe =
  case Feed
fe of
    Feed.Types.AtomFeed f :: Feed
f ->
      Feed -> Feed
Feed.Types.AtomFeed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      Feed
f {feedGenerator :: Maybe Generator
Atom.feedGenerator = Generator -> Maybe Generator
forall a. a -> Maybe a
Just ((URI -> Generator
Atom.nullGenerator URI
gen) {genURI :: Maybe URI
Atom.genURI = Maybe URI
mbURI})}
    Feed.Types.RSSFeed f :: RSS
f ->
      RSS -> Feed
Feed.Types.RSSFeed RSS
f {rssChannel :: RSSChannel
rssChannel = (RSS -> RSSChannel
rssChannel RSS
f) {rssGenerator :: Maybe URI
rssGenerator = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
gen}}
    Feed.Types.RSS1Feed f :: Feed
f ->
      Feed -> Feed
Feed.Types.RSS1Feed (Feed -> Feed) -> Feed -> Feed
forall a b. (a -> b) -> a -> b
$
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isSource ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f) of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f) {channelDC :: [DCItem]
RSS1.channelDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
gen} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
            }
        (_, []) ->
          Feed
f
            { feedChannel :: Channel
RSS1.feedChannel =
                (Feed -> Channel
RSS1.feedChannel Feed
f)
                  { channelDC :: [DCItem]
RSS1.channelDC =
                      DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Source, dcText :: URI
dcText = URI
gen} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Channel -> [DCItem]
RSS1.channelDC (Feed -> Channel
RSS1.feedChannel Feed
f)
                  }
            }
    Feed.Types.XMLFeed f :: Element
f ->
      Element -> Feed
Feed.Types.XMLFeed (Element -> Feed) -> Element -> Feed
forall a b. (a -> b) -> a -> b
$
      (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
        (\e :: Element
e ->
           if Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "channel"
             then Element -> Maybe Element
forall a. a -> Maybe a
Just
                    ((Element -> Maybe Element) -> Element -> Element
mapMaybeChildren
                       (\e2 :: Element
e2 ->
                          if Element -> Name
elementName Element
e2 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== "generator"
                            then Element -> Maybe Element
forall a. a -> Maybe a
Just (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "generator" URI
gen)
                            else Maybe Element
forall a. Maybe a
Nothing)
                       Element
e)
             else Maybe Element
forall a. Maybe a
Nothing)
        Element
f
  where
    isSource :: DCItem -> Bool
isSource dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Source

-- Item constructors (all the way to the end):
atomEntryToItem :: Atom.Entry -> Feed.Types.Item
atomEntryToItem :: Entry -> Item
atomEntryToItem = Entry -> Item
Feed.Types.AtomItem

rssItemToItem :: RSS.RSSItem -> Feed.Types.Item
rssItemToItem :: RSSItem -> Item
rssItemToItem = RSSItem -> Item
Feed.Types.RSSItem

rdfItemToItem :: RSS1.Item -> Feed.Types.Item
rdfItemToItem :: Item -> Item
rdfItemToItem = Item -> Item
Feed.Types.RSS1Item

type ItemSetter a = a -> Feed.Types.Item -> Feed.Types.Item

-- | 'withItemPubDate dt' associates the creation\/ publication date 'dt'
-- with a feed item.
withItemPubDate :: ItemSetter DateString
withItemPubDate :: ItemSetter URI
withItemPubDate dt :: URI
dt fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e -> Entry -> Item
Feed.Types.AtomItem Entry
e {entryUpdated :: URI
Atom.entryUpdated = URI
dt}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemPubDate :: Maybe URI
RSS.rssItemPubDate = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
dt}
    Feed.Types.RSS1Item i :: Item
i ->
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isDate ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Item -> [DCItem]
RSS1.itemDC Item
i of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDC :: [DCItem]
RSS1.itemDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
dt} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
        (_, []) ->
          Item -> Item
Feed.Types.RSS1Item
            Item
i {itemDC :: [DCItem]
RSS1.itemDC = DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Date, dcText :: URI
dcText = URI
dt} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Item -> [DCItem]
RSS1.itemDC Item
i}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "pubDate" URI
dt) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "pubDate") Element
i
  where
    isDate :: DCItem -> Bool
isDate dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Date

-- | 'withItemDate' is a synonym for 'withItemPubDate'.
withItemDate :: ItemSetter DateString
withItemDate :: ItemSetter URI
withItemDate = ItemSetter URI
withItemPubDate

-- | 'withItemTitle myTitle' associates a new title, 'myTitle',
-- with a feed item.
withItemTitle :: ItemSetter Text
withItemTitle :: ItemSetter URI
withItemTitle tit :: URI
tit fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e -> Entry -> Item
Feed.Types.AtomItem Entry
e {entryTitle :: TextContent
Atom.entryTitle = URI -> TextContent
TextString URI
tit}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemTitle :: Maybe URI
RSS.rssItemTitle = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
tit}
    Feed.Types.RSS1Item i :: Item
i -> Item -> Item
Feed.Types.RSS1Item Item
i {itemTitle :: URI
RSS1.itemTitle = URI
tit}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "title" URI
tit) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "title") Element
i

-- | 'withItemAuthor auStr' associates new author info
-- with a feed item.
withItemAuthor :: ItemSetter Text
withItemAuthor :: ItemSetter URI
withItemAuthor au :: URI
au fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem
        Entry
e {entryAuthors :: [Person]
Atom.entryAuthors = [Person
nullPerson {personName :: URI
personName = URI
au, personURI :: Maybe URI
personURI = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
au}]}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemAuthor :: Maybe URI
RSS.rssItemAuthor = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
au}
    Feed.Types.RSS1Item i :: Item
i ->
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isAuthor ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Item -> [DCItem]
RSS1.itemDC Item
i of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDC :: [DCItem]
RSS1.itemDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
au} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
        (_, []) ->
          Item -> Item
Feed.Types.RSS1Item
            Item
i {itemDC :: [DCItem]
RSS1.itemDC = DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Creator, dcText :: URI
dcText = URI
au} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Item -> [DCItem]
RSS1.itemDC Item
i}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "author" URI
au) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "author") Element
i
  where
    isAuthor :: DCItem -> Bool
isAuthor dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Creator

-- | 'withItemFeedLink name myFeed' associates the parent feed URL 'myFeed'
-- with a feed item. It is labelled as 'name'.
withItemFeedLink :: Text -> ItemSetter Text
withItemFeedLink :: URI -> ItemSetter URI
withItemFeedLink tit :: URI
tit url :: URI
url fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem
        Entry
e
          { entrySource :: Maybe Source
Atom.entrySource =
              Source -> Maybe Source
forall a. a -> Maybe a
Just Source
Atom.nullSource {sourceId :: Maybe URI
sourceId = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
url, sourceTitle :: Maybe TextContent
sourceTitle = TextContent -> Maybe TextContent
forall a. a -> Maybe a
Just (URI -> TextContent
TextString URI
tit)}
          }
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemSource :: Maybe RSSSource
RSS.rssItemSource = RSSSource -> Maybe RSSSource
forall a. a -> Maybe a
Just (URI -> URI -> RSSSource
RSS.nullSource URI
url URI
tit)}
    Feed.Types.RSS1Item i :: Item
i -> Item -> Item
Feed.Types.RSS1Item Item
i {itemTitle :: URI
RSS1.itemTitle = URI
tit}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> ([Attr], URI) -> Element
forall t. ToNode t => Name -> t -> Element
unode "source" ([URI -> URI -> Attr
mkAttr "url" URI
url], URI
tit)) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
      (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "source") Element
i

-- | 'withItemCommentLink url' sets the URL reference to the comment page to 'url'.
withItemCommentLink :: ItemSetter Text
withItemCommentLink :: ItemSetter URI
withItemCommentLink url :: URI
url fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem
        Entry
e {entryLinks :: [Link]
Atom.entryLinks = ((URI -> Link
nullLink URI
url) {linkRel :: Maybe (Either URI URI)
linkRel = Either URI URI -> Maybe (Either URI URI)
forall a. a -> Maybe a
Just (URI -> Either URI URI
forall a b. a -> Either a b
Left "replies")}) Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: Entry -> [Link]
Atom.entryLinks Entry
e}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemComments :: Maybe URI
RSS.rssItemComments = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
url}
    Feed.Types.RSS1Item i :: Item
i ->
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isRel ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Item -> [DCItem]
RSS1.itemDC Item
i of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDC :: [DCItem]
RSS1.itemDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
url} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
        (_, []) ->
          Item -> Item
Feed.Types.RSS1Item
            Item
i {itemDC :: [DCItem]
RSS1.itemDC = DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Relation, dcText :: URI
dcText = URI
url} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Item -> [DCItem]
RSS1.itemDC Item
i}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "comments" URI
url) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "comments") Element
i
  where
    isRel :: DCItem -> Bool
isRel dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Relation

-- | 'withItemEnclosure url mbTy len' sets the URL reference to the comment page to 'url'.
withItemEnclosure :: Text -> Maybe Text -> ItemSetter (Maybe Integer)
withItemEnclosure :: URI -> Maybe URI -> ItemSetter (Maybe Integer)
withItemEnclosure url :: URI
url ty :: Maybe URI
ty mb_len :: Maybe Integer
mb_len fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem
        Entry
e
          { entryLinks :: [Link]
Atom.entryLinks =
              ((URI -> Link
nullLink URI
url)
                 { linkRel :: Maybe (Either URI URI)
linkRel = Either URI URI -> Maybe (Either URI URI)
forall a. a -> Maybe a
Just (URI -> Either URI URI
forall a b. a -> Either a b
Left "enclosure")
                 , linkType :: Maybe URI
linkType = Maybe URI
ty
                 , linkLength :: Maybe URI
linkLength = (Integer -> URI) -> Maybe Integer -> Maybe URI
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Char] -> URI
pack ([Char] -> URI) -> (Integer -> [Char]) -> Integer -> URI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> [Char]
forall a. Show a => a -> [Char]
show) Maybe Integer
mb_len
                 }) Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
:
              Entry -> [Link]
Atom.entryLinks Entry
e
          }
    Feed.Types.RSSItem i :: RSSItem
i ->
      RSSItem -> Item
Feed.Types.RSSItem
        RSSItem
i {rssItemEnclosure :: Maybe RSSEnclosure
RSS.rssItemEnclosure = RSSEnclosure -> Maybe RSSEnclosure
forall a. a -> Maybe a
Just (URI -> Maybe Integer -> URI -> RSSEnclosure
nullEnclosure URI
url Maybe Integer
mb_len (URI -> Maybe URI -> URI
forall a. a -> Maybe a -> a
fromMaybe "text/html" Maybe URI
ty))}
    Feed.Types.RSS1Item i :: Item
i ->
      Item -> Item
Feed.Types.RSS1Item
        Item
i
          { itemContent :: [ContentInfo]
RSS1.itemContent =
              ContentInfo
nullContentInfo {contentURI :: Maybe URI
contentURI = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
url, contentFormat :: Maybe URI
contentFormat = Maybe URI
ty} ContentInfo -> [ContentInfo] -> [ContentInfo]
forall a. a -> [a] -> [a]
: Item -> [ContentInfo]
RSS1.itemContent Item
i
          }
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild
        ((Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "enclosure" URI
url)
           {elementAttributes :: [Attr]
elementAttributes = [URI -> URI -> Attr
mkAttr "length" "0", URI -> URI -> Attr
mkAttr "type" (URI -> Maybe URI -> URI
forall a. a -> Maybe a -> a
fromMaybe "text/html" Maybe URI
ty)]}) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
      (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "enclosure") Element
i

-- | 'withItemId isURL id' associates new unique identifier with a feed item.
-- If 'isURL' is 'True', then the id is assumed to point to a valid web resource.
withItemId :: Bool -> ItemSetter Text
withItemId :: Bool -> ItemSetter URI
withItemId isURL :: Bool
isURL idS :: URI
idS fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e -> Entry -> Item
Feed.Types.AtomItem Entry
e {entryId :: URI
Atom.entryId = URI
idS}
    Feed.Types.RSSItem i :: RSSItem
i ->
      RSSItem -> Item
Feed.Types.RSSItem
        RSSItem
i {rssItemGuid :: Maybe RSSGuid
RSS.rssItemGuid = RSSGuid -> Maybe RSSGuid
forall a. a -> Maybe a
Just (URI -> RSSGuid
nullGuid URI
idS) {rssGuidPermanentURL :: Maybe Bool
rssGuidPermanentURL = Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
isURL}}
    Feed.Types.RSS1Item i :: Item
i ->
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break DCItem -> Bool
isId ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Item -> [DCItem]
RSS1.itemDC Item
i of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDC :: [DCItem]
RSS1.itemDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
idS} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
        (_, []) ->
          Item -> Item
Feed.Types.RSS1Item
            Item
i {itemDC :: [DCItem]
RSS1.itemDC = DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Identifier, dcText :: URI
dcText = URI
idS} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Item -> [DCItem]
RSS1.itemDC Item
i}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> ([Attr], URI) -> Element
forall t. ToNode t => Name -> t -> Element
unode "guid" ([URI -> URI -> Attr
mkAttr "isPermaLink" (Bool -> URI
forall a. Show a => a -> URI
showBool Bool
isURL)], URI
idS)) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
      (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "guid") Element
i
  where
    showBool :: a -> URI
showBool x :: a
x = [Char] -> URI
pack ([Char] -> URI) -> [Char] -> URI
forall a b. (a -> b) -> a -> b
$ (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (a -> [Char]
forall a. Show a => a -> [Char]
show a
x)
    isId :: DCItem -> Bool
isId dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Identifier

-- | 'withItemDescription desc' associates a new descriptive string (aka summary)
-- with a feed item.
withItemDescription :: ItemSetter Text
withItemDescription :: ItemSetter URI
withItemDescription desc :: URI
desc fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e -> Entry -> Item
Feed.Types.AtomItem Entry
e {entrySummary :: Maybe TextContent
Atom.entrySummary = TextContent -> Maybe TextContent
forall a. a -> Maybe a
Just (URI -> TextContent
TextString URI
desc)}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemDescription :: Maybe URI
RSS.rssItemDescription = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
desc}
    Feed.Types.RSS1Item i :: Item
i -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDesc :: Maybe URI
RSS1.itemDesc = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
desc}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "description" URI
desc) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "description") Element
i

-- | 'withItemRights rightStr' associates the rights information 'rightStr'
-- with a feed item.
withItemRights :: ItemSetter Text
withItemRights :: ItemSetter URI
withItemRights desc :: URI
desc fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e -> Entry -> Item
Feed.Types.AtomItem Entry
e {entryRights :: Maybe TextContent
Atom.entryRights = TextContent -> Maybe TextContent
forall a. a -> Maybe a
Just (URI -> TextContent
TextString URI
desc)}
     -- Note: per-item copyright information isn't supported by RSS2.0 (and earlier editions),
     -- you can only attach this at the feed/channel level. So, there's not much we can do
     -- except dropping the information on the floor here. (Rolling our own attribute or
     -- extension element is an option, but would prefer if someone else had started that
     -- effort already.
    Feed.Types.RSSItem {} -> Item
fi
    Feed.Types.RSS1Item i :: Item
i ->
      case (DCItem -> Bool) -> [DCItem] -> ([DCItem], [DCItem])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break ((DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Rights) (DCInfo -> Bool) -> (DCItem -> DCInfo) -> DCItem -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DCItem -> DCInfo
dcElt) ([DCItem] -> ([DCItem], [DCItem]))
-> [DCItem] -> ([DCItem], [DCItem])
forall a b. (a -> b) -> a -> b
$ Item -> [DCItem]
RSS1.itemDC Item
i of
        (as :: [DCItem]
as, dci :: DCItem
dci:bs :: [DCItem]
bs) -> Item -> Item
Feed.Types.RSS1Item Item
i {itemDC :: [DCItem]
RSS1.itemDC = [DCItem]
as [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ DCItem
dci {dcText :: URI
dcText = URI
desc} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: [DCItem]
bs}
        (_, []) ->
          Item -> Item
Feed.Types.RSS1Item
            Item
i {itemDC :: [DCItem]
RSS1.itemDC = DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Rights, dcText :: URI
dcText = URI
desc} DCItem -> [DCItem] -> [DCItem]
forall a. a -> [a] -> [a]
: Item -> [DCItem]
RSS1.itemDC Item
i}
     -- Since we're so far assuming that a shallow XML rep. of an item
     -- is of RSS2.0 ilk, pinning on the rights info is hard (see above.)
    Feed.Types.XMLItem {} -> Item
fi

-- | 'withItemTitle myLink' associates a new URL, 'myLink',
-- with a feed item.
withItemLink :: ItemSetter URLString
withItemLink :: ItemSetter URI
withItemLink url :: URI
url fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem Entry
e {entryLinks :: [Link]
Atom.entryLinks = URI -> [Link] -> [Link]
replaceAlternate URI
url (Entry -> [Link]
Atom.entryLinks Entry
e)}
    Feed.Types.RSSItem i :: RSSItem
i -> RSSItem -> Item
Feed.Types.RSSItem RSSItem
i {rssItemLink :: Maybe URI
RSS.rssItemLink = URI -> Maybe URI
forall a. a -> Maybe a
Just URI
url}
    Feed.Types.RSS1Item i :: Item
i -> Item -> Item
Feed.Types.RSS1Item Item
i {itemLink :: URI
RSS1.itemLink = URI
url}
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      Element -> Element -> Element
addChild (Name -> URI -> Element
forall t. ToNode t => Name -> t -> Element
unode "link" URI
url) (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ (Element -> Bool) -> Element -> Element
filterChildren (\e :: Element
e -> Element -> Name
elementName Element
e Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= "link") Element
i
  where
    replaceAlternate :: URI -> [Link] -> [Link]
replaceAlternate _ [] = []
    replaceAlternate x :: URI
x (lr :: Link
lr:xs :: [Link]
xs)
      | Maybe (Either URI URI) -> URI
forall p. IsString p => Maybe (Either p p) -> p
toStr (Link -> Maybe (Either URI URI)
Atom.linkRel Link
lr) URI -> URI -> Bool
forall a. Eq a => a -> a -> Bool
== "alternate" = Link
lr {linkHref :: URI
Atom.linkHref = URI
x} Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: [Link]
xs
      | Bool
otherwise = Link
lr Link -> [Link] -> [Link]
forall a. a -> [a] -> [a]
: URI -> [Link] -> [Link]
replaceAlternate URI
x [Link]
xs
    toStr :: Maybe (Either p p) -> p
toStr Nothing = ""
    toStr (Just (Left x :: p
x)) = p
x
    toStr (Just (Right x :: p
x)) = p
x

withItemCategories :: ItemSetter [(Text, Maybe Text)]
withItemCategories :: ItemSetter [(URI, Maybe URI)]
withItemCategories cats :: [(URI, Maybe URI)]
cats fi :: Item
fi =
  case Item
fi of
    Feed.Types.AtomItem e :: Entry
e ->
      Entry -> Item
Feed.Types.AtomItem
        Entry
e
          { entryCategories :: [Category]
Atom.entryCategories =
              ((URI, Maybe URI) -> Category) -> [(URI, Maybe URI)] -> [Category]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, mb :: Maybe URI
mb) -> (URI -> Category
Atom.newCategory URI
t) {catScheme :: Maybe URI
Atom.catScheme = Maybe URI
mb}) [(URI, Maybe URI)]
cats [Category] -> [Category] -> [Category]
forall a. [a] -> [a] -> [a]
++ Entry -> [Category]
entryCategories Entry
e
          }
    Feed.Types.RSSItem i :: RSSItem
i ->
      RSSItem -> Item
Feed.Types.RSSItem
        RSSItem
i
          { rssItemCategories :: [RSSCategory]
RSS.rssItemCategories =
              ((URI, Maybe URI) -> RSSCategory)
-> [(URI, Maybe URI)] -> [RSSCategory]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, mb :: Maybe URI
mb) -> (URI -> RSSCategory
RSS.newCategory URI
t) {rssCategoryDomain :: Maybe URI
RSS.rssCategoryDomain = Maybe URI
mb}) [(URI, Maybe URI)]
cats [RSSCategory] -> [RSSCategory] -> [RSSCategory]
forall a. [a] -> [a] -> [a]
++
              RSSItem -> [RSSCategory]
rssItemCategories RSSItem
i
          }
    Feed.Types.RSS1Item i :: Item
i ->
      Item -> Item
Feed.Types.RSS1Item
        Item
i
          { itemDC :: [DCItem]
RSS1.itemDC =
              ((URI, Maybe URI) -> DCItem) -> [(URI, Maybe URI)] -> [DCItem]
forall a b. (a -> b) -> [a] -> [b]
map (\(t :: URI
t, _) -> DCItem :: DCInfo -> URI -> DCItem
DCItem {dcElt :: DCInfo
dcElt = DCInfo
DC_Subject, dcText :: URI
dcText = URI
t}) [(URI, Maybe URI)]
cats [DCItem] -> [DCItem] -> [DCItem]
forall a. [a] -> [a] -> [a]
++ Item -> [DCItem]
RSS1.itemDC Item
i
          }
    Feed.Types.XMLItem i :: Element
i ->
      Element -> Item
Feed.Types.XMLItem (Element -> Item) -> Element -> Item
forall a b. (a -> b) -> a -> b
$
      ((URI, Maybe URI) -> Element -> Element)
-> Element -> [(URI, Maybe URI)] -> Element
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
        (\(t :: URI
t, mb :: Maybe URI
mb) acc :: Element
acc ->
           Element -> Element -> Element
addChild
             (Name -> [Attr] -> Element
forall t. ToNode t => Name -> t -> Element
unode "category" ((Attr -> [Attr])
-> (URI -> Attr -> [Attr]) -> Maybe URI -> Attr -> [Attr]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Attr -> [Attr] -> [Attr]
forall a. a -> [a] -> [a]
: []) (\v :: URI
v x :: Attr
x -> [URI -> URI -> Attr
mkAttr "domain" URI
v, Attr
x]) Maybe URI
mb (URI -> URI -> Attr
mkAttr "term" URI
t)))
             Element
acc)
        Element
i
        [(URI, Maybe URI)]
cats

-- helpers..
filterChildren :: (XML.Element -> Bool) -> XML.Element -> XML.Element
filterChildren :: (Element -> Bool) -> Element -> Element
filterChildren pre :: Element -> Bool
pre e :: Element
e =
  case Element -> [Node]
elementNodes Element
e of
    [] -> Element
e
    cs :: [Node]
cs -> Element
e {elementNodes :: [Node]
elementNodes = (Node -> Maybe Node) -> [Node] -> [Node]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Node -> Maybe Node
filterElt [Node]
cs}
  where
    filterElt :: Node -> Maybe Node
filterElt xe :: Node
xe@(XML.NodeElement el :: Element
el)
      | Element -> Bool
pre Element
el = Node -> Maybe Node
forall a. a -> Maybe a
Just Node
xe
      | Bool
otherwise = Maybe Node
forall a. Maybe a
Nothing
    filterElt xe :: Node
xe = Node -> Maybe Node
forall a. a -> Maybe a
Just Node
xe

addChild :: XML.Element -> XML.Element -> XML.Element
addChild :: Element -> Element -> Element
addChild a :: Element
a b :: Element
b = Element
b {elementNodes :: [Node]
elementNodes = Element -> Node
XML.NodeElement Element
a Node -> [Node] -> [Node]
forall a. a -> [a] -> [a]
: Element -> [Node]
elementNodes Element
b}

mapMaybeChildren :: (XML.Element -> Maybe XML.Element) -> XML.Element -> XML.Element
mapMaybeChildren :: (Element -> Maybe Element) -> Element -> Element
mapMaybeChildren f :: Element -> Maybe Element
f e :: Element
e =
  case Element -> [Node]
elementNodes Element
e of
    [] -> Element
e
    cs :: [Node]
cs -> Element
e {elementNodes :: [Node]
elementNodes = (Node -> Node) -> [Node] -> [Node]
forall a b. (a -> b) -> [a] -> [b]
map Node -> Node
procElt [Node]
cs}
  where
    procElt :: Node -> Node
procElt xe :: Node
xe@(XML.NodeElement el :: Element
el) =
      case Element -> Maybe Element
f Element
el of
        Nothing -> Node
xe
        Just el1 :: Element
el1 -> Element -> Node
XML.NodeElement Element
el1
    procElt xe :: Node
xe = Node
xe