packages feed

heddit-0.0.2: examples/Streaming.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedLabels #-}

-- | This example will show how to use the 'stream' action to get an infinite
-- stream of new 'Paginable' things. In this example, we will stream new
-- submissions, filter them based on some criteria, and print out some information
-- about them. In a real program, instead of simply printing information, we could
-- take some 'MonadReddit' action instead, such as replying to them
--
-- Running this example will produce the following type of output (truncated for
-- readability here):
--
-- > On 2021-07-18 07:32:21 UTC u/Pututu_Life posted "What is your go to comfort ..
-- > On 2021-07-18 07:32:29 UTC u/Kenney93 posted "What do you do when you are ...
-- > On 2021-07-18 07:32:45 UTC u/CYS801 posted "What is your proudest ...
-- > On 2021-07-18 07:32:53 UTC u/Ambitious-Ad8598 posted "What is the name of ...
-- > On 2021-07-18 07:33:08 UTC u/Additional_Quantity5 posted "What is your ...
--
module Streaming where

import           Conduit

import           Data.Generics.Labels  ()
import           Data.Generics.Wrapped
import           Data.Text             ( Text )
import qualified Data.Text             as T
import qualified Data.Text.IO          as T

import           Lens.Micro.Platform

import           Network.Reddit

main :: IO ()
main = loadClient Nothing >>= (`runReddit` streamed)
  where
    -- We can use r/askreddit, which has a fairly high and steady
    -- volume of new submissions being posted
    streamed = streamSubmissions =<< mkSubredditName "askreddit"

-- | Run the stream until interrupted
streamSubmissions :: MonadReddit m => SubredditName -> m ()
streamSubmissions subname = runConduit
    $ stream (Just True) -- This will discard elements that were
                         -- already "in" the stream before starting,
                         -- so we only get actually new submissions
             action
    .| filterC isAskingWhat
    .| submissionInfo
    .| mapM_C (liftIO . T.putStrLn) -- This will look nicer than
                                    -- @printC@
  where
    action = getNewSubmissions subname

-- | A silly heuristic to detect questions asking "what ... ?". Of course
-- this will miss questions using the popular format "...s of Reddit,
-- what...?", but r/askreddit is high-volume enough that it will still
-- catch a lot of submissions
isAskingWhat :: Submission -> Bool
isAskingWhat s = case s ^? #title . to (T.words . T.toLower) . _head of
    Just "what" -> True
    _           -> False

-- | Print some information about the submission
submissionInfo :: Monad m => ConduitT Submission Text m ()
submissionInfo = awaitForever $ \s -> yield
    $ mconcat [ "On "
              , s ^. #created . to show . packed
              , " u/"
              , s ^. #author & wrappedTo
              , " posted "
              , "\""
              , s ^. #title
              , "\""
              ]