packages feed

ffeed-0.3: examples/TweetStream.hs

{-
  Demonstrates how to use the FriendFeed API by querying
  for the most recent public entries collected by FriendFeed.
  
  The API interaction happens in @showPublic@, with 
  @presentEntries@ outputting the results. The rest is option
  handling stuff + startup and shutdown code in @main@.
  
  Example command-line invocation:
  
  foo$ showPublic -u <your-username> -k <remote-key> \
         -s twitter -l 2
  
  showing the last 2 public tweets.

  where <your-username> and <remote-key> is your FriendFeed auth
  setup. Your remote key can be located here:
  
     http://friendfeed.com/remotekey
  
  However, since this example presently uses public methods not
  needing authentication, any old username/key combo will work.
  [Top tip: try leaving them out..]

  The @-s@ option constrains the entries from a given FriendFeed-supported
  service. @-l@ limits the length to given size (default: 30.)
-}
module Main(main) where

import FriendFeed.API
import FriendFeed.Updates

import Util.GetOpts
import System.IO
import System.Environment
import System.Exit

import Control.Monad
import Control.Concurrent
import Data.Maybe ( fromMaybe, isJust )

-- main functions for grabbing public entries + 
-- presenting them to the user:
getUpdateStream :: Maybe String -> Maybe Int -> Bool -> RoomName -> UpdateToken -> FFm [Entry]
getUpdateStream mbS mbL isList r tok = 
  (fromMaybe id (fmap forService   mbS)) $
  (fromMaybe id (fmap withPageSize mbL)) $
    (if isList then getUpdatesRoom else (if r == "home" then const getUpdatesHome else getUpdatesList)) r tok (Just 3)

presentEntries :: [Entry] -> IO ()
presentEntries [] = putStrLn "No public entries found!"
presentEntries xs = do
  putStrLn ("Most recent public entries: ")
  mapM_ presentEntry xs
 where
  presentEntry e = 
    putStrLn $ unlines
      [ "---"
      , " Title: " ++ entryTitle e
      , " Link:  " ++ entryLink e
      , " User:  " ++ resourceName (entryUser e)
      ]


-- start option handling

data Options
 = Options
    { optUser    :: Maybe String
    , optKey     :: Maybe String
    , optSize    :: Maybe Int
    , optService :: Maybe String
    , optRoom    :: Maybe String
    , optList    :: Maybe String
    }

nullOptions :: Options
nullOptions = Options
    { optUser     = Just ""
    , optKey      = Just ""
    , optSize     = Nothing
    , optService  = Nothing
    , optRoom     = Nothing
    , optList     = Nothing
    }
     
option_descr :: [OptDescr (Options -> Options)]
option_descr = 
  [ Option ['u'] ["user"]
           (ReqArg (\ x o -> o{optUser=Just x}) "USER")
	   "user name to authenticate as"
  , Option ['k','p'] ["key","remote-key"]
           (ReqArg (\ x o -> o{optKey=Just x}) "REMOTE KEY")
	   "the user's FriendFeed remote key"
  , Option ['l'] ["length"]
           (ReqArg (\ x o -> o{optSize=Just (read x)}) "SIZE")
	   "fetch SIZE entries"
  , Option ['s'] ["service"]
           (ReqArg (\ x o -> o{optService=Just x}) "SERVICE")
	   "limit query to given service name"
  , Option ['r'] ["room"]
           (ReqArg (\ x o -> o{optRoom=Just x}) "ROOM")
	   "get continual updates from the given room"
  , Option ['L'] ["list"]
           (ReqArg (\ x o -> o{optRoom=Just x}) "LIST")
	   "get continual updates from the given list (personal,favorites,etc.)"
  ]

parseOptions :: [String] -> (Options, [String], [String])
parseOptions argv = getOpt2 Permute option_descr argv nullOptions

processOptions :: IO Options
processOptions = do
  ls <- getArgs
  let (opts, ws, es) = parseOptions ls
  when (not $ null ws) $ do
    hPutStrLn stderr "Command-line warnings: " 
    hPutStrLn stderr (unlines ws)
  when (not $ null es) $ do
    hPutStrLn stderr (unlines es)
    hPutStrLn stderr ("(try '--help' for list of options supported.)")
    exitFailure
  return opts

-- end option handling

main :: IO ()
main = do
  opts <- processOptions
  case (optUser opts, optKey opts) of
    (Just u,Just k) -> do
       t  <- runFF u k (getUpdateInfo)
       let
        r   = fromMaybe (if isL then ls else "haskell") (optRoom opts)
        ls  = fromMaybe "home" (optRoom opts)
	isL = isJust (optList opts)
        loopIt = do
	   putStrLn "sampling.." 
	   hFlush stdout
           xs <- runFF u k (getUpdateStream (optService opts) (optSize opts) isL r (updToken t))
           presentEntries xs
	   hFlush stdout
	   threadDelay (fromIntegral (updInterval t * 1000 * 1000))
	   loopIt

       loopIt

    _ -> do
       putStrLn ("Both user and remote-key options are required.")
       return ()