{-# 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
  , 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 fe :: Feed
fe =
  case Feed
fe of
    AtomFeed f :: 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 f :: 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 f :: 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 f :: Element
f ->
      case Name -> Element -> [Element]
findElements "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 "entry") Element
f
        l :: [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 ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> (Person -> Text) -> Maybe Person -> Maybe Text
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 f :: RSS
f -> RSSChannel -> Maybe Text
RSS.rssEditor (RSS -> RSSChannel
RSS.rssChannel RSS
f)
    Feed.RSS1Feed f :: Feed
f ->
      (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "editor" Element
e1
        Nothing ->
          (Element -> Text) -> Maybe Element -> Maybe Text
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 "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 "author") Element
f
  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

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

getFeedHome :: FeedGetter URLString
getFeedHome :: FeedGetter Text
getFeedHome ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> (Link -> Text) -> Maybe Link -> Maybe Text
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 f :: RSS
f -> Text -> Maybe Text
forall a. a -> Maybe a
Just (RSSChannel -> Text
RSS.rssLink (RSS -> RSSChannel
RSS.rssChannel RSS
f))
    Feed.RSS1Feed f :: Feed
f -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Channel -> Text
RSS1.channelURI (Feed -> Channel
RSS1.feedChannel Feed
f))
    Feed.XMLFeed f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "link" Element
e1
        Nothing -> Name -> Element -> Maybe Text
attributeText "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 "link") Element
f
  where
    isSelf :: Link -> Bool
isSelf lr :: 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
== "self"

getFeedHTML :: FeedGetter URLString
getFeedHTML :: FeedGetter Text
getFeedHTML ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> (Link -> Text) -> Maybe Link -> Maybe Text
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 f :: RSS
f -> Text -> Maybe Text
forall a. a -> Maybe a
Just (RSSChannel -> Text
RSS.rssLink (RSS -> RSSChannel
RSS.rssChannel RSS
f))
    Feed.RSS1Feed f :: Feed
f -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Channel -> Text
RSS1.channelURI (Feed -> Channel
RSS1.feedChannel Feed
f))
    Feed.XMLFeed f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "link" Element
e1
        Nothing -> Maybe Text
forall a. Maybe a
Nothing -- ToDo parse atom like tags
  where
    isSelf :: Link -> Bool
isSelf lr :: 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
== "alternate") Bool -> Bool -> Bool
&& Maybe Text -> Bool
isHTMLType (Link -> Maybe Text
linkType Link
lr)
    isHTMLType :: Maybe Text -> Bool
isHTMLType (Just str :: Text
str) = "html" Text -> Text -> Bool
`T.isSuffixOf` Text
str
    isHTMLType _ = Bool
True -- if none given, assume html.

getFeedDescription :: FeedGetter Text
getFeedDescription :: FeedGetter Text
getFeedDescription ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> (TextContent -> Text) -> Maybe TextContent -> Maybe Text
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 f :: 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 f :: Feed
f -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Channel -> Text
RSS1.channelDesc (Feed -> Channel
RSS1.feedChannel Feed
f))
    Feed.XMLFeed f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "description" Element
e1
        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 "subtitle") Element
f

getFeedPubDate :: FeedGetter DateString
getFeedPubDate :: FeedGetter Text
getFeedPubDate ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: 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 f :: RSS
f -> RSSChannel -> Maybe Text
RSS.rssPubDate (RSS -> RSSChannel
RSS.rssChannel RSS
f)
    Feed.RSS1Feed f :: Feed
f ->
      (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "pubDate" Element
e1
        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 "published") 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

getFeedLastUpdate :: FeedGetter Text
getFeedLastUpdate :: FeedGetter Text
getFeedLastUpdate ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: 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 f :: RSS
f -> RSSChannel -> Maybe Text
RSS.rssPubDate (RSS -> RSSChannel
RSS.rssChannel RSS
f)
    Feed.RSS1Feed f :: Feed
f ->
      (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "pubDate" Element
e1
        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 "updated") 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

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

