module Network.Google.Books (
ShelfId
, listBooks
, listBookshelves
) where
import Control.Monad (liftM)
import Data.Maybe (fromMaybe)
import Network.Google (AccessToken, appendQuery, doRequest, makeRequest)
import Network.HTTP.Conduit (Request)
import Text.JSON (JSObject, JSValue(..), Result(Ok), decode, fromJSObject, toJSObject, valFromObj)
booksHost :: String
booksHost = "www.googleapis.com"
booksApi :: (String, String)
booksApi = ("Gdata-version", "2")
type ShelfId = String
listBookshelves ::
AccessToken
-> IO JSValue
listBookshelves accessToken =
doRequest $ booksRequest accessToken Nothing 0
listBookshelfIds ::
AccessToken
-> IO [String]
listBookshelfIds accessToken =
do
JSObject result <- listBookshelves accessToken
let
extractId :: JSValue -> String
extractId (JSObject x) =
let
y :: Rational
Ok (JSRational _ y) = valFromObj "id" x
in
show (round y :: Int)
items :: [JSValue]
Ok (JSArray items) = valFromObj "items" result
return $ map extractId items
listBooks ::
AccessToken
-> [ShelfId]
-> IO JSValue
listBooks accessToken shelves =
do
shelves' <-
if null shelves
then listBookshelfIds accessToken
else return shelves
results <- mapM (listShelfBooks accessToken) shelves'
return $ JSArray results
listShelfBooks ::
AccessToken
-> ShelfId
-> IO JSValue
listShelfBooks accessToken shelf =
do
x <- listShelfBooks' accessToken shelf Nothing
let
y :: [JSValue]
y = concatMap items x
JSObject o = head x
z :: [(String, JSValue)]
z = fromJSObject o
u :: [(String, JSValue)]
u = filter (\w -> fst w /= "items") z
v :: [(String, JSValue)]
v = ("items", JSArray y) : u
return $ JSObject $ toJSObject v
listShelfBooks' ::
AccessToken
-> ShelfId
-> Maybe Int
-> IO [JSValue]
listShelfBooks' accessToken shelf startIndex =
do
let
startIndex' :: Int
startIndex' = fromMaybe 0 startIndex
books <- doRequest $ booksRequest accessToken (Just shelf) startIndex'
let
startIndex'' = startIndex' + length (items books)
liftM (books :) $
if startIndex' + 1 <= totalItems books
then listShelfBooks' accessToken shelf $ Just startIndex''
else return []
totalItems ::
JSValue
-> Int
totalItems (JSObject books) =
let
Ok count = "totalItems" `valFromObj` books
in
count
items ::
JSValue
-> [JSValue]
items (JSObject books) =
let
list = "items" `valFromObj` books
f (Ok x) = x
f _ = []
in
f list
booksRequest ::
AccessToken
-> Maybe ShelfId
-> Int
-> Request m
booksRequest accessToken shelf startIndex =
appendQuery
[
("maxResults", "40")
, ("startIndex", show startIndex)
]
$
makeRequest accessToken booksApi "GET"
(
booksHost
, "/books/v1/mylibrary/bookshelves" ++ maybe "" (\x -> "/" ++ x ++ "/volumes") shelf
)