chatwork 0.1.2.0 → 0.1.3.0
raw patch · 19 files changed
+185/−314 lines, 19 filesdep −retrydep ~http-typesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: retry
Dependency ranges changed: http-types
API changes (from Hackage documentation)
- ChatWork.MonadHttpIO: instance Network.HTTP.Req.MonadHttp GHC.Types.IO
- ChatWork.Utils: fixEmptyString :: Response BodyReader -> IO (Response BodyReader)
- ChatWork.Utils: fixEmptyStringManager :: IO Manager
- ChatWork.Utils: getHttpResponse' :: (HttpResponse a, MonadHttp m) => Proxy a -> Request -> Manager -> m a
+ ChatWork.Types: data JsonResponse' a
+ ChatWork.Types: instance Data.Aeson.Types.FromJSON.FromJSON a => Network.HTTP.Req.HttpResponse (ChatWork.Types.JsonResponse' a)
+ ChatWork.Types: jsonResponse' :: Proxy (JsonResponse' a)
- ChatWork.Client: class Client a where type ClientScheme a :: Scheme where {
+ ChatWork.Client: class Client a where {
- ChatWork.Types: type ChatWorkResponse a = JsonResponse (Either ChatWorkErrors a)
+ ChatWork.Types: type ChatWorkResponse a = JsonResponse' (Either ChatWorkErrors a)
Files
- LICENSE +1/−1
- chatwork.cabal +44/−44
- sample/Main.hs +7/−5
- src/ChatWork.hs +0/−3
- src/ChatWork/Endpoints/Contacts.hs +5/−6
- src/ChatWork/Endpoints/IncomingRequests.hs +8/−10
- src/ChatWork/Endpoints/Me.hs +5/−6
- src/ChatWork/Endpoints/My.hs +9/−9
- src/ChatWork/Endpoints/Rooms.hs +33/−34
- src/ChatWork/Internal.hs +0/−28
- src/ChatWork/MonadHttpIO.hs +0/−13
- src/ChatWork/Types.hs +28/−5
- src/ChatWork/Utils.hs +5/−126
- test/ChatWork/Endpoints/ContactsSpec.hs +1/−1
- test/ChatWork/Endpoints/IncomingRequestsSpec.hs +1/−1
- test/ChatWork/Endpoints/MeSpec.hs +8/−8
- test/ChatWork/Endpoints/MySpec.hs +8/−8
- test/ChatWork/Endpoints/RoomsSpec.hs +9/−6
- test/ChatWork/Test/MonadHttpIO.hs +13/−0
LICENSE view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 MATSUBARA Nobutada +Copyright (c) 2017-2018 MATSUBARA Nobutada Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
chatwork.cabal view
@@ -1,21 +1,23 @@--- This file has been generated from package.yaml by hpack version 0.17.1.+-- This file has been generated from package.yaml by hpack version 0.20.0. -- -- see: https://github.com/sol/hpack+--+-- hash: 421a3807b8f34719aa0095c9b4046dc4aec9ff8d6bafd0b51893c15f35bd1af4 -name: chatwork-version: 0.1.2.0-synopsis: The ChatWork API in Haskell-description: See README at <https://github.com/matsubara0507/chatwork#readme>-homepage: https://github.com/matsubara0507/chatwork#readme-bug-reports: https://github.com/matsubara0507/chatwork/issues-author: MATSUBARA Nobutada-maintainer: MATSUBARA Nobutada-copyright: 2017 MATSUBARA Nobutada-license: MIT-license-file: LICENSE-category: Web-build-type: Simple-cabal-version: >= 1.10+name: chatwork+version: 0.1.3.0+synopsis: The ChatWork API in Haskell+description: See README at <https://github.com/matsubara0507/chatwork#readme>+category: Web+homepage: https://github.com/matsubara0507/chatwork#readme+bug-reports: https://github.com/matsubara0507/chatwork/issues+author: MATSUBARA Nobutada+maintainer: MATSUBARA Nobutada+copyright: 2017-2018 MATSUBARA Nobutada+license: MIT+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10 source-repository head type: git@@ -25,6 +27,19 @@ hs-source-dirs: src ghc-options: -Wall+ build-depends:+ aeson >=1.0.2.1 && <1.3+ , aeson-casing >=0.1.0.5 && <0.2+ , base >=4.7 && <5+ , bytestring >=0.10.8.1 && <0.11+ , connection >=0.2.7 && <0.3+ , data-default-class >=0.1.2.0 && <0.2+ , http-api-data >=0.3.5 && <0.3.8+ , http-client >=0.5.5.0 && <0.6+ , http-client-tls >=0.3.3.1 && <0.4+ , http-types >=0.9.1 && <0.12+ , req >=1.0.0 && <1.1.0+ , text >=1.2.2.1 && <1.3 exposed-modules: ChatWork ChatWork.Client@@ -34,7 +49,6 @@ ChatWork.Endpoints.Contacts ChatWork.Endpoints.Rooms ChatWork.Endpoints.IncomingRequests- ChatWork.MonadHttpIO ChatWork.Types ChatWork.Types.Base ChatWork.Types.Error@@ -45,21 +59,7 @@ ChatWork.Types.IncomingRequests ChatWork.Utils other-modules:- ChatWork.Internal- build-depends:- base >=4.7 && <5- , aeson >=1.0.2.1 && <1.3- , aeson-casing >=0.1.0.5 && <0.2- , bytestring >=0.10.8.1 && <0.11- , connection >=0.2.7 && <0.3- , data-default-class >=0.1.2.0 && <0.2- , http-api-data >=0.3.5 && <0.3.8- , http-client >=0.5.5.0 && <0.6- , http-client-tls >=0.3.3.1 && <0.4- , http-types >=0.9.1 && <0.11- , req >=1.0.0 && <1.1.0- , retry >=0.7.0 && <0.8- , text >=1.2.2.1 && <1.3+ Paths_chatwork default-language: Haskell2010 executable sample-exe@@ -68,20 +68,21 @@ sample ghc-options: -Wall build-depends:- base >=4.7 && <5- , aeson >=1.0.2.1 && <1.3+ aeson >=1.0.2.1 && <1.3 , aeson-casing >=0.1.0.5 && <0.2+ , base >=4.7 && <5 , bytestring >=0.10.8.1 && <0.11+ , chatwork , connection >=0.2.7 && <0.3 , data-default-class >=0.1.2.0 && <0.2 , http-api-data >=0.3.5 && <0.3.8 , http-client >=0.5.5.0 && <0.6 , http-client-tls >=0.3.3.1 && <0.4- , http-types >=0.9.1 && <0.11+ , http-types >=0.9.1 && <0.12 , req >=1.0.0 && <1.1.0- , retry >=0.7.0 && <0.8 , text >=1.2.2.1 && <1.3- , chatwork+ other-modules:+ Paths_chatwork default-language: Haskell2010 test-suite spec@@ -92,22 +93,21 @@ src ghc-options: -Wall build-depends:- base >=4.7 && <5- , aeson >=1.0.2.1 && <1.3+ aeson >=1.0.2.1 && <1.3 , aeson-casing >=0.1.0.5 && <0.2+ , base >=4.7 && <5 , bytestring >=0.10.8.1 && <0.11 , connection >=0.2.7 && <0.3 , data-default-class >=0.1.2.0 && <0.2+ , hspec >=2.4.1 && <2.5 , http-api-data >=0.3.5 && <0.3.8 , http-client >=0.5.5.0 && <0.6 , http-client-tls >=0.3.3.1 && <0.4- , http-types >=0.9.1 && <0.11+ , http-types >=0.9.1 && <0.12 , req >=1.0.0 && <1.1.0- , retry >=0.7.0 && <0.8- , text >=1.2.2.1 && <1.3 , servant-server >=0.9.1.1 && <0.13+ , text >=1.2.2.1 && <1.3 , warp >=3.2.11 && <3.3- , hspec >=2.4.1 && <2.5 other-modules: ChatWork.Endpoints.ContactsSpec ChatWork.Endpoints.IncomingRequestsSpec@@ -116,6 +116,7 @@ ChatWork.Endpoints.RoomsSpec ChatWork.Test.Client ChatWork.Test.MockServer+ ChatWork.Test.MonadHttpIO ChatWork.Test.Types ChatWork.Test.Values ChatWork.Test.Values.Contacts@@ -131,8 +132,6 @@ ChatWork.Endpoints.Me ChatWork.Endpoints.My ChatWork.Endpoints.Rooms- ChatWork.Internal- ChatWork.MonadHttpIO ChatWork.Types ChatWork.Types.Base ChatWork.Types.Contacts@@ -142,4 +141,5 @@ ChatWork.Types.My ChatWork.Types.Rooms ChatWork.Utils+ Paths_chatwork default-language: Haskell2010
sample/Main.hs view
@@ -1,21 +1,23 @@ {-# LANGUAGE OverloadedStrings #-} import ChatWork -import Network.HTTP.Req (responseBody) +import Control.Monad.IO.Class (liftIO) +import Data.Default.Class +import Network.HTTP.Req (responseBody, runReq) main :: IO () -main = do +main = runReq def $ do let token = "xxx" client = ChatWorkClient token (Right myId) <- (fmap meToAccountId . responseBody) <$> getMe client (Right ids) <- (fmap (fmap contactToAccountId) . responseBody) <$> getContacts client - (Right roomId) <- (fmap getRoomId . responseBody) <$> createRoom client - (CreateRoomParams Nothing Nothing [myId] (Just ids) Nothing "test") + (Right roomId) <- (fmap getRoomId . responseBody) <$> + createRoom client (CreateRoomParams Nothing Nothing [myId] (Just ids) Nothing "test") _ <- postMessage client roomId "Wellcome to Test Room !!" _ <- createTask client roomId (CreateTaskParams "Self-Introduction" Nothing ids) - putStrLn $ + liftIO . putStrLn $ "I Created Test Room and Tasks that Self-Introductions to my contact members."
src/ChatWork.hs view
@@ -11,11 +11,8 @@ , module ChatWork.Endpoints -- * Response and request param type definitions , module ChatWork.Types - -- * Define MonadHttp type class instance of IO - , module ChatWork.MonadHttpIO ) where import ChatWork.Client import ChatWork.Endpoints -import ChatWork.MonadHttpIO () import ChatWork.Types
src/ChatWork/Endpoints/Contacts.hs view
@@ -7,11 +7,10 @@ ( getContacts ) where -import ChatWork.Client (Client (..)) -import ChatWork.Internal (req) -import ChatWork.Types (ChatWorkResponse, Contacts) -import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), - jsonResponse, (/:)) +import ChatWork.Client (Client (..)) +import ChatWork.Types (ChatWorkResponse, Contacts, jsonResponse') +import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), req, + (/:)) getContacts :: (MonadHttp m, Client c) => c -> m (ChatWorkResponse Contacts) -getContacts c = req GET (baseUrl c /: "contacts") NoReqBody jsonResponse $ mkHeader c +getContacts c = req GET (baseUrl c /: "contacts") NoReqBody jsonResponse' $ mkHeader c
src/ChatWork/Endpoints/IncomingRequests.hs view
@@ -9,23 +9,21 @@ , rejectIncomingRequest ) where -import ChatWork.Client (Client (..)) -import ChatWork.Internal (req) -import ChatWork.Types (AcceptedIncomingRequest, ChatWorkResponse, - IncomingRequests) -import Network.HTTP.Req (DELETE (..), GET (..), MonadHttp, - NoReqBody (..), PUT (..), jsonResponse, - (/:), (/~)) +import ChatWork.Client (Client (..)) +import ChatWork.Types (AcceptedIncomingRequest, ChatWorkResponse, + IncomingRequests, jsonResponse') +import Network.HTTP.Req (DELETE (..), GET (..), MonadHttp, + NoReqBody (..), PUT (..), req, (/:), (/~)) getIncomingRequests :: (MonadHttp m, Client c) => c -> m (ChatWorkResponse IncomingRequests) -getIncomingRequests c = req GET (baseUrl c /: "incoming_requests") NoReqBody jsonResponse $ mkHeader c +getIncomingRequests c = req GET (baseUrl c /: "incoming_requests") NoReqBody jsonResponse' $ mkHeader c -- | -- argument 'Int' is `request_id` acceptIncomingRequest :: (MonadHttp m, Client c) => c -> Int -> m (ChatWorkResponse AcceptedIncomingRequest) -acceptIncomingRequest c n = req PUT (baseUrl c /: "incoming_requests" /~ n ) NoReqBody jsonResponse $ mkHeader c +acceptIncomingRequest c n = req PUT (baseUrl c /: "incoming_requests" /~ n ) NoReqBody jsonResponse' $ mkHeader c -- | -- argument 'Int' is `request_id` rejectIncomingRequest :: (MonadHttp m, Client c) => c -> Int -> m (ChatWorkResponse ()) -rejectIncomingRequest c n = req DELETE (baseUrl c /: "incoming_requests" /~ n) NoReqBody jsonResponse $ mkHeader c +rejectIncomingRequest c n = req DELETE (baseUrl c /: "incoming_requests" /~ n) NoReqBody jsonResponse' $ mkHeader c
src/ChatWork/Endpoints/Me.hs view
@@ -7,11 +7,10 @@ ( getMe ) where -import ChatWork.Client (Client (..)) -import ChatWork.Internal (req) -import ChatWork.Types (ChatWorkResponse, Me) -import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), - jsonResponse, (/:)) +import ChatWork.Client (Client (..)) +import ChatWork.Types (ChatWorkResponse, Me, jsonResponse') +import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), req, + (/:)) getMe :: (MonadHttp m, Client c) => c -> m (ChatWorkResponse Me) -getMe c = req GET (baseUrl c /: "me") NoReqBody jsonResponse $ mkHeader c +getMe c = req GET (baseUrl c /: "me") NoReqBody jsonResponse' $ mkHeader c
src/ChatWork/Endpoints/My.hs view
@@ -8,19 +8,19 @@ , getMyTasks ) where -import ChatWork.Client (Client (..)) -import ChatWork.Internal (req) -import ChatWork.Types (ChatWorkResponse, GetMyTasksParams (..), - MyStatus, MyTasks, ToReqParam (..)) -import Data.Monoid ((<>)) -import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), - jsonResponse, (/:)) +import ChatWork.Client (Client (..)) +import ChatWork.Types (ChatWorkResponse, GetMyTasksParams (..), + MyStatus, MyTasks, ToReqParam (..), + jsonResponse') +import Data.Monoid ((<>)) +import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), req, + (/:)) getMyStatus :: (MonadHttp m, Client c) => c -> m (ChatWorkResponse MyStatus) -getMyStatus c = req GET (baseUrl c /: "my" /: "status") NoReqBody jsonResponse $ mkHeader c +getMyStatus c = req GET (baseUrl c /: "my" /: "status") NoReqBody jsonResponse' $ mkHeader c getMyTasks :: (MonadHttp m, Client c) => c -> GetMyTasksParams -> m (ChatWorkResponse MyTasks) -getMyTasks c params = req GET (baseUrl c /: "my" /: "tasks") NoReqBody jsonResponse $ mkHeader c <> params' +getMyTasks c params = req GET (baseUrl c /: "my" /: "tasks") NoReqBody jsonResponse' $ mkHeader c <> params' where params' = toReqParam "assigned_by_account_id" (getMyTasksAssignedByAccountId params) <> toReqParam "status" (getMyTasksStatus params)
src/ChatWork/Endpoints/Rooms.hs view
@@ -28,31 +28,30 @@ , getFile ) where -import ChatWork.Client (Client (..)) -import ChatWork.Internal (req) -import ChatWork.Types (AccountId, ChatWorkResponse, - CreateRoomParams (..), - CreateTaskParams (..), CreateUrlFlag, - DeleteRoomActionType (..), File, Files, - Force, GetTasksParams (..), Members, - MembersPermission, Message, MessageBody, - MessageIdWrap, Messages, RoomDetail, - RoomIdWrap, RoomMembersParams (..), - RoomTask, RoomTasks, Rooms, TaskIdsWrap, - ToReqParam (..), UpdateRoomParams (..)) -import ChatWork.Utils (DELETE2 (..)) -import Data.Bool (bool) -import Data.Monoid ((<>)) -import Data.Text (Text) -import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), - POST (..), PUT (..), ReqBodyUrlEnc (..), - jsonResponse, (/:), (/~), (=:)) +import ChatWork.Client (Client (..)) +import ChatWork.Types (AccountId, ChatWorkResponse, + CreateRoomParams (..), CreateTaskParams (..), + CreateUrlFlag, DeleteRoomActionType (..), + File, Files, Force, GetTasksParams (..), + Members, MembersPermission, Message, + MessageBody, MessageIdWrap, Messages, + RoomDetail, RoomIdWrap, + RoomMembersParams (..), RoomTask, RoomTasks, + Rooms, TaskIdsWrap, ToReqParam (..), + UpdateRoomParams (..), jsonResponse') +import ChatWork.Utils (DELETE2 (..)) +import Data.Bool (bool) +import Data.Monoid ((<>)) +import Data.Text (Text) +import Network.HTTP.Req (GET (..), MonadHttp, NoReqBody (..), + POST (..), PUT (..), ReqBodyUrlEnc (..), req, + (/:), (/~), (=:)) getRooms :: (MonadHttp m, Client c) => c -> m (ChatWorkResponse Rooms) -getRooms c = req GET (baseUrl c /: "rooms") NoReqBody jsonResponse $ mkHeader c +getRooms c = req GET (baseUrl c /: "rooms") NoReqBody jsonResponse' $ mkHeader c createRoom :: (MonadHttp m, Client c) => c -> CreateRoomParams -> m (ChatWorkResponse RoomIdWrap) -createRoom c params = req POST (baseUrl c /: "rooms") (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +createRoom c params = req POST (baseUrl c /: "rooms") (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = toReqParam "description" (cRoomDescription params) <> toReqParam "icon_preset" (cIconPreset params) @@ -64,12 +63,12 @@ -- | -- argumrnt 'Int' is `room_id`. getRoom :: (MonadHttp m, Client c) => c -> Int -> m (ChatWorkResponse RoomDetail) -getRoom c n = req GET (baseUrl c /: "rooms" /~ n) NoReqBody jsonResponse $ mkHeader c +getRoom c n = req GET (baseUrl c /: "rooms" /~ n) NoReqBody jsonResponse' $ mkHeader c -- | -- argumrnt 'Int' is `room_id`. updateRoom :: (MonadHttp m, Client c) => c -> Int -> UpdateRoomParams -> m (ChatWorkResponse RoomIdWrap) -updateRoom c n params = req PUT (baseUrl c /: "rooms" /~ n) (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +updateRoom c n params = req PUT (baseUrl c /: "rooms" /~ n) (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = toReqParam "description" (uRoomDescription params) <> toReqParam "icon_preset" (uIconPreset params) @@ -90,19 +89,19 @@ -- | -- argumrnt 'Int' is `room_id`. deleteRoom' :: (MonadHttp m, Client c) => c -> Int -> DeleteRoomActionType -> m (ChatWorkResponse ()) -deleteRoom' c n action = req DELETE2 (baseUrl c /: "rooms" /~ n) (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +deleteRoom' c n action = req DELETE2 (baseUrl c /: "rooms" /~ n) (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = "action_type" =: show action -- | -- argumrnt 'Int' is `room_id`. getMembers :: (MonadHttp m, Client c) => c -> Int -> m (ChatWorkResponse Members) -getMembers c n = req GET (baseUrl c /: "rooms" /~ n /: "members") NoReqBody jsonResponse $ mkHeader c +getMembers c n = req GET (baseUrl c /: "rooms" /~ n /: "members") NoReqBody jsonResponse' $ mkHeader c -- | -- argumrnt 'Int' is `room_id`. updateMembersPermission :: (MonadHttp m, Client c) => c -> Int -> RoomMembersParams -> m (ChatWorkResponse MembersPermission) -updateMembersPermission c n params = req PUT (baseUrl c /: "rooms" /~ n /: "members") (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +updateMembersPermission c n params = req PUT (baseUrl c /: "rooms" /~ n /: "members") (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = toReqParam "members_admin_ids" (getAdminIds params) <> toReqParam "members_member_ids" (getMemberIds params) @@ -111,14 +110,14 @@ -- | -- argumrnt 'Int' is `room_id`. getMessages :: (MonadHttp m, Client c) => c -> Int -> Maybe Force -> m (ChatWorkResponse Messages) -getMessages c n force = req GET (baseUrl c /: "rooms" /~ n /: "messages") NoReqBody jsonResponse $ mkHeader c <> params' +getMessages c n force = req GET (baseUrl c /: "rooms" /~ n /: "messages") NoReqBody jsonResponse' $ mkHeader c <> params' where params' = toReqParam "force" (bool 0 (1 :: Int) <$> force) -- | -- argumrnt 'Int' is `room_id`. postMessage :: (MonadHttp m, Client c) => c -> Int -> MessageBody -> m (ChatWorkResponse MessageIdWrap) -postMessage c n body = req POST (baseUrl c /: "rooms" /~ n /: "messages") (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +postMessage c n body = req POST (baseUrl c /: "rooms" /~ n /: "messages") (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = toReqParam "body" body @@ -126,12 +125,12 @@ -- argumrnt 'Int' is `room_id`. -- argumrnt 'Text' is `message_id`. getMessage :: (MonadHttp m, Client c) => c -> Int -> Text -> m (ChatWorkResponse Message) -getMessage c rid mid = req GET (baseUrl c /: "rooms" /~ rid /: "messages" /~ mid) NoReqBody jsonResponse $ mkHeader c +getMessage c rid mid = req GET (baseUrl c /: "rooms" /~ rid /: "messages" /~ mid) NoReqBody jsonResponse' $ mkHeader c -- | -- argumrnt 'Int' is `room_id`. getRoomTasks :: (MonadHttp m, Client c) => c -> Int -> GetTasksParams -> m (ChatWorkResponse RoomTasks) -getRoomTasks c n params = req GET (baseUrl c /: "rooms" /~ n /: "tasks") NoReqBody jsonResponse $ mkHeader c <> params' +getRoomTasks c n params = req GET (baseUrl c /: "rooms" /~ n /: "tasks") NoReqBody jsonResponse' $ mkHeader c <> params' where params' = toReqParam "account_id" (getTaskAccountId params) <> toReqParam "assigned_by_account_id" (getTaskAssignedByAccountId params) @@ -140,7 +139,7 @@ -- | -- argumrnt 'Int' is `room_id`. createTask :: (MonadHttp m, Client c) => c -> Int -> CreateTaskParams -> m (ChatWorkResponse TaskIdsWrap) -createTask c n params = req POST (baseUrl c /: "rooms" /~ n /: "tasks") (ReqBodyUrlEnc params') jsonResponse $ mkHeader c +createTask c n params = req POST (baseUrl c /: "rooms" /~ n /: "tasks") (ReqBodyUrlEnc params') jsonResponse' $ mkHeader c where params' = toReqParam "body" (getTaskBody params) <> toReqParam "limit" (getTaskLimit params) @@ -149,12 +148,12 @@ -- argumrnt first 'Int' is `room_id`. -- argumrnt second 'Int' is `task_id`. getRoomTask :: (MonadHttp m, Client c) => c -> Int -> Int -> m (ChatWorkResponse RoomTask) -getRoomTask c rid tid = req GET (baseUrl c /: "rooms" /~ rid /: "tasks" /~ tid) NoReqBody jsonResponse $ mkHeader c +getRoomTask c rid tid = req GET (baseUrl c /: "rooms" /~ rid /: "tasks" /~ tid) NoReqBody jsonResponse' $ mkHeader c -- | -- argumrnt 'Int' is `room_id`. getFiles :: (MonadHttp m, Client c) => c -> Int -> Maybe AccountId -> m (ChatWorkResponse Files) -getFiles c rid aid = req GET (baseUrl c /: "rooms" /~ rid /: "files") NoReqBody jsonResponse $ mkHeader c <> params' +getFiles c rid aid = req GET (baseUrl c /: "rooms" /~ rid /: "files") NoReqBody jsonResponse' $ mkHeader c <> params' where params' = toReqParam "account_id" aid @@ -162,6 +161,6 @@ -- argumrnt first 'Int' is `room_id`. -- argumrnt second 'Int' is `file_id`. getFile :: (MonadHttp m, Client c) => c -> Int -> Int -> Maybe CreateUrlFlag -> m (ChatWorkResponse File) -getFile c rid fid flag = req GET (baseUrl c /: "rooms" /~ rid /: "files" /~ fid) NoReqBody jsonResponse $ mkHeader c <> params' +getFile c rid fid flag = req GET (baseUrl c /: "rooms" /~ rid /: "files" /~ fid) NoReqBody jsonResponse' $ mkHeader c <> params' where params' = toReqParam "create_download_url" (bool 0 (1 :: Int) <$> flag)
− src/ChatWork/Internal.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MultiParamTypeClasses #-} - -module ChatWork.Internal - ( req - ) where - -import ChatWork.Utils (getHttpResponse') - -import Data.Proxy (Proxy) -import Network.HTTP.Req (AllowsBody, HttpBody, HttpBodyAllowed, - HttpMethod, HttpResponse, MonadHttp, Option, - ProvidesBody, Url, req') - --- | --- Helper function for req' --- getHttpResponse' is used my custamize Manager - -req :: - ( MonadHttp m, HttpMethod method, HttpBody body, HttpResponse response - , HttpBodyAllowed (AllowsBody method) (ProvidesBody body)) - => method - -> Url scheme - -> body - -> Proxy response - -> Option scheme - -> m response -req method url body = flip (req' method url body) . getHttpResponse'
− src/ChatWork/MonadHttpIO.hs
@@ -1,13 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-} - --- | --- This module is that define MonadHttp type class instance of IO. --- if you want other definition, don't import this module. - -module ChatWork.MonadHttpIO where - -import Control.Exception (throwIO) -import Network.HTTP.Req - -instance MonadHttp IO where - handleHttpException = throwIO
src/ChatWork/Types.hs view
@@ -1,11 +1,14 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module ChatWork.Types ( + JsonResponse' + , jsonResponse' -- * type synonym of Response Json - ChatWorkResponse + , ChatWorkResponse -- * Helper type class for constructing Request paramater , ToReqParam(..) @@ -22,17 +25,37 @@ import ChatWork.Types.Base (IconPreset, TaskStatus) import ChatWork.Types.Error (ChatWorkErrors) - import Control.Applicative ((<|>)) -import Data.Aeson (FromJSON (..)) +import Control.Exception (throwIO) +import Data.Aeson (FromJSON (..), eitherDecode) +import qualified Data.ByteString.Lazy as BL import Data.Monoid (Monoid) +import Data.Proxy (Proxy (..)) import Data.Text (Text, pack) -import Network.HTTP.Req (JsonResponse, QueryParam, +import qualified Network.HTTP.Client as L +import Network.HTTP.Req (HttpException (..), + HttpResponse (..), QueryParam, (=:)) +newtype JsonResponse' a = JsonResponse' (L.Response a) + +instance FromJSON a => HttpResponse (JsonResponse' a) where + type HttpResponseBody (JsonResponse' a) = a + toVanillaResponse (JsonResponse' r) = r + getHttpResponse r = do + chunks <- L.brConsume (L.responseBody r) + let + body = if null chunks then "[]" else BL.fromChunks chunks + case eitherDecode body of + Left e -> throwIO (JsonHttpException e) + Right x -> return $ JsonResponse' (x <$ r) + +jsonResponse' :: Proxy (JsonResponse' a) +jsonResponse' = Proxy + -- | -- Wrapper type synonym of 'JsonResponse' and 'ChatWorkErrors' -type ChatWorkResponse a = JsonResponse (Either ChatWorkErrors a) +type ChatWorkResponse a = JsonResponse' (Either ChatWorkErrors a) instance {-# OVERLAPS #-} (FromJSON a) => FromJSON (Either ChatWorkErrors a) where parseJSON v = (Left <$> parseJSON v) <|> (Right <$> parseJSON v)
src/ChatWork/Utils.hs view
@@ -1,140 +1,19 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeFamilies #-} module ChatWork.Utils ( - -- * Custamize Managaer - getHttpResponse' - , fixEmptyStringManager - , fixEmptyString -- * DELETE HTTP method with paramater - , DELETE2(..) + DELETE2(..) -- * help to make 'FromJSON' instance , strLength ) where -import Control.Exception (bracket, handle, mask_, throwIO, - try) -import Control.Monad ((>=>)) -import Control.Monad.IO.Class (MonadIO (..)) -import Control.Retry (retrying) -import Data.ByteString (ByteString) -import qualified Data.ByteString as B -import Data.Default.Class (def) -import Data.IORef (modifyIORef', newIORef, - readIORef, writeIORef) -import Data.List (lookup) -import Data.Maybe (fromMaybe) -import Data.Proxy (Proxy (..)) -import Network.Connection (initConnectionContext) -import Network.HTTP.Client (BodyReader, Manager, - ManagerSettings (..), Request, - Response (..)) -import qualified Network.HTTP.Client as L -import qualified Network.HTTP.Client.Internal as LI -import qualified Network.HTTP.Client.TLS as L -import Network.HTTP.Req (AllowsBody (..), - CanHaveBody (..), - HttpConfig (..), - HttpException (..), - HttpMethod (..), - HttpResponse (..), - MonadHttp (..), getHttpConfig) -import Network.HTTP.Types (methodDelete) -import Network.HTTP.Types.Header (hContentLength) - --- | --- Helper function that use custamized Manager -getHttpResponse' :: (HttpResponse a, MonadHttp m) => Proxy a -> Request -> Manager -> m a -getHttpResponse' Proxy request _ = do - HttpConfig {..} <- getHttpConfig - let wrapVanilla = handle (throwIO . VanillaHttpException) - wrapExc = handle (throwIO . LI.toHttpException request) - withRRef = bracket - (newIORef Nothing) - (readIORef >=> mapM_ L.responseClose) - (liftIO . try . wrapVanilla . wrapExc) (withRRef $ \rref -> do - manager <- fixEmptyStringManager - let openResponse = mask_ $ do - r <- readIORef rref - mapM_ L.responseClose r - r' <- L.responseOpen request manager - writeIORef rref (Just r') - return r' - r <- retrying - httpConfigRetryPolicy - (\st r -> return $ httpConfigRetryJudge st r) - (const openResponse) - (preview, r') <- grabPreview bodyPreviewLength r - mapM_ LI.throwHttp (httpConfigCheckResponse request r' preview) - getHttpResponse r') - >>= either handleHttpException return - -fixEmptyStringManager :: IO Manager -fixEmptyStringManager = do - context <- initConnectionContext - let settings = L.mkManagerSettingsContext (Just context) def Nothing - L.newManager $ settings { managerModifyResponse = fixEmptyString } - --- | --- if response is no contents, replace "[]". --- aeson return parse error when response is no content response -fixEmptyString :: Response BodyReader -> IO (Response BodyReader) -fixEmptyString res = do - reader <- LI.constBodyReader ["[]"] - let - contentLength = fromMaybe "0" $ lookup hContentLength (responseHeaders res) - return $ if contentLength /= "0" then res else res { responseBody = reader } - ----------------------------------------------------------------------------- --- Helpers for response interpretations - -grabPreview :: Int -> L.Response L.BodyReader -> IO (ByteString, L.Response L.BodyReader) -grabPreview nbytes r = do - let br = L.responseBody r - (target, leftover, done) <- brReadN br nbytes - nref <- newIORef (0 :: Int) - let br' = do - n <- readIORef nref - let incn = modifyIORef' nref (+ 1) - case n of - 0 -> do - incn - if B.null target - then br' - else return target - 1 -> do - incn - if B.null leftover - then br' - else return leftover - _ -> - if done - then return B.empty - else br - return (target, r { L.responseBody = br' }) - -brReadN :: L.BodyReader -> Int -> IO (ByteString, ByteString, Bool) -brReadN br n = go 0 id id - where - go !tlen t l = do - chunk <- br - if B.null chunk - then return (r t, r l, True) - else do - let (target, leftover) = B.splitAt (n - tlen) chunk - tlen' = B.length target - t' = t . (target:) - l' = l . (leftover:) - if tlen + tlen' < n - then go (tlen + tlen') t' l' - else return (r t', r l', False) - r f = B.concat (f []) - -bodyPreviewLength :: Num a => a -bodyPreviewLength = 1024 +import Data.Proxy (Proxy (..)) +import Network.HTTP.Req (AllowsBody (..), CanHaveBody (..), + HttpMethod (..)) +import Network.HTTP.Types (methodDelete) -- | -- if want to use Delete HTTP methos with request param, use this type.
test/ChatWork/Endpoints/ContactsSpec.hs view
@@ -4,9 +4,9 @@ ) where import ChatWork.Endpoints.Contacts (getContacts) -import ChatWork.MonadHttpIO () import ChatWork.Test.Client (TestClient (..)) import ChatWork.Test.MockServer (runMockServer) +import ChatWork.Test.MonadHttpIO () import ChatWork.Test.Values.Contacts (contacts) import Network.HTTP.Req (responseBody) import Test.Hspec (Spec, around_, context,
test/ChatWork/Endpoints/IncomingRequestsSpec.hs view
@@ -6,9 +6,9 @@ import ChatWork.Endpoints.IncomingRequests (acceptIncomingRequest, getIncomingRequests, rejectIncomingRequest) -import ChatWork.MonadHttpIO () import ChatWork.Test.Client (TestClient (..)) import ChatWork.Test.MockServer (runMockServer) +import ChatWork.Test.MonadHttpIO () import ChatWork.Test.Values.IncomingRequests (acceptedIncomingRequest, incomingRequests) import Network.HTTP.Req (responseBody)
test/ChatWork/Endpoints/MeSpec.hs view
@@ -3,14 +3,14 @@ , spec ) where -import ChatWork.Endpoints.Me (getMe) -import ChatWork.MonadHttpIO () -import ChatWork.Test.Client (TestClient (..)) -import ChatWork.Test.MockServer (runMockServer) -import ChatWork.Test.Values.Me (me) -import Network.HTTP.Req (responseBody) -import Test.Hspec (Spec, around_, context, describe, - hspec, it, shouldReturn) +import ChatWork.Endpoints.Me (getMe) +import ChatWork.Test.Client (TestClient (..)) +import ChatWork.Test.MockServer (runMockServer) +import ChatWork.Test.MonadHttpIO () +import ChatWork.Test.Values.Me (me) +import Network.HTTP.Req (responseBody) +import Test.Hspec (Spec, around_, context, describe, + hspec, it, shouldReturn) main :: IO () main = hspec spec
test/ChatWork/Endpoints/MySpec.hs view
@@ -3,14 +3,14 @@ , spec ) where -import ChatWork.Endpoints.My (getMyStatus, getMyTasks) -import ChatWork.MonadHttpIO () -import ChatWork.Test.Client (TestClient (..)) -import ChatWork.Test.MockServer (runMockServer) -import ChatWork.Test.Values.My (getMyTasksParams, myStatus, myTasks) -import Network.HTTP.Req (responseBody) -import Test.Hspec (Spec, around_, context, describe, - hspec, it, shouldReturn) +import ChatWork.Endpoints.My (getMyStatus, getMyTasks) +import ChatWork.Test.Client (TestClient (..)) +import ChatWork.Test.MockServer (runMockServer) +import ChatWork.Test.MonadHttpIO () +import ChatWork.Test.Values.My (getMyTasksParams, myStatus, myTasks) +import Network.HTTP.Req (responseBody) +import Test.Hspec (Spec, around_, context, describe, + hspec, it, shouldReturn) main :: IO () main = hspec spec
test/ChatWork/Endpoints/RoomsSpec.hs view
@@ -12,14 +12,17 @@ getRooms, leaveRoom, postMessage, updateMembersPermission, updateRoom) -import ChatWork.MonadHttpIO () import ChatWork.Test.Client (TestClient (..)) import ChatWork.Test.MockServer (runMockServer) -import ChatWork.Test.Values.Rooms (file, files, members, - membersPermission, message, - messageId, messages, roomDetail, - roomId, roomTask, roomTasks, rooms, - taskIds, createRoomParams, updateRoomParams, createTaskParams, roomMembersParams, getTasksParams) +import ChatWork.Test.MonadHttpIO () +import ChatWork.Test.Values.Rooms (createRoomParams, createTaskParams, + file, files, getTasksParams, + members, membersPermission, + message, messageId, messages, + roomDetail, roomId, + roomMembersParams, roomTask, + roomTasks, rooms, taskIds, + updateRoomParams) import Network.HTTP.Req (responseBody) import Test.Hspec (Spec, around_, context, describe, hspec, it, shouldReturn)
+ test/ChatWork/Test/MonadHttpIO.hs view
@@ -0,0 +1,13 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} + +-- | +-- This module is that define MonadHttp type class instance of IO. +-- if you want other definition, don't import this module. + +module ChatWork.Test.MonadHttpIO where + +import Control.Exception (throwIO) +import Network.HTTP.Req + +instance MonadHttp IO where + handleHttpException = throwIO