getFeedLogoLink :: FeedGetter URLString
getFeedLogoLink :: FeedGetter Text
getFeedLogoLink ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> Feed -> Maybe Text
Atom.feedLogo Feed
f
    Feed.RSSFeed f :: RSS
f -> (RSSImage -> Text) -> Maybe RSSImage -> Maybe Text
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 f :: 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 f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just ch :: Element
ch -> do
          Element
e1 <- Name -> Element -> Maybe Element
findElement "image" Element
ch
          Element
v <- Name -> Element -> Maybe Element
findElement "url" Element
e1
          Text -> Maybe Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> Text
strContent Element
v)
        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 "logo") Element
f

getFeedLanguage :: FeedGetter Text
getFeedLanguage :: FeedGetter Text
getFeedLanguage ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> Name -> Element -> Maybe Text
attributeText "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 "" (Feed -> [Attr]
Atom.feedAttrs Feed
f)
    Feed.RSSFeed f :: RSS
f -> RSSChannel -> Maybe Text
RSS.rssLanguage (RSS -> RSSChannel
RSS.rssChannel RSS
f)
    Feed.RSS1Feed f :: Feed
f ->
      (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 f :: Element
f -> do
      Element
ch <- Name -> Element -> Maybe Element
findElement "channel" Element
f
      Element
e1 <- Name -> Element -> Maybe Element
findElement "language" Element
ch
      Text -> Maybe Text
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 dc :: 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 ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: 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 (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 f :: 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 (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 f :: 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
        ls :: [DCItem]
ls -> (DCItem -> (Text, Maybe Text)) -> [DCItem] -> [(Text, Maybe Text)]
forall a b. (a -> b) -> [a] -> [b]
map (\l :: DCItem
l -> (DCItem -> Text
dcText DCItem
l, Maybe Text
forall a. Maybe a
Nothing)) [DCItem]
ls
    Feed.XMLFeed f :: Element
f ->
      case [Element] -> (Element -> [Element]) -> Maybe Element -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Name -> Element -> [Element]
findElements "category") (Name -> Element -> Maybe Element
findElement "channel" Element
f) of
        ls :: [Element]
ls -> (Element -> (Text, Maybe Text))
-> [Element] -> [(Text, Maybe Text)]
forall a b. (a -> b) -> [a] -> [b]
map (\l :: Element
l -> (Text -> (Element -> Text) -> Maybe Element -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe "" Element -> Text
strContent (Name -> Element -> Maybe Element
findElement "term" Element
l), Name -> Element -> Maybe Text
attributeText "domain" Element
l)) [Element]
ls
       -- ToDo parse atom like tags too
  where
    isCat :: DCItem -> Bool
isCat dc :: 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 ft :: Feed
ft =
  case Feed
ft of
    Feed.AtomFeed f :: Feed
f -> do
      Generator
gen <- Feed -> Maybe Generator
Atom.feedGenerator Feed
f
      Generator -> Maybe Text
Atom.genURI Generator
gen
    Feed.RSSFeed f :: RSS
f -> RSSChannel -> Maybe Text
RSS.rssGenerator (RSS -> RSSChannel
RSS.rssChannel RSS
f)
    Feed.RSS1Feed f :: Feed
f ->
      (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 f :: Element
f ->
      case Name -> Element -> Maybe Element
findElement "channel" Element
f of
        Just e1 :: 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 "generator" Element
e1
        Nothing -> Name -> Element -> Maybe Text
attributeText "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 "generator") 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

type ItemGetter a = Feed.Item -> Maybe a

getItemTitle :: ItemGetter Text
getItemTitle :: ItemGetter Text
getItemTitle it :: Item
it =
  case Item
it of
    Feed.AtomItem i :: 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 i :: RSSItem
i -> RSSItem -> Maybe Text
RSS.rssItemTitle RSSItem
i
    Feed.RSS1Item i :: Item
i -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Item -> Text
RSS1.itemTitle Item
i)
    Feed.XMLItem e :: Element
e -> (Element -> Text) -> Maybe Element -> Maybe Text
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 "title" Element
e Maybe Element -> Maybe Element -> Maybe Element
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Name -> Element -> Maybe Element
findChild (Text -> Name
atomName "title") Element
e

getItemLink :: ItemGetter Text
getItemLink :: ItemGetter Text
getItemLink it :: 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 i :: Entry
i -> (Link -> Text) -> Maybe Link -> Maybe Text
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 i :: RSSItem
i -> RSSItem -> Maybe Text
RSS.rssItemLink RSSItem
i
    Feed.RSS1Item i :: Item
i -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Item -> Text
RSS1.itemLink Item
i)
    Feed.XMLItem i :: Element
i ->
      (Element -> Text) -> Maybe Element -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Element -> Text
strContent (Name -> Element -> Maybe Element
findElement "link" Element
i) Maybe Text -> Maybe Text -> Maybe Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Name -> Element -> Maybe Element
findChild (Text -> Name
atomName "link") Element
i Maybe Element -> (Element -> Maybe Text) -> Maybe Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Name -> Element -> Maybe Text
attributeText "href")
  where
    isSelf :: Link -> Bool
