packages feed

hackernews-1.0.0.0: ghcjs-src/Web/HackerNews.hs

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings   #-}
------------------------------------------------------------------------------
-- |
-- Module      : Web.HackerNews
-- Copyright   : (c) David Johnson, 2014-2016
-- Maintainer  : djohnson.m@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
------------------------------------------------------------------------------
module Web.HackerNews
       ( -- * API functions
         getItem
       , getUser
       , getMaxItem
       , getTopStories
       , getNewStories
       , getBestStories
       , getAskStories
       , getShowStories
       , getJobStories
       , getUpdates
       -- * Core Types
       , Item        (..)
       , User        (..)
       , Updates     (..)
       , MaxItem     (..)
       , TopStories  (..)
       , NewStories  (..)
       , BestStories (..)
       , AskStories  (..)
       , ShowStories (..)
       , JobStories  (..)
       --- * Supporting Types
       , UserId      (..)
       , ItemId      (..)
       , Deleted     (..)
       , ItemType    (..)
       , UserName    (..)
       , Time        (..)
       , ItemText    (..)
       , Dead        (..)
       , Parent      (..)
       , Kids        (..)
       , URL         (..)
       , Score       (..)
       , Title       (..)
       , Parts       (..)
       , Descendants (..)
       , Delay       (..)
       , Created     (..)
       , Karma       (..)
       , About       (..)
       , Submitted   (..)
       ) where

------------------------------------------------------------------------------
import Data.Aeson
import Data.Monoid
import JavaScript.Web.XMLHttpRequest
import Data.String.Conversions
import Data.JSString
import Data.JSString.Text

import Web.HackerNews.Types

-- | Retrieve `Item`
getItem :: ItemId -> IO (Either HackerNewsError Item)
getItem (ItemId x) = issueAjax (Just "item") $ textToJSString $ cs (show x)

-- | Retrieve `User`
getUser :: UserId -> IO (Either HackerNewsError User)
getUser (UserId u) = issueAjax (Just "user") (textToJSString u)

-- | Retrieve `MaxItem`
getMaxItem :: IO (Either HackerNewsError MaxItem)
getMaxItem = issueAjax Nothing "maxitem"

-- | Retrieve `TopStories`
getTopStories :: IO (Either HackerNewsError TopStories)
getTopStories = issueAjax Nothing "topstories"

-- | Retrieve `NewStories`
getNewStories :: IO (Either HackerNewsError NewStories)
getNewStories = issueAjax Nothing "newstories"

-- | Retrieve `BestStories`
getBestStories :: IO (Either HackerNewsError BestStories)
getBestStories = issueAjax Nothing "beststories"

-- | Retrieve `AskStories`
getAskStories :: IO (Either HackerNewsError AskStories)
getAskStories = issueAjax Nothing "askstories"

-- | Retrieve `ShowStories`
getShowStories :: IO (Either HackerNewsError ShowStories)
getShowStories = issueAjax Nothing "showstories"

-- | Retrieve `JobStories`
getJobStories :: IO (Either HackerNewsError JobStories)
getJobStories = issueAjax Nothing "jobstories"

-- | Retrieve `Updates`
getUpdates :: IO (Either HackerNewsError Updates)
getUpdates = issueAjax Nothing "updates"

issueAjax :: FromJSON a => Maybe JSString -> JSString -> IO (Either HackerNewsError a)
issueAjax maybePath uri = do
  response <- xhrByteString request
  pure $ case contents response of
    Nothing -> Left NotFound
    Just "null" -> Left NotFound
    Just x ->
      case eitherDecode (cs x) of
        Left l -> Left $ DecodeFailureError (cs l) mempty
        Right r -> Right r
    where
      request = Request GET url Nothing [] False NoData
      url = "https://hacker-news.firebaseio.com/v0/"
              <> maybe mempty (\path -> path <> "/") maybePath
              <> uri
              <> ".json"