    {-# LANGUAGE CPP #-}

    --------------------------------------------------------------------
    -- |
    -- Module    : Text.Feed.Query
    -- Copyright : (c) Galois, Inc. 2008,
    --             (c) Sigbjorn Finne 2009-
    -- License   : BSD3
    --
    -- Maintainer: Sigbjorn Finne <sof@forkIO.com>
    -- Stability : provisional
    -- Portability: portable
    --
    --------------------------------------------------------------------
    module Text.Feed.Query
      ( Text.Feed.Query.feedItems -- :: Feed.Feed -> [Feed.Item]
      , FeedGetter -- type _ a = Feed -> a
      , getFeedTitle -- :: FeedGetter Text
      , getFeedAuthor -- :: FeedGetter Text
      , getFeedHome -- :: FeedGetter URLString
      , getFeedHTML -- :: FeedGetter URLString
      , getFeedDescription -- :: FeedGetter Text
      , getFeedPubDate -- :: FeedGetter DateString
      , getFeedLastUpdate -- :: FeedGetter Text
      , getFeedDate -- :: FeedGetter DateString
      , getFeedLogoLink -- :: FeedGetter URLString
      , getFeedLanguage -- :: FeedGetter Text
      , getFeedCategories -- :: FeedGetter [(Text, Maybe Text)]
      , getFeedGenerator -- :: FeedGetter Text
      , getFeedItems -- :: FeedGetter [Item]
      , ItemGetter -- type _ a = Item -> Maybe a
      , getItemTitle -- :: ItemGetter Text
      , getItemLink -- :: ItemGetter Text
      , getItemPublishDate -- :: Data.Time.ParseTime t => ItemGetter (Maybe t)
      , getItemPublishDateString -- :: ItemGetter (DateString)
      , getItemDate -- :: ItemGetter (DateString)
      , getItemAuthor -- :: ItemGetter Text
      , getItemCommentLink -- :: ItemGetter (URLString)
      , getItemEnclosure -- :: ItemGetter (URI, Maybe Text, Integer)
      , getItemFeedLink -- :: ItemGetter (URLString)
      , getItemId -- :: ItemGetter (Bool, Text)
      , getItemCategories -- :: ItemGetter [Text]
      , getItemRights -- :: ItemGetter Text
      , getItemSummary -- :: ItemGetter Text
      , getItemContent -- :: ItemGetter Text
      , getItemDescription -- :: ItemGetter Text (synonym of previous.)
      ) where

    import Prelude.Compat

    import Text.Feed.Types as Feed

    import Data.XML.Types as XML
    import Text.Atom.Feed as Atom
    import Text.Atom.Feed.Export (atomName)
    import Text.RSS.Syntax as RSS
    import Text.RSS1.Syntax as RSS1

    import Data.XML.Compat

    import Text.DublinCore.Types

    import Control.Applicative ((<|>))
    import Control.Arrow ((&&&))
    import Control.Monad.Compat (mplus)
    import Data.Maybe
    import Data.Text (Text)
    import qualified Data.Text as T
    import Data.Text.Read

    import Data.Time.Format (ParseTime)
    import qualified Data.Time.Format as F

    -- for getItemPublishDate rfc822 date parsing.
    import Data.Time.Locale.Compat (defaultTimeLocale, iso8601DateFormat, rfc822DateFormat)

    feedItems :: Feed.Feed -> [Feed.Item]
    feedItems :: Feed -> [Item]
    feedItems Feed
    fe =
      case Feed
    fe of
        AtomFeed Feed
    f -> (Entry -> Item) -> [Entry] -> [Item]
    forall a b. (a -> b) -> [a] -> [b]
    map Entry -> Item
    Feed.AtomItem (Feed -> [Entry]
    Atom.feedEntries Feed
    f)
        RSSFeed RSS
    f -> (RSSItem -> Item) -> [RSSItem] -> [Item]
    forall a b. (a -> b) -> [a] -> [b]
    map RSSItem -> Item
    Feed.RSSItem (RSSChannel -> [RSSItem]
    RSS.rssItems (RSSChannel -> [RSSItem]) -> RSSChannel -> [RSSItem]
    forall a b. (a -> b) -> a -> b
    $ RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        RSS1Feed Feed
    f -> (Item -> Item) -> [Item] -> [Item]
    forall a b. (a -> b) -> [a] -> [b]
    map Item -> Item
    Feed.RSS1Item (Feed -> [Item]
    RSS1.feedItems Feed
    f)
        XMLFeed Element
    f ->
          case Name -> Element -> [Element]
    findElements Name
    "item" Element
    f of
            [] -> (Element -> Item) -> [Element] -> [Item]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Item
    Feed.XMLItem ([Element] -> [Item]) -> [Element] -> [Item]
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> [Element]
    findElements (Text -> Name
    atomName Text
    "entry") Element
    f
            [Element]
    l -> (Element -> Item) -> [Element] -> [Item]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Item
    Feed.XMLItem [Element]
    l

    getFeedItems :: Feed.Feed -> [Feed.Item]
    getFeedItems :: Feed -> [Item]
    getFeedItems = Feed -> [Item]
    Text.Feed.Query.feedItems

    type FeedGetter a = Feed.Feed -> Maybe a

    getFeedAuthor :: FeedGetter Text
    getFeedAuthor :: FeedGetter Text
    getFeedAuthor Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> (Person -> Text) -> Maybe Person -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Person -> Text
    Atom.personName (Maybe Person -> Maybe Text) -> Maybe Person -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Person] -> Maybe Person
    forall a. [a] -> Maybe a
    listToMaybe ([Person] -> Maybe Person) -> [Person] -> Maybe Person
    forall a b. (a -> b) -> a -> b
    $ Feed -> [Person]
    Atom.feedAuthors Feed
    f
        Feed.RSSFeed RSS
    f -> RSSChannel -> Maybe Text
    RSS.rssEditor (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f ->
          (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isAuthor ([DCItem] -> [DCItem]) -> [DCItem] -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Channel -> [DCItem]
    RSS1.channelDC (Feed -> Channel
    RSS1.feedChannel Feed
    f)
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "editor" Element
    e1
            Maybe Element
    Nothing ->
              (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Maybe Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "name") (Element -> Maybe Element) -> Maybe Element -> Maybe Element
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "author") Element
    f
      where
        isAuthor :: DCItem -> Bool
    isAuthor DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Creator

    getFeedTitle :: Feed.Feed -> Text
    getFeedTitle :: Feed -> Text
    getFeedTitle Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> TextContent -> Text
    contentToStr (TextContent -> Text) -> TextContent -> Text
    forall a b. (a -> b) -> a -> b
    $ Feed -> TextContent
    Atom.feedTitle Feed
    f
        Feed.RSSFeed RSS
    f -> RSSChannel -> Text
    RSS.rssTitle (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f -> Channel -> Text
    RSS1.channelTitle (Feed -> Channel
    RSS1.feedChannel Feed
    f)
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Text -> (Element -> Text) -> Maybe Element -> Text
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Text
    "" Element -> Text
    strContent (Name -> Element -> Maybe Element
    findElement Name
    "title" Element
    e1)
            Maybe Element
    Nothing -> Text -> (Element -> Text) -> Maybe Element -> Text
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Text
    "" Element -> Text
    strContent (Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "title") Element
    f)

    getFeedHome :: FeedGetter URLString
    getFeedHome :: FeedGetter Text
    getFeedHome Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> (Link -> Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Link -> Text
    Atom.linkHref (Maybe Link -> Maybe Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Link] -> Maybe Link
    forall a. [a] -> Maybe a
    listToMaybe ([Link] -> Maybe Link) -> [Link] -> Maybe Link
    forall a b. (a -> b) -> a -> b
    $ (Link -> Bool) -> [Link] -> [Link]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Link -> Bool
    isSelf (Feed -> [Link]
    Atom.feedLinks Feed
    f)
        Feed.RSSFeed RSS
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (RSSChannel -> Text
    RSS.rssLink (RSS -> RSSChannel
    RSS.rssChannel RSS
    f))
        Feed.RSS1Feed Feed
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Channel -> Text
    RSS1.channelURI (Feed -> Channel
    RSS1.feedChannel Feed
    f))
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "link" Element
    e1
            Maybe Element
    Nothing -> Name -> Element -> Maybe Text
    attributeText Name
    "href" (Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "link") Element
    f
      where
        isSelf :: Link -> Bool
    isSelf Link
    lr = Maybe (Either Text Text) -> Text
    toStr (Link -> Maybe (Either Text Text)
    Atom.linkRel Link
    lr) Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "self"

    getFeedHTML :: FeedGetter URLString
    getFeedHTML :: FeedGetter Text
    getFeedHTML Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> (Link -> Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Link -> Text
    Atom.linkHref (Maybe Link -> Maybe Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Link] -> Maybe Link
    forall a. [a] -> Maybe a
    listToMaybe ([Link] -> Maybe Link) -> [Link] -> Maybe Link
    forall a b. (a -> b) -> a -> b
    $ (Link -> Bool) -> [Link] -> [Link]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Link -> Bool
    isSelf (Feed -> [Link]
    Atom.feedLinks Feed
    f)
        Feed.RSSFeed RSS
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (RSSChannel -> Text
    RSS.rssLink (RSS -> RSSChannel
    RSS.rssChannel RSS
    f))
        Feed.RSS1Feed Feed
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Channel -> Text
    RSS1.channelURI (Feed -> Channel
    RSS1.feedChannel Feed
    f))
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "link" Element
    e1
            Maybe Element
    Nothing -> Maybe Text
    forall a. Maybe a
    Nothing -- ToDo parse atom like tags
      where
        isSelf :: Link -> Bool
    isSelf Link
    lr =
          let rel :: Maybe (Either Text Text)
    rel = Link -> Maybe (Either Text Text)
    Atom.linkRel Link
    lr
           in (Maybe (Either Text Text) -> Bool
    forall a. Maybe a -> Bool
    isNothing Maybe (Either Text Text)
    rel Bool -> Bool -> Bool
    || Maybe (Either Text Text) -> Text
    toStr Maybe (Either Text Text)
    rel Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "alternate") Bool -> Bool -> Bool
    && Maybe Text -> Bool
    isHTMLType (Link -> Maybe Text
    linkType Link
    lr)
        isHTMLType :: Maybe Text -> Bool
    isHTMLType (Just Text
    str) = Text
    "html" Text -> Text -> Bool
    `T.isSuffixOf` Text
    str
        isHTMLType Maybe Text
    _ = Bool
    True -- if none given, assume html.

    getFeedDescription :: FeedGetter Text
    getFeedDescription :: FeedGetter Text
    getFeedDescription Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> (TextContent -> Text) -> Maybe TextContent -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap TextContent -> Text
    contentToStr (Feed -> Maybe TextContent
    Atom.feedSubtitle Feed
    f)
        Feed.RSSFeed RSS
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text) -> Text -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ RSSChannel -> Text
    RSS.rssDescription (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Channel -> Text
    RSS1.channelDesc (Feed -> Channel
    RSS1.feedChannel Feed
    f))
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "description" Element
    e1
            Maybe Element
    Nothing -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "subtitle") Element
    f

    getFeedPubDate :: FeedGetter DateString
    getFeedPubDate :: FeedGetter Text
    getFeedPubDate Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text) -> Text -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Feed -> Text
    Atom.feedUpdated Feed
    f
        Feed.RSSFeed RSS
    f -> RSSChannel -> Maybe Text
    RSS.rssPubDate (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f ->
          (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isDate (Channel -> [DCItem]
    RSS1.channelDC (Channel -> [DCItem]) -> Channel -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Feed -> Channel
    RSS1.feedChannel Feed
    f)
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "pubDate" Element
    e1
            Maybe Element
    Nothing -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "published") Element
    f
      where
        isDate :: DCItem -> Bool
    isDate DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Date

    getFeedLastUpdate :: FeedGetter Text
    getFeedLastUpdate :: FeedGetter Text
    getFeedLastUpdate Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text) -> Text -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Feed -> Text
    Atom.feedUpdated Feed
    f
        Feed.RSSFeed RSS
    f -> RSSChannel -> Maybe Text
    RSS.rssPubDate (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f ->
          (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isDate (Channel -> [DCItem]
    RSS1.channelDC (Channel -> [DCItem]) -> Channel -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Feed -> Channel
    RSS1.feedChannel Feed
    f)
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "pubDate" Element
    e1
            Maybe Element
    Nothing -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "updated") Element
    f
      where
        isDate :: DCItem -> Bool
    isDate DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Date

    getFeedDate :: FeedGetter DateString
    getFeedDate :: FeedGetter Text
    getFeedDate = FeedGetter Text
    getFeedPubDate

    getFeedLogoLink :: FeedGetter URLString
    getFeedLogoLink :: FeedGetter Text
    getFeedLogoLink Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> Feed -> Maybe Text
    Atom.feedLogo Feed
    f
        Feed.RSSFeed RSS
    f -> (RSSImage -> Text) -> Maybe RSSImage -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap RSSImage -> Text
    RSS.rssImageURL (RSSChannel -> Maybe RSSImage
    RSS.rssImage (RSSChannel -> Maybe RSSImage) -> RSSChannel -> Maybe RSSImage
    forall a b. (a -> b) -> a -> b
    $ RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f -> Image -> Text
    RSS1.imageURI (Image -> Text) -> Maybe Image -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Feed -> Maybe Image
    RSS1.feedImage Feed
    f
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    ch -> do
              Element
    e1 <- Name -> Element -> Maybe Element
    findElement Name
    "image" Element
    ch
              Element
    v <- Name -> Element -> Maybe Element
    findElement Name
    "url" Element
    e1
              Text -> Maybe Text
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Element -> Text
    strContent Element
    v)
            Maybe Element
    Nothing -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "logo") Element
    f

    getFeedLanguage :: FeedGetter Text
    getFeedLanguage :: FeedGetter Text
    getFeedLanguage Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> Name -> Element -> Maybe Text
    attributeText Name
    "lang" (Element -> Maybe Text) -> Element -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Name -> [Attr] -> Element
    forall t. ToNode t => Name -> t -> Element
    unode Name
    "" (Feed -> [Attr]
    Atom.feedAttrs Feed
    f)
        Feed.RSSFeed RSS
    f -> RSSChannel -> Maybe Text
    RSS.rssLanguage (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f ->
          (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isLang (Channel -> [DCItem]
    RSS1.channelDC (Channel -> [DCItem]) -> Channel -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Feed -> Channel
    RSS1.feedChannel Feed
    f)
        Feed.XMLFeed Element
    f -> do
          Element
    ch <- Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f
          Element
    e1 <- Name -> Element -> Maybe Element
    findElement Name
    "language" Element
    ch
          Text -> Maybe Text
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Element -> Text
    strContent Element
    e1)
           -- ToDo parse atom like tags too
      where
        isLang :: DCItem -> Bool
    isLang DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Language

    getFeedCategories :: Feed.Feed -> [(Text, Maybe Text)]
    getFeedCategories :: Feed -> [(Text, Maybe Text)]
    getFeedCategories Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> (Category -> (Text, Maybe Text))
    -> [Category] -> [(Text, Maybe Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (Category -> Text
    Atom.catTerm (Category -> Text)
    -> (Category -> Maybe Text) -> Category -> (Text, Maybe Text)
    forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& Category -> Maybe Text
    Atom.catScheme) (Feed -> [Category]
    Atom.feedCategories Feed
    f)
        Feed.RSSFeed RSS
    f ->
          (RSSCategory -> (Text, Maybe Text))
    -> [RSSCategory] -> [(Text, Maybe Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (RSSCategory -> Text
    RSS.rssCategoryValue (RSSCategory -> Text)
    -> (RSSCategory -> Maybe Text) -> RSSCategory -> (Text, Maybe Text)
    forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
    forall (a :: * -> * -> *) b c c'.
    Arrow a =>
    a b c -> a b c' -> a b (c, c')
    &&& RSSCategory -> Maybe Text
    RSS.rssCategoryDomain) (RSSChannel -> [RSSCategory]
    RSS.rssCategories (RSS -> RSSChannel
    RSS.rssChannel RSS
    f))
        Feed.RSS1Feed Feed
    f ->
          case (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isCat (Channel -> [DCItem]
    RSS1.channelDC (Channel -> [DCItem]) -> Channel -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Feed -> Channel
    RSS1.feedChannel Feed
    f) of
            [DCItem]
    ls -> (DCItem -> (Text, Maybe Text)) -> [DCItem] -> [(Text, Maybe Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\DCItem
    l -> (DCItem -> Text
    dcText DCItem
    l, Maybe Text
    forall a. Maybe a
    Nothing)) [DCItem]
    ls
        Feed.XMLFeed Element
    f ->
          case [Element] -> (Element -> [Element]) -> Maybe Element -> [Element]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [] (Name -> Element -> [Element]
    findElements Name
    "category") (Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f) of
            [Element]
    ls -> (Element -> (Text, Maybe Text))
    -> [Element] -> [(Text, Maybe Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\Element
    l -> (Text -> (Element -> Text) -> Maybe Element -> Text
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Text
    "" Element -> Text
    strContent (Name -> Element -> Maybe Element
    findElement Name
    "term" Element
    l), Name -> Element -> Maybe Text
    attributeText Name
    "domain" Element
    l)) [Element]
    ls
           -- ToDo parse atom like tags too
      where
        isCat :: DCItem -> Bool
    isCat DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Subject

    getFeedGenerator :: FeedGetter Text
    getFeedGenerator :: FeedGetter Text
    getFeedGenerator Feed
    ft =
      case Feed
    ft of
        Feed.AtomFeed Feed
    f -> do
          Generator
    gen <- Feed -> Maybe Generator
    Atom.feedGenerator Feed
    f
          Generator -> Maybe Text
    Atom.genURI Generator
    gen
        Feed.RSSFeed RSS
    f -> RSSChannel -> Maybe Text
    RSS.rssGenerator (RSS -> RSSChannel
    RSS.rssChannel RSS
    f)
        Feed.RSS1Feed Feed
    f ->
          (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isSource (Channel -> [DCItem]
    RSS1.channelDC (Feed -> Channel
    RSS1.feedChannel Feed
    f))
        Feed.XMLFeed Element
    f ->
          case Name -> Element -> Maybe Element
    findElement Name
    "channel" Element
    f of
            Just Element
    e1 -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement Name
    "generator" Element
    e1
            Maybe Element
    Nothing -> Name -> Element -> Maybe Text
    attributeText Name
    "uri" (Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "generator") Element
    f
      where
        isSource :: DCItem -> Bool
    isSource DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Source

    type ItemGetter a = Feed.Item -> Maybe a

    getItemTitle :: ItemGetter Text
    getItemTitle :: ItemGetter Text
    getItemTitle Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    i -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (TextContent -> Text
    contentToStr (TextContent -> Text) -> TextContent -> Text
    forall a b. (a -> b) -> a -> b
    $ Entry -> TextContent
    Atom.entryTitle Entry
    i)
        Feed.RSSItem RSSItem
    i -> RSSItem -> Maybe Text
    RSS.rssItemTitle RSSItem
    i
        Feed.RSS1Item Item
    i -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Item -> Text
    RSS1.itemTitle Item
    i)
        Feed.XMLItem Element
    e -> (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Maybe Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Element
    findElement Name
    "title" Element
    e Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "title") Element
    e

    getItemLink :: ItemGetter Text
    getItemLink :: ItemGetter Text
    getItemLink Item
    it =
      case Item
    it
           -- look up the 'alternate' HTML link relation on the entry, or one
           -- without link relation since that is equivalent to 'alternate':
            of
        Feed.AtomItem Entry
    i -> (Link -> Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Link -> Text
    Atom.linkHref (Maybe Link -> Maybe Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Link] -> Maybe Link
    forall a. [a] -> Maybe a
    listToMaybe ([Link] -> Maybe Link) -> [Link] -> Maybe Link
    forall a b. (a -> b) -> a -> b
    $ (Link -> Bool) -> [Link] -> [Link]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Link -> Bool
    isSelf ([Link] -> [Link]) -> [Link] -> [Link]
    forall a b. (a -> b) -> a -> b
    $ Entry -> [Link]
    Atom.entryLinks Entry
    i
        Feed.RSSItem RSSItem
    i -> RSSItem -> Maybe Text
    RSS.rssItemLink RSSItem
    i
        Feed.RSS1Item Item
    i -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Item -> Text
    RSS1.itemLink Item
    i)
        Feed.XMLItem Element
    i ->
          (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Name -> Element -> Maybe Element
    findElement Name
    "link" Element
    i) Maybe Text -> Maybe Text -> Maybe Text
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|>
          (Name -> Element -> Maybe Element
    findChild (Text -> Name
    atomName Text
    "link") Element
    i Maybe Element -> (Element -> Maybe Text) -> Maybe Text
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Name -> Element -> Maybe Text
    attributeText Name
    "href")
      where
        isSelf :: Link -> Bool
    isSelf Link
    lr =
          let rel :: Maybe (Either Text Text)
    rel = Link -> Maybe (Either Text Text)
    Atom.linkRel Link
    lr
           in (Maybe (Either Text Text) -> Bool
    forall a. Maybe a -> Bool
    isNothing Maybe (Either Text Text)
    rel Bool -> Bool -> Bool
    || Maybe (Either Text Text) -> Text
    toStr Maybe (Either Text Text)
    rel Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "alternate") Bool -> Bool -> Bool
    && Maybe Text -> Bool
    isHTMLType (Link -> Maybe Text
    linkType Link
    lr)
        isHTMLType :: Maybe Text -> Bool
    isHTMLType (Just Text
    str) = Text
    "html" Text -> Text -> Bool
    `T.isSuffixOf` Text
    str
        isHTMLType Maybe Text
    _ = Bool
    True -- if none given, assume html.

    -- | 'getItemPublishDate item' returns the publication date of the item,
    -- but first parsed per the supported RFC 822 and RFC 3339 formats.
    --
    -- If the date string cannot be parsed as such, Just Nothing is
    -- returned.  The caller must then instead fall back to processing the
    -- date string from 'getItemPublishDateString'.
    --
    -- The parsed date representation is one of the ParseTime instances;
    -- see 'Data.Time.Format'.
    getItemPublishDate :: ParseTime t => ItemGetter (Maybe t)
    getItemPublishDate :: forall t. ParseTime t => ItemGetter (Maybe t)
    getItemPublishDate Item
    it = do
      Text
    ds <- ItemGetter Text
    getItemPublishDateString Item
    it
      let rfc3339DateFormat1 :: String
    rfc3339DateFormat1 = Maybe String -> String
    iso8601DateFormat (String -> Maybe String
    forall a. a -> Maybe a
    Just String
    "%H:%M:%S%Z")
          rfc3339DateFormat2 :: String
    rfc3339DateFormat2 = Maybe String -> String
    iso8601DateFormat (String -> Maybe String
    forall a. a -> Maybe a
    Just String
    "%H:%M:%S%Q%Z")
          formats :: [String]
    formats = [String
    rfc3339DateFormat1, String
    rfc3339DateFormat2, String
    rfc822DateFormat]
          date :: Maybe t
    date = (Maybe t -> Maybe t -> Maybe t) -> [Maybe t] -> Maybe t
    forall a. (a -> a -> a) -> [a] -> a
    forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
    foldl1 Maybe t -> Maybe t -> Maybe t
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    mplus ((String -> Maybe t) -> [String] -> [Maybe t]
    forall a b. (a -> b) -> [a] -> [b]
    map (\String
    fmt -> TimeLocale -> String -> String -> Maybe t
    parseTime TimeLocale
    defaultTimeLocale String
    fmt (String -> Maybe t) -> String -> Maybe t
    forall a b. (a -> b) -> a -> b
    $ Text -> String
    T.unpack Text
    ds) [String]
    formats)
      Maybe t -> Maybe (Maybe t)
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe t
    date
      where

    #if MIN_VERSION_time(1,5,0)
         parseTime :: TimeLocale -> String -> String -> Maybe t
    parseTime = Bool -> TimeLocale -> String -> String -> Maybe t
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> String -> String -> m t
    F.parseTimeM Bool
    True
    #else
         parseTime = F.parseTime
    #endif
    getItemPublishDateString :: ItemGetter DateString
    getItemPublishDateString :: ItemGetter Text
    getItemPublishDateString Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    i -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text) -> Text -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Entry -> Text
    Atom.entryUpdated Entry
    i
        Feed.RSSItem RSSItem
    i -> RSSItem -> Maybe Text
    RSS.rssItemPubDate RSSItem
    i
        Feed.RSS1Item Item
    i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isDate ([DCItem] -> [DCItem]) -> [DCItem] -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Item -> [DCItem]
    RSS1.itemDC Item
    i
        Feed.XMLItem Element
    e ->
          (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Maybe Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Element
    findElement Name
    "pubDate" Element
    e Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "published") Element
    e
      where
        isDate :: DCItem -> Bool
    isDate DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Date

    getItemDate :: ItemGetter DateString
    getItemDate :: ItemGetter Text
    getItemDate = ItemGetter Text
    getItemPublishDateString

    -- | 'getItemAuthor f' returns the optional author of the item.
    getItemAuthor :: ItemGetter Text
    getItemAuthor :: ItemGetter Text
    getItemAuthor Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    i -> (Person -> Text) -> Maybe Person -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Person -> Text
    Atom.personName (Maybe Person -> Maybe Text) -> Maybe Person -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Person] -> Maybe Person
    forall a. [a] -> Maybe a
    listToMaybe ([Person] -> Maybe Person) -> [Person] -> Maybe Person
    forall a b. (a -> b) -> a -> b
    $ Entry -> [Person]
    Atom.entryAuthors Entry
    i
        Feed.RSSItem RSSItem
    i -> RSSItem -> Maybe Text
    RSS.rssItemAuthor RSSItem
    i
        Feed.RSS1Item Item
    i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isAuthor ([DCItem] -> [DCItem]) -> [DCItem] -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Item -> [DCItem]
    RSS1.itemDC Item
    i
        Feed.XMLItem Element
    e ->
          (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Maybe Element -> Maybe Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $
          Name -> Element -> Maybe Element
    findElement Name
    "author" Element
    e Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|>
          (Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "author") Element
    e Maybe Element -> (Element -> Maybe Element) -> Maybe Element
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "name"))
      where
        isAuthor :: DCItem -> Bool
    isAuthor DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Creator

    getItemCommentLink :: ItemGetter URLString
    getItemCommentLink :: ItemGetter Text
    getItemCommentLink Item
    it =
      case Item
    it
           -- look up the 'replies' HTML link relation on the entry:
            of
        Feed.AtomItem Entry
    e -> (Link -> Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Link -> Text
    Atom.linkHref (Maybe Link -> Maybe Text) -> Maybe Link -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [Link] -> Maybe Link
    forall a. [a] -> Maybe a
    listToMaybe ([Link] -> Maybe Link) -> [Link] -> Maybe Link
    forall a b. (a -> b) -> a -> b
    $ (Link -> Bool) -> [Link] -> [Link]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Link -> Bool
    isReplies ([Link] -> [Link]) -> [Link] -> [Link]
    forall a b. (a -> b) -> a -> b
    $ Entry -> [Link]
    Atom.entryLinks Entry
    e
        Feed.RSSItem RSSItem
    i -> RSSItem -> Maybe Text
    RSS.rssItemComments RSSItem
    i
        Feed.RSS1Item Item
    i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isRel ([DCItem] -> [DCItem]) -> [DCItem] -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Item -> [DCItem]
    RSS1.itemDC Item
    i
        Feed.XMLItem Element
    i ->
          (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Name -> Element -> Maybe Element
    findElement Name
    "comments" Element
    i) Maybe Text -> Maybe Text -> Maybe Text
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|>
          (Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "link") Element
    i Maybe Element -> (Element -> Maybe Text) -> Maybe Text
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Name -> Element -> Maybe Text
    attributeText Name
    "href")
      where
        isReplies :: Link -> Bool
    isReplies Link
    lr = Maybe (Either Text Text) -> Text
    toStr (Link -> Maybe (Either Text Text)
    Atom.linkRel Link
    lr) Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "replies"
        isRel :: DCItem -> Bool
    isRel DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Relation

    getItemEnclosure :: ItemGetter (URI, Maybe Text, Maybe Integer)
    getItemEnclosure :: ItemGetter (Text, Maybe Text, Maybe Integer)
    getItemEnclosure Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e ->
          case (Link -> Bool) -> [Link] -> [Link]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Link -> Bool
    isEnc ([Link] -> [Link]) -> [Link] -> [Link]
    forall a b. (a -> b) -> a -> b
    $ Entry -> [Link]
    Atom.entryLinks Entry
    e of
            (Link
    l:[Link]
    _) -> (Text, Maybe Text, Maybe Integer)
    -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a. a -> Maybe a
    Just (Link -> Text
    Atom.linkHref Link
    l, Link -> Maybe Text
    Atom.linkType Link
    l, Maybe Text -> Maybe Integer
    forall {a}. Integral a => Maybe Text -> Maybe a
    readLength (Link -> Maybe Text
    Atom.linkLength Link
    l))
            [Link]
    _ -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a. Maybe a
    Nothing
        Feed.RSSItem RSSItem
    i ->
          (RSSEnclosure -> (Text, Maybe Text, Maybe Integer))
    -> Maybe RSSEnclosure -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap
            (\RSSEnclosure
    e -> (RSSEnclosure -> Text
    RSS.rssEnclosureURL RSSEnclosure
    e, Text -> Maybe Text
    forall a. a -> Maybe a
    Just (RSSEnclosure -> Text
    RSS.rssEnclosureType RSSEnclosure
    e), RSSEnclosure -> Maybe Integer
    RSS.rssEnclosureLength RSSEnclosure
    e))
            (RSSItem -> Maybe RSSEnclosure
    RSS.rssItemEnclosure RSSItem
    i)
        Feed.RSS1Item Item
    i ->
          case Item -> [ContentInfo]
    RSS1.itemContent Item
    i of
            [] -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a. Maybe a
    Nothing
            (ContentInfo
    c:[ContentInfo]
    _) -> (Text, Maybe Text, Maybe Integer)
    -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a. a -> Maybe a
    Just (Text -> Maybe Text -> Text
    forall a. a -> Maybe a -> a
    fromMaybe Text
    "" (ContentInfo -> Maybe Text
    RSS1.contentURI ContentInfo
    c), ContentInfo -> Maybe Text
    RSS1.contentFormat ContentInfo
    c, Maybe Integer
    forall a. Maybe a
    Nothing)
        Feed.XMLItem Element
    e ->
          (Element -> (Text, Maybe Text, Maybe Integer))
    -> Maybe Element -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> (Text, Maybe Text, Maybe Integer)
    forall {a}. Integral a => Element -> (Text, Maybe Text, Maybe a)
    xmlToEnclosure (Maybe Element -> Maybe (Text, Maybe Text, Maybe Integer))
    -> Maybe Element -> Maybe (Text, Maybe Text, Maybe Integer)
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Element
    findElement Name
    "enclosure" Element
    e Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "enclosure") Element
    e
      where
        isEnc :: Link -> Bool
    isEnc Link
    lr = Maybe (Either Text Text) -> Text
    toStr (Link -> Maybe (Either Text Text)
    Atom.linkRel Link
    lr) Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "enclosure"
        readLength :: Maybe Text -> Maybe a
    readLength Maybe Text
    Nothing = Maybe a
    forall a. Maybe a
    Nothing
        readLength (Just Text
    str) =
          case Reader a
    forall a. Integral a => Reader a
    decimal Text
    str of
            Right (a
    v, Text
    _) -> a -> Maybe a
    forall a. a -> Maybe a
    Just a
    v
            Either String (a, Text)
    _ -> Maybe a
    forall a. Maybe a
    Nothing
        xmlToEnclosure :: Element -> (Text, Maybe Text, Maybe a)
    xmlToEnclosure Element
    e =
          ( Text -> Maybe Text -> Text
    forall a. a -> Maybe a -> a
    fromMaybe Text
    "" (Name -> Element -> Maybe Text
    attributeText Name
    "url" Element
    e)
          , Name -> Element -> Maybe Text
    attributeText Name
    "type" Element
    e
          , Maybe Text -> Maybe a
    forall {a}. Integral a => Maybe Text -> Maybe a
    readLength (Maybe Text -> Maybe a) -> Maybe Text -> Maybe a
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Text
    attributeText Name
    "length" Element
    e)

    getItemFeedLink :: ItemGetter URLString
    getItemFeedLink :: ItemGetter Text
    getItemFeedLink Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e ->
          case Entry -> Maybe Source
    Atom.entrySource Entry
    e of
            Maybe Source
    Nothing -> Maybe Text
    forall a. Maybe a
    Nothing
            Just Source
    s -> Source -> Maybe Text
    Atom.sourceId Source
    s
        Feed.RSSItem RSSItem
    i ->
          case RSSItem -> Maybe RSSSource
    RSS.rssItemSource RSSItem
    i of
            Maybe RSSSource
    Nothing -> Maybe Text
    forall a. Maybe a
    Nothing
            Just RSSSource
    s -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just (RSSSource -> Text
    RSS.rssSourceURL RSSSource
    s)
        Feed.RSS1Item Item
    _ -> Maybe Text
    forall a. Maybe a
    Nothing
        Feed.XMLItem Element
    e ->
          case Name -> Element -> Maybe Element
    findElement Name
    "source" Element
    e of
            Maybe Element
    Nothing -> Maybe Text
    forall a. Maybe a
    Nothing
            Just Element
    s -> (Element -> Text) -> Maybe Element -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Element -> Text
    strContent (Name -> Element -> Maybe Element
    findElement Name
    "url" Element
    s)
          -- ToDo parse atom like tags too

    getItemId :: ItemGetter (Bool, Text)
    getItemId :: ItemGetter (Bool, Text)
    getItemId Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e -> (Bool, Text) -> Maybe (Bool, Text)
    forall a. a -> Maybe a
    Just (Bool
    True, Entry -> Text
    Atom.entryId Entry
    e)
        Feed.RSSItem RSSItem
    i ->
          case RSSItem -> Maybe RSSGuid
    RSS.rssItemGuid RSSItem
    i of
            Maybe RSSGuid
    Nothing -> Maybe (Bool, Text)
    forall a. Maybe a
    Nothing
            Just RSSGuid
    ig -> (Bool, Text) -> Maybe (Bool, Text)
    forall a. a -> Maybe a
    Just (Bool -> Maybe Bool -> Bool
    forall a. a -> Maybe a -> a
    fromMaybe Bool
    True (RSSGuid -> Maybe Bool
    RSS.rssGuidPermanentURL RSSGuid
    ig), RSSGuid -> Text
    RSS.rssGuidValue RSSGuid
    ig)
        Feed.RSS1Item Item
    i ->
          case (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isId (Item -> [DCItem]
    RSS1.itemDC Item
    i) of
            (DCItem
    l:[DCItem]
    _) -> (Bool, Text) -> Maybe (Bool, Text)
    forall a. a -> Maybe a
    Just (Bool
    True, DCItem -> Text
    dcText DCItem
    l)
            [DCItem]
    _ -> Maybe (Bool, Text)
    forall a. Maybe a
    Nothing
        Feed.XMLItem Element
    e ->
          (Element -> (Bool, Text)) -> Maybe Element -> Maybe (Bool, Text)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\Element
    e1 -> (Bool
    True, Element -> Text
    strContent Element
    e1)) (Maybe Element -> Maybe (Bool, Text))
    -> Maybe Element -> Maybe (Bool, Text)
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> Maybe Element
    findElement Name
    "guid" Element
    e Maybe Element -> Maybe Element -> Maybe Element
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "id") Element
    e
      where
        isId :: DCItem -> Bool
    isId DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Identifier

    getItemCategories :: Feed.Item -> [Text]
    getItemCategories :: Item -> [Text]
    getItemCategories Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    i -> (Category -> Text) -> [Category] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Category -> Text
    Atom.catTerm ([Category] -> [Text]) -> [Category] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Entry -> [Category]
    Atom.entryCategories Entry
    i
        Feed.RSSItem RSSItem
    i -> (RSSCategory -> Text) -> [RSSCategory] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map RSSCategory -> Text
    RSS.rssCategoryValue ([RSSCategory] -> [Text]) -> [RSSCategory] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ RSSItem -> [RSSCategory]
    RSS.rssItemCategories RSSItem
    i
        Feed.RSS1Item Item
    i -> [[Text]] -> [Text]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([[Text]] -> [Text]) -> [[Text]] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Item -> [[Text]]
    getCats1 Item
    i
       -- ToDo parse atom like tags too
        Feed.XMLItem Element
    i -> (Element -> Text) -> [Element] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Element -> Text
    strContent ([Element] -> [Text]) -> [Element] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Name -> Element -> [Element]
    findElements Name
    "category" Element
    i
        -- get RSS1 categories; either via DublinCore's subject (or taxonomy topics...not yet.)
      where
        getCats1 :: Item -> [[Text]]
    getCats1 Item
    i1 = (DCItem -> [Text]) -> [DCItem] -> [[Text]]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> [Text]
    T.words (Text -> [Text]) -> (DCItem -> Text) -> DCItem -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DCItem -> Text
    dcText) ([DCItem] -> [[Text]]) -> [DCItem] -> [[Text]]
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (\DCItem
    dc -> DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Subject) ([DCItem] -> [DCItem]) -> [DCItem] -> [DCItem]
    forall a b. (a -> b) -> a -> b
    $ Item -> [DCItem]
    RSS1.itemDC Item
    i1

    getItemRights :: ItemGetter Text
    getItemRights :: ItemGetter Text
    getItemRights Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e -> TextContent -> Text
    contentToStr (TextContent -> Text) -> Maybe TextContent -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Entry -> Maybe TextContent
    Atom.entryRights Entry
    e
        Feed.RSSItem RSSItem
    _ -> Maybe Text
    forall a. Maybe a
    Nothing
        Feed.RSS1Item Item
    i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DCItem -> Text
    dcText (Maybe DCItem -> Maybe Text) -> Maybe DCItem -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ [DCItem] -> Maybe DCItem
    forall a. [a] -> Maybe a
    listToMaybe ([DCItem] -> Maybe DCItem) -> [DCItem] -> Maybe DCItem
    forall a b. (a -> b) -> a -> b
    $ (DCItem -> Bool) -> [DCItem] -> [DCItem]
    forall a. (a -> Bool) -> [a] -> [a]
    filter DCItem -> Bool
    isRights (Item -> [DCItem]
    RSS1.itemDC Item
    i)
        Feed.XMLItem Element
    i -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "rights") Element
    i
      where
        isRights :: DCItem -> Bool
    isRights DCItem
    dc = DCItem -> DCInfo
    dcElt DCItem
    dc DCInfo -> DCInfo -> Bool
    forall a. Eq a => a -> a -> Bool
    == DCInfo
    DC_Rights

    getItemContent :: ItemGetter Text
    getItemContent :: ItemGetter Text
    getItemContent Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e -> EntryContent -> Text
    atomContentToStr (EntryContent -> Text) -> Maybe EntryContent -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Entry -> Maybe EntryContent
    Atom.entryContent Entry
    e
        Feed.RSSItem RSSItem
    e -> RSSItem -> Maybe Text
    RSS.rssItemContent RSSItem
    e
        Feed.RSS1Item Item
    _ -> Maybe Text
    forall a. Maybe a
    Nothing
        Feed.XMLItem Element
    i -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "content") Element
    i

    getItemSummary :: ItemGetter Text
    getItemSummary :: ItemGetter Text
    getItemSummary = ItemGetter Text
    getItemDescription

    getItemDescription :: ItemGetter Text
    getItemDescription :: ItemGetter Text
    getItemDescription Item
    it =
      case Item
    it of
        Feed.AtomItem Entry
    e -> TextContent -> Text
    contentToStr (TextContent -> Text) -> Maybe TextContent -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Entry -> Maybe TextContent
    Atom.entrySummary Entry
    e
        Feed.RSSItem RSSItem
    e -> RSSItem -> Maybe Text
    RSS.rssItemDescription RSSItem
    e
        Feed.RSS1Item Item
    i -> Item -> Maybe Text
    itemDesc Item
    i
        Feed.XMLItem Element
    i -> Element -> Text
    strContent (Element -> Text) -> Maybe Element -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Name -> Element -> Maybe Element
    findElement (Text -> Name
    atomName Text
    "summary") Element
    i
     -- strip away

    toStr :: Maybe (Either Text Text) -> Text
    toStr :: Maybe (Either Text Text) -> Text
    toStr Maybe (Either Text Text)
    Nothing = Text
    ""
    toStr (Just (Left Text
    x)) = Text
    x
    toStr (Just (Right Text
    x)) = Text
    x

    atomContentToStr :: EntryContent -> Text
    atomContentToStr :: EntryContent -> Text
    atomContentToStr EntryContent
    entry =
      case EntryContent
    entry of
        HTMLContent Text
    e -> Text
    e
        XHTMLContent Element
    e -> [Text] -> Text
    T.unlines ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ Element -> [Text]
    elementText Element
    e
        MixedContent Maybe Text
    text [Node]
    _ -> Text -> Maybe Text -> Text
    forall a. a -> Maybe a -> a
    fromMaybe Text
    "" Maybe Text
    text
        ExternalContent Maybe Text
    _ Text
    b -> Text
    b
        TextContent Text
    text -> Text
    text

    contentToStr :: TextContent -> Text
    contentToStr :: TextContent -> Text
    contentToStr TextContent
    x =
      case TextContent
    x of
        Atom.TextString Text
    s -> Text
    s
        Atom.HTMLString Text
    s -> Text
    s
        Atom.XHTMLString Element
    s -> Element -> Text
    strContent Element
    s