isSelf lr :: 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
== "alternate") Bool -> Bool -> Bool
&& Maybe Text -> Bool
isHTMLType (Link -> Maybe Text
linkType Link
lr)
    isHTMLType :: Maybe Text -> Bool
isHTMLType (Just str :: Text
str) = "html" Text -> Text -> Bool
`T.isSuffixOf` Text
str
    isHTMLType _ = 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 :: ItemGetter (Maybe t)
getItemPublishDate it :: 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 "%H:%M:%S%Z")
      rfc3339DateFormat2 :: String
rfc3339DateFormat2 = Maybe String -> String
iso8601DateFormat (String -> Maybe String
forall a. a -> Maybe a
Just "%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 (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Maybe t -> Maybe t -> Maybe t
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 (\fmt :: 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 (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 it :: Item
it =
  case Item
it of
    Feed.AtomItem i :: 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 i :: RSSItem
i -> RSSItem -> Maybe Text
RSS.rssItemPubDate RSSItem
i
    Feed.RSS1Item i :: Item
i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 e :: Element
e ->
      (Element -> Text) -> Maybe Element -> Maybe Text
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 "pubDate" Element
e Maybe Element -> Maybe Element -> Maybe Element
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Name -> Element -> Maybe Element
findElement (Text -> Name
atomName "published") Element
e
  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

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 it :: Item
it =
  case Item
it of
    Feed.AtomItem i :: Entry
i -> (Person -> Text) -> Maybe Person -> Maybe Text
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 i :: RSSItem
i -> RSSItem -> Maybe Text
RSS.rssItemAuthor RSSItem
i
    Feed.RSS1Item i :: Item
i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 e :: Element
e ->
      (Element -> Text) -> Maybe Element -> Maybe Text
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 "author" Element
e Maybe Element -> Maybe Element -> Maybe Element
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Name -> Element -> Maybe Element
findElement (Text -> Name
atomName "author") Element
e Maybe Element -> (Element -> Maybe Element) -> Maybe Element
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Name -> Element -> Maybe Element
findElement (Text -> Name
atomName "name"))
  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

getItemCommentLink :: ItemGetter URLString
getItemCommentLink :: ItemGetter Text
getItemCommentLink it :: Item
it =
  case Item
it
       -- look up the 'replies' HTML link relation on the entry:
        of
    Feed.AtomItem e :: Entry
e -> (Link -> Text) -> Maybe Link -> Maybe Text
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 i :: RSSItem
i -> RSSItem -> Maybe Text
RSS.rssItemComments RSSItem
i
    Feed.RSS1Item i :: Item
i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 i :: Element
i ->
      (Element -> Text) -> Maybe Element -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Element -> Text
strContent (Name -> Element -> Maybe Element
findElement "comments" Element
i) Maybe Text -> Maybe Text -> Maybe Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
      (Name -> Element -> Maybe Element
findElement (Text -> Name
atomName "link") Element
i Maybe Element -> (Element -> Maybe Text) -> Maybe Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Name -> Element -> Maybe Text
attributeText "href")
  where
    isReplies :: Link -> Bool
isReplies lr :: 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
== "replies"
    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

getItemEnclosure :: ItemGetter (URI, Maybe Text, Maybe Integer)
getItemEnclosure :: ItemGetter (Text, Maybe Text, Maybe Integer)
getItemEnclosure it :: Item
it =
  case Item
it of
    Feed.AtomItem e :: 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
        (l :: Link
l:_) -> (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))
        _ -> Maybe (Text, Maybe Text, Maybe Integer)
forall a. Maybe a
Nothing
    Feed.RSSItem i :: RSSItem
i ->
      (RSSEnclosure -> (Text, Maybe Text, Maybe Integer))
-> Maybe RSSEnclosure -> Maybe (Text, Maybe Text, Maybe Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        (\e :: 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 i :: Item
i ->
      case Item -> [ContentInfo]
RSS1.itemContent Item
i of
        [] -> Maybe (Text, Maybe Text, Maybe Integer)
forall a. Maybe a
Nothing
        (c :: ContentInfo
c:_) -> (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 "" (ContentInfo -> Maybe Text
RSS1.contentURI ContentInfo
c), ContentInfo -> Maybe Text
RSS1.contentFormat ContentInfo
c, Maybe Integer
forall a. Maybe a
Nothing)
    Feed.XMLItem e :: Element
e ->
      (Element -> (Text, Maybe Text, Maybe Integer))
-> Maybe Element -> Maybe (Text, Maybe Text, Maybe Integer)
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 "enclosure" Element
e Maybe Element -> Maybe Element -> Maybe Element
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Name -> Element -> Maybe Element
findElement (Text -> Name
atomName "enclosure") Element
e
  where
    isEnc :: Link -> Bool
isEnc lr :: 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
== "enclosure"
    readLength :: Maybe Text -> Maybe a
readLength Nothing = Maybe a
forall a. Maybe a
Nothing
    readLength (Just str :: Text
str) =
      case Reader a
forall a. Integral a => Reader a
decimal Text
str of
        Right (v :: a
v, _) -> a -> Maybe a
forall a. a -> Maybe a
Just a
v
        _ -> Maybe a
forall a. Maybe a
Nothing
    xmlToEnclosure :: Element -> (Text, Maybe Text, Maybe a)
xmlToEnclosure e :: Element
e =
      ( Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe "" (Name -> Element -> Maybe Text
attributeText "url" Element
e)
      , Name -> Element -> Maybe Text
attributeText "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 "length" Element
e)

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

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

getItemCategories :: Feed.Item -> [Text]
getItemCategories :: Item -> [Text]
getItemCategories it :: Item
it =
  case Item
it of
    Feed.AtomItem i :: 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 i :: 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 i :: 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 i :: 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 "category" Element
i
    -- get RSS1 categories; either via DublinCore's subject (or taxonomy topics...not yet.)
  where
    getCats1 :: Item -> [[Text]]
getCats1 i1 :: 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 (\dc :: 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 it :: Item
it =
  case Item
it of
    Feed.AtomItem e :: 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 _ -> Maybe Text
forall a. Maybe a
Nothing
    Feed.RSS1Item i :: Item
i -> (DCItem -> Text) -> Maybe DCItem -> Maybe Text
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 i :: 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 "rights") Element
i
  where
    isRights :: DCItem -> Bool
isRights dc :: DCItem
dc = DCItem -> DCInfo
dcElt DCItem
dc DCInfo -> DCInfo -> Bool
forall a. Eq a => a -> a -> Bool
== DCInfo
DC_Rights

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

getItemDescription :: ItemGetter Text
getItemDescription :: ItemGetter Text
getItemDescription it :: Item
it =
  case Item
it of
    Feed.AtomItem e :: 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 e :: RSSItem
e -> RSSItem -> Maybe Text
RSS.rssItemDescription RSSItem
e
    Feed.RSS1Item i :: Item
i -> Item -> Maybe Text
itemDesc Item
i
    Feed.XMLItem i :: 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 "summary") Element
i
 -- strip away

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

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