pinboard 0.8.10 → 0.9.0
raw patch · 12 files changed
+332/−323 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Pinboard.ApiTypes: fromDoneResult :: DoneResult -> ()
- Pinboard.ApiTypes: fromJsonTagMap :: JsonTagMap -> TagMap
- Pinboard.ApiTypes: fromTextResult :: TextResult -> Text
- Pinboard.ApiTypes: fromUpdateTime :: UpdateTime -> UTCTime
- Pinboard.ApiTypes: instance Data DoneResult
- Pinboard.ApiTypes: instance Data JsonTagMap
- Pinboard.ApiTypes: instance Data Note
- Pinboard.ApiTypes: instance Data NoteList
- Pinboard.ApiTypes: instance Data NoteListItem
- Pinboard.ApiTypes: instance Data Post
- Pinboard.ApiTypes: instance Data PostDates
- Pinboard.ApiTypes: instance Data Posts
- Pinboard.ApiTypes: instance Data Suggested
- Pinboard.ApiTypes: instance Data TextResult
- Pinboard.ApiTypes: instance Data UpdateTime
- Pinboard.ApiTypes: instance Eq DoneResult
- Pinboard.ApiTypes: instance Eq JsonTagMap
- Pinboard.ApiTypes: instance Eq Note
- Pinboard.ApiTypes: instance Eq NoteList
- Pinboard.ApiTypes: instance Eq NoteListItem
- Pinboard.ApiTypes: instance Eq Post
- Pinboard.ApiTypes: instance Eq PostDates
- Pinboard.ApiTypes: instance Eq Posts
- Pinboard.ApiTypes: instance Eq Suggested
- Pinboard.ApiTypes: instance Eq TextResult
- Pinboard.ApiTypes: instance Eq UpdateTime
- Pinboard.ApiTypes: instance FromJSON DoneResult
- Pinboard.ApiTypes: instance FromJSON JsonTagMap
- Pinboard.ApiTypes: instance FromJSON Note
- Pinboard.ApiTypes: instance FromJSON NoteList
- Pinboard.ApiTypes: instance FromJSON NoteListItem
- Pinboard.ApiTypes: instance FromJSON Post
- Pinboard.ApiTypes: instance FromJSON PostDates
- Pinboard.ApiTypes: instance FromJSON Posts
- Pinboard.ApiTypes: instance FromJSON Suggested
- Pinboard.ApiTypes: instance FromJSON TextResult
- Pinboard.ApiTypes: instance FromJSON UpdateTime
- Pinboard.ApiTypes: instance Ord DoneResult
- Pinboard.ApiTypes: instance Ord Note
- Pinboard.ApiTypes: instance Ord NoteList
- Pinboard.ApiTypes: instance Ord NoteListItem
- Pinboard.ApiTypes: instance Ord Post
- Pinboard.ApiTypes: instance Ord PostDates
- Pinboard.ApiTypes: instance Ord Posts
- Pinboard.ApiTypes: instance Ord Suggested
- Pinboard.ApiTypes: instance Ord TextResult
- Pinboard.ApiTypes: instance Ord UpdateTime
- Pinboard.ApiTypes: instance Show DoneResult
- Pinboard.ApiTypes: instance Show JsonTagMap
- Pinboard.ApiTypes: instance Show Note
- Pinboard.ApiTypes: instance Show NoteList
- Pinboard.ApiTypes: instance Show NoteListItem
- Pinboard.ApiTypes: instance Show Post
- Pinboard.ApiTypes: instance Show PostDates
- Pinboard.ApiTypes: instance Show Posts
- Pinboard.ApiTypes: instance Show Suggested
- Pinboard.ApiTypes: instance Show TextResult
- Pinboard.ApiTypes: instance Show UpdateTime
- Pinboard.ApiTypes: instance ToJSON JsonTagMap
- Pinboard.ApiTypes: instance ToJSON Note
- Pinboard.ApiTypes: instance ToJSON NoteList
- Pinboard.ApiTypes: instance ToJSON NoteListItem
- Pinboard.ApiTypes: instance ToJSON Post
- Pinboard.ApiTypes: instance ToJSON PostDates
- Pinboard.ApiTypes: instance ToJSON Posts
- Pinboard.ApiTypes: instance ToJSON Suggested
- Pinboard.ApiTypes: instance ToJSON [Suggested]
- Pinboard.ApiTypes: instance Typeable DoneResult
- Pinboard.ApiTypes: instance Typeable JsonTagMap
- Pinboard.ApiTypes: instance Typeable Note
- Pinboard.ApiTypes: instance Typeable NoteList
- Pinboard.ApiTypes: instance Typeable NoteListItem
- Pinboard.ApiTypes: instance Typeable Post
- Pinboard.ApiTypes: instance Typeable PostDates
- Pinboard.ApiTypes: instance Typeable Posts
- Pinboard.ApiTypes: instance Typeable Suggested
- Pinboard.ApiTypes: instance Typeable TextResult
- Pinboard.ApiTypes: instance Typeable UpdateTime
- Pinboard.ApiTypes: noteCreatedAt :: Note -> UTCTime
- Pinboard.ApiTypes: noteHash :: Note -> Text
- Pinboard.ApiTypes: noteId :: Note -> Text
- Pinboard.ApiTypes: noteLength :: Note -> Int
- Pinboard.ApiTypes: noteListCount :: NoteList -> Int
- Pinboard.ApiTypes: noteListItemCreatedAt :: NoteListItem -> UTCTime
- Pinboard.ApiTypes: noteListItemHash :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemId :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemLength :: NoteListItem -> Int
- Pinboard.ApiTypes: noteListItemTitle :: NoteListItem -> Text
- Pinboard.ApiTypes: noteListItemUpdatedAt :: NoteListItem -> UTCTime
- Pinboard.ApiTypes: noteListItems :: NoteList -> [NoteListItem]
- Pinboard.ApiTypes: noteText :: Note -> Text
- Pinboard.ApiTypes: noteTitle :: Note -> Text
- Pinboard.ApiTypes: noteUpdatedAt :: Note -> UTCTime
- Pinboard.ApiTypes: postDatesCount :: PostDates -> [DateCount]
- Pinboard.ApiTypes: postDatesTag :: PostDates -> Text
- Pinboard.ApiTypes: postDatesUser :: PostDates -> Text
- Pinboard.ApiTypes: postDescription :: Post -> Text
- Pinboard.ApiTypes: postExtended :: Post -> Text
- Pinboard.ApiTypes: postHash :: Post -> Text
- Pinboard.ApiTypes: postHref :: Post -> Text
- Pinboard.ApiTypes: postMeta :: Post -> Text
- Pinboard.ApiTypes: postShared :: Post -> Bool
- Pinboard.ApiTypes: postTags :: Post -> [Tag]
- Pinboard.ApiTypes: postTime :: Post -> UTCTime
- Pinboard.ApiTypes: postToread :: Post -> Bool
- Pinboard.ApiTypes: postsDate :: Posts -> UTCTime
- Pinboard.ApiTypes: postsPosts :: Posts -> [Post]
- Pinboard.ApiTypes: postsUser :: Posts -> Text
- Pinboard.Client: apiToken :: PinboardConfig -> ByteString
- Pinboard.Client: debug :: PinboardConfig -> Bool
- Pinboard.Client: mgrOpen :: MonadIO m => m (Either SomeException Manager)
- Pinboard.Client: mgrOpenRaw :: MonadIO m => m Manager
- Pinboard.Client.Error: BadRequest :: PinboardErrorHTTPCode
- Pinboard.Client.Error: ConnectionFailure :: PinboardErrorType
- Pinboard.Client.Error: Forbidden :: PinboardErrorHTTPCode
- Pinboard.Client.Error: HttpStatusFailure :: PinboardErrorType
- Pinboard.Client.Error: NotFound :: PinboardErrorHTTPCode
- Pinboard.Client.Error: ParseFailure :: PinboardErrorType
- Pinboard.Client.Error: PinboardError :: PinboardErrorType -> Text -> Maybe PinboardErrorCode -> Maybe Text -> Maybe PinboardErrorHTTPCode -> PinboardError
- Pinboard.Client.Error: PinboardServerError :: PinboardErrorHTTPCode
- Pinboard.Client.Error: RequestFailed :: PinboardErrorHTTPCode
- Pinboard.Client.Error: TooManyRequests :: PinboardErrorHTTPCode
- Pinboard.Client.Error: UnAuthorized :: PinboardErrorHTTPCode
- Pinboard.Client.Error: UnknownError :: PinboardErrorCode
- Pinboard.Client.Error: UnknownErrorType :: PinboardErrorType
- Pinboard.Client.Error: UnknownHTTPCode :: PinboardErrorHTTPCode
- Pinboard.Client.Error: data PinboardError
- Pinboard.Client.Error: data PinboardErrorCode
- Pinboard.Client.Error: data PinboardErrorHTTPCode
- Pinboard.Client.Error: data PinboardErrorType
- Pinboard.Client.Error: defaultPinboardError :: PinboardError
- Pinboard.Client.Error: errorCode :: PinboardError -> Maybe PinboardErrorCode
- Pinboard.Client.Error: errorHTTP :: PinboardError -> Maybe PinboardErrorHTTPCode
- Pinboard.Client.Error: errorMsg :: PinboardError -> Text
- Pinboard.Client.Error: errorParam :: PinboardError -> Maybe Text
- Pinboard.Client.Error: errorType :: PinboardError -> PinboardErrorType
- Pinboard.Client.Error: instance Show PinboardError
- Pinboard.Client.Error: instance Show PinboardErrorCode
- Pinboard.Client.Error: instance Show PinboardErrorHTTPCode
- Pinboard.Client.Error: instance Show PinboardErrorType
- Pinboard.Client.Types: Count :: Int -> Param
- Pinboard.Client.Types: Date :: Day -> Param
- Pinboard.Client.Types: DateTime :: UTCTime -> Param
- Pinboard.Client.Types: Description :: Text -> Param
- Pinboard.Client.Types: Extended :: Text -> Param
- Pinboard.Client.Types: Format :: ResultFormatType -> Param
- Pinboard.Client.Types: FormatJson :: ResultFormatType
- Pinboard.Client.Types: FormatXml :: ResultFormatType
- Pinboard.Client.Types: FromDateTime :: UTCTime -> Param
- Pinboard.Client.Types: Meta :: Int -> Param
- Pinboard.Client.Types: New :: Text -> Param
- Pinboard.Client.Types: Old :: Text -> Param
- Pinboard.Client.Types: PinboardConfig :: ByteString -> Bool -> PinboardConfig
- Pinboard.Client.Types: PinboardRequest :: Text -> [Param] -> PinboardRequest
- Pinboard.Client.Types: Replace :: Bool -> Param
- Pinboard.Client.Types: Results :: Int -> Param
- Pinboard.Client.Types: Shared :: Bool -> Param
- Pinboard.Client.Types: Start :: Int -> Param
- Pinboard.Client.Types: Tag :: Text -> Param
- Pinboard.Client.Types: Tags :: Text -> Param
- Pinboard.Client.Types: ToDateTime :: UTCTime -> Param
- Pinboard.Client.Types: ToRead :: Bool -> Param
- Pinboard.Client.Types: Url :: Text -> Param
- Pinboard.Client.Types: apiToken :: PinboardConfig -> ByteString
- Pinboard.Client.Types: data Param
- Pinboard.Client.Types: data PinboardConfig
- Pinboard.Client.Types: data PinboardRequest
- Pinboard.Client.Types: data ResultFormatType
- Pinboard.Client.Types: debug :: PinboardConfig -> Bool
- Pinboard.Client.Types: instance Eq Param
- Pinboard.Client.Types: instance Eq ResultFormatType
- Pinboard.Client.Types: instance Show Param
- Pinboard.Client.Types: instance Show PinboardConfig
- Pinboard.Client.Types: instance Show PinboardRequest
- Pinboard.Client.Types: instance Show ResultFormatType
- Pinboard.Client.Types: requestParams :: PinboardRequest -> [Param]
- Pinboard.Client.Types: requestPath :: PinboardRequest -> Text
- Pinboard.Client.Types: runPinboardT :: PinboardEnv -> PinboardT m a -> m (Either PinboardError a)
- Pinboard.Client.Types: type MonadPinboard m = (Functor m, Applicative m, Monad m, MonadIO m, MonadIO m, MonadReader PinboardEnv m, MonadError PinboardError m)
- Pinboard.Client.Types: type ParamsBS = [(ByteString, ByteString)]
- Pinboard.Client.Types: type PinboardEnv = (PinboardConfig, Manager)
- Pinboard.Client.Types: type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a
- Pinboard.Client.Util: (</>) :: (Monoid m, IsString m) => m -> m -> m
- Pinboard.Client.Util: encodeParams :: [Param] -> ParamsBS
- Pinboard.Client.Util: ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest
- Pinboard.Client.Util: mkConfig :: PinboardConfig
- Pinboard.Client.Util: paramToName :: Param -> Text
- Pinboard.Client.Util: paramToText :: Param -> (Text, Text)
- Pinboard.Client.Util: paramsToByteString :: (Monoid m, IsString m) => [(m, m)] -> m
- Pinboard.Client.Util: toText :: Show a => a -> Text
- Pinboard.Client.Util: toTextLower :: Show a => a -> Text
+ Pinboard.ApiTypes: [fromDoneResult] :: DoneResult -> ()
+ Pinboard.ApiTypes: [fromJsonTagMap] :: JsonTagMap -> TagMap
+ Pinboard.ApiTypes: [fromTextResult] :: TextResult -> Text
+ Pinboard.ApiTypes: [fromUpdateTime] :: UpdateTime -> UTCTime
+ Pinboard.ApiTypes: [noteCreatedAt] :: Note -> UTCTime
+ Pinboard.ApiTypes: [noteHash] :: Note -> Text
+ Pinboard.ApiTypes: [noteId] :: Note -> Text
+ Pinboard.ApiTypes: [noteLength] :: Note -> Int
+ Pinboard.ApiTypes: [noteListCount] :: NoteList -> Int
+ Pinboard.ApiTypes: [noteListItemCreatedAt] :: NoteListItem -> UTCTime
+ Pinboard.ApiTypes: [noteListItemHash] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemId] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemLength] :: NoteListItem -> Int
+ Pinboard.ApiTypes: [noteListItemTitle] :: NoteListItem -> Text
+ Pinboard.ApiTypes: [noteListItemUpdatedAt] :: NoteListItem -> UTCTime
+ Pinboard.ApiTypes: [noteListItems] :: NoteList -> [NoteListItem]
+ Pinboard.ApiTypes: [noteText] :: Note -> Text
+ Pinboard.ApiTypes: [noteTitle] :: Note -> Text
+ Pinboard.ApiTypes: [noteUpdatedAt] :: Note -> UTCTime
+ Pinboard.ApiTypes: [postDatesCount] :: PostDates -> [DateCount]
+ Pinboard.ApiTypes: [postDatesTag] :: PostDates -> Text
+ Pinboard.ApiTypes: [postDatesUser] :: PostDates -> Text
+ Pinboard.ApiTypes: [postDescription] :: Post -> Text
+ Pinboard.ApiTypes: [postExtended] :: Post -> Text
+ Pinboard.ApiTypes: [postHash] :: Post -> Text
+ Pinboard.ApiTypes: [postHref] :: Post -> Text
+ Pinboard.ApiTypes: [postMeta] :: Post -> Text
+ Pinboard.ApiTypes: [postShared] :: Post -> Bool
+ Pinboard.ApiTypes: [postTags] :: Post -> [Tag]
+ Pinboard.ApiTypes: [postTime] :: Post -> UTCTime
+ Pinboard.ApiTypes: [postToread] :: Post -> Bool
+ Pinboard.ApiTypes: [postsDate] :: Posts -> UTCTime
+ Pinboard.ApiTypes: [postsPosts] :: Posts -> [Post]
+ Pinboard.ApiTypes: [postsUser] :: Posts -> Text
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.FromJSON Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Aeson.Types.Class.ToJSON [Pinboard.ApiTypes.Suggested]
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance Data.Data.Data Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Classes.Eq Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Classes.Ord Pinboard.ApiTypes.UpdateTime
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.DoneResult
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.JsonTagMap
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Note
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.NoteList
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.NoteListItem
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Post
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.PostDates
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Posts
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.Suggested
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.TextResult
+ Pinboard.ApiTypes: instance GHC.Show.Show Pinboard.ApiTypes.UpdateTime
+ Pinboard.Client: [apiToken] :: PinboardConfig -> ByteString
+ Pinboard.Client: [debug] :: PinboardConfig -> Bool
+ Pinboard.Client: newMgr :: MonadIO m => m Manager
+ Pinboard.Error: BadRequest :: PinboardErrorHTTPCode
+ Pinboard.Error: ConnectionFailure :: PinboardErrorType
+ Pinboard.Error: Forbidden :: PinboardErrorHTTPCode
+ Pinboard.Error: HttpStatusFailure :: PinboardErrorType
+ Pinboard.Error: NotFound :: PinboardErrorHTTPCode
+ Pinboard.Error: ParseFailure :: PinboardErrorType
+ Pinboard.Error: PinboardError :: PinboardErrorType -> Text -> Maybe PinboardErrorCode -> Maybe Text -> Maybe PinboardErrorHTTPCode -> PinboardError
+ Pinboard.Error: PinboardServerError :: PinboardErrorHTTPCode
+ Pinboard.Error: RequestFailed :: PinboardErrorHTTPCode
+ Pinboard.Error: TooManyRequests :: PinboardErrorHTTPCode
+ Pinboard.Error: UnAuthorized :: PinboardErrorHTTPCode
+ Pinboard.Error: UnknownError :: PinboardErrorCode
+ Pinboard.Error: UnknownErrorType :: PinboardErrorType
+ Pinboard.Error: UnknownHTTPCode :: PinboardErrorHTTPCode
+ Pinboard.Error: [errorCode] :: PinboardError -> Maybe PinboardErrorCode
+ Pinboard.Error: [errorHTTP] :: PinboardError -> Maybe PinboardErrorHTTPCode
+ Pinboard.Error: [errorMsg] :: PinboardError -> Text
+ Pinboard.Error: [errorParam] :: PinboardError -> Maybe Text
+ Pinboard.Error: [errorType] :: PinboardError -> PinboardErrorType
+ Pinboard.Error: data PinboardError
+ Pinboard.Error: data PinboardErrorCode
+ Pinboard.Error: data PinboardErrorHTTPCode
+ Pinboard.Error: data PinboardErrorType
+ Pinboard.Error: defaultPinboardError :: PinboardError
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardError
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorCode
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorHTTPCode
+ Pinboard.Error: instance GHC.Show.Show Pinboard.Error.PinboardErrorType
+ Pinboard.Types: Count :: Int -> Param
+ Pinboard.Types: Date :: Day -> Param
+ Pinboard.Types: DateTime :: UTCTime -> Param
+ Pinboard.Types: Description :: Text -> Param
+ Pinboard.Types: Extended :: Text -> Param
+ Pinboard.Types: Format :: ResultFormatType -> Param
+ Pinboard.Types: FormatJson :: ResultFormatType
+ Pinboard.Types: FormatXml :: ResultFormatType
+ Pinboard.Types: FromDateTime :: UTCTime -> Param
+ Pinboard.Types: Meta :: Int -> Param
+ Pinboard.Types: New :: Text -> Param
+ Pinboard.Types: Old :: Text -> Param
+ Pinboard.Types: PinboardConfig :: ByteString -> Bool -> PinboardConfig
+ Pinboard.Types: PinboardRequest :: Text -> [Param] -> PinboardRequest
+ Pinboard.Types: Replace :: Bool -> Param
+ Pinboard.Types: Results :: Int -> Param
+ Pinboard.Types: Shared :: Bool -> Param
+ Pinboard.Types: Start :: Int -> Param
+ Pinboard.Types: Tag :: Text -> Param
+ Pinboard.Types: Tags :: Text -> Param
+ Pinboard.Types: ToDateTime :: UTCTime -> Param
+ Pinboard.Types: ToRead :: Bool -> Param
+ Pinboard.Types: Url :: Text -> Param
+ Pinboard.Types: [apiToken] :: PinboardConfig -> ByteString
+ Pinboard.Types: [debug] :: PinboardConfig -> Bool
+ Pinboard.Types: [requestParams] :: PinboardRequest -> [Param]
+ Pinboard.Types: [requestPath] :: PinboardRequest -> Text
+ Pinboard.Types: data Param
+ Pinboard.Types: data PinboardConfig
+ Pinboard.Types: data PinboardRequest
+ Pinboard.Types: data ResultFormatType
+ Pinboard.Types: instance GHC.Classes.Eq Pinboard.Types.Param
+ Pinboard.Types: instance GHC.Classes.Eq Pinboard.Types.ResultFormatType
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.Param
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.PinboardConfig
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.PinboardRequest
+ Pinboard.Types: instance GHC.Show.Show Pinboard.Types.ResultFormatType
+ Pinboard.Types: runPinboardT :: PinboardEnv -> PinboardT m a -> m (Either PinboardError a)
+ Pinboard.Types: type MonadPinboard m = (Functor m, Applicative m, Monad m, MonadIO m, MonadReader PinboardEnv m, MonadError PinboardError m)
+ Pinboard.Types: type ParamsBS = [(ByteString, ByteString)]
+ Pinboard.Types: type PinboardEnv = (PinboardConfig, Manager)
+ Pinboard.Types: type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a
+ Pinboard.Util: (</>) :: (Monoid m, IsString m) => m -> m -> m
+ Pinboard.Util: encodeParams :: [Param] -> ParamsBS
+ Pinboard.Util: ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest
+ Pinboard.Util: mkConfig :: PinboardConfig
+ Pinboard.Util: paramToName :: Param -> Text
+ Pinboard.Util: paramToText :: Param -> (Text, Text)
+ Pinboard.Util: paramsToByteString :: (Monoid m, IsString m) => [(m, m)] -> m
+ Pinboard.Util: toText :: Show a => a -> Text
+ Pinboard.Util: toTextLower :: Show a => a -> Text
- Pinboard.Client: runPinboardSingleRaw :: MonadIO m => PinboardConfig -> PinboardRequest -> (Response ByteString -> a) -> m (Either PinboardError a)
+ Pinboard.Client: runPinboardSingleRaw :: MonadIO m => PinboardConfig -> PinboardRequest -> m (Either PinboardError (Response ByteString))
- Pinboard.Client: sendPinboardRequest :: MonadIO m => PinboardEnv -> PinboardRequest -> (Response ByteString -> a) -> m a
+ Pinboard.Client: sendPinboardRequest :: MonadIO m => PinboardEnv -> PinboardRequest -> m (Response ByteString)
Files
- README.md +20/−0
- changelog.md +5/−0
- pinboard.cabal +4/−16
- src/Pinboard/Api.hs +1/−1
- src/Pinboard/ApiRequest.hs +3/−3
- src/Pinboard/Client.hs +26/−29
- src/Pinboard/Client/Error.hs +0/−56
- src/Pinboard/Client/Types.hs +0/−107
- src/Pinboard/Client/Util.hs +0/−111
- src/Pinboard/Error.hs +56/−0
- src/Pinboard/Types.hs +106/−0
- src/Pinboard/Util.hs +111/−0
README.md view
@@ -28,7 +28,27 @@ Right details -> print details Left pinboardError -> print pinboardError ```++output:+```+Posts{postsDate = 2015 - 10 - 24 16 : 17 : 12 UTC,+ postsUser = "jonschoning",+ postsPosts =+ [Post{postHref = "http://www.reddit.com/r/haskell/comments/25vj62/adventure_with_types_in_haskell_simon_peyton/",+ postDescription = "Adventure with Types in Haskell - Simon Peyton Jones [1:33:36] : haskell",+ postExtended = "", + postMeta = "3fe9fb05c7c37f7bb66be7b9d85599eb",+ postHash = "c46b717604ef8b126dabeba97b27a36f",+ postTime = 2014 - 5 - 19 3 : 35 : 55 UTC, + postShared = True,+ postToread = False,+ postTags = ["spj", "video", "haskell", "typetheory"]}]}+``` ## Modules++[Pinboard.Types](https://hackage.haskell.org/package/pinboard/docs/Pinboard-Types.html)++ Pinboard typeclasses and type aliases [Pinboard.Client](https://hackage.haskell.org/package/pinboard/docs/Pinboard-Client.html)
changelog.md view
@@ -1,3 +1,8 @@+__v0.9.0__++refactored Client.hs to simplify parameters+promote types under .Client subtree to top-level+ __v0.8.5__ replace Pinboard stack with PinboardT transfomer (use mtl style constraints instead of a fixed monad transformer stack)
pinboard.cabal view
@@ -1,5 +1,5 @@ name: pinboard-version: 0.8.10+version: 0.9.0 synopsis: Access to the Pinboard API license: MIT license-file: LICENSE@@ -18,18 +18,6 @@ library wraps the API exposing functions and data structures suitable for usage in Haskell programs. .- Example:- .- > import Pinboard- > - > main :: IO ()- > main = do- > let config = fromApiToken "api token"- > result <- runPinboard config $ getPostsRecent Nothing Nothing- > case result of- > Right details -> print details- > Left pinboardError -> print pinboardError- . Extra-Source-Files: README.md changelog.md library @@ -60,9 +48,9 @@ Pinboard.ApiRequest Pinboard.ApiTypes Pinboard.Client- Pinboard.Client.Error- Pinboard.Client.Types- Pinboard.Client.Util+ Pinboard.Error+ Pinboard.Types+ Pinboard.Util ghc-options: -Wall -rtsopts source-repository head
src/Pinboard/Api.hs view
@@ -42,7 +42,7 @@ import Pinboard.Client (pinboardJson) import Data.Text (Text) import Data.Time (UTCTime)-import Pinboard.Client.Types (MonadPinboard, ResultFormatType (..))+import Pinboard.Types (MonadPinboard, ResultFormatType (..)) import Pinboard.ApiTypes import Pinboard.ApiRequest
src/Pinboard/ApiRequest.hs view
@@ -37,12 +37,12 @@ getNoteRequest, ) where -import Pinboard.Client.Types (PinboardRequest (..), Param (..))-import Pinboard.Client.Util ((</>))+import Pinboard.Types (PinboardRequest (..), Param (..))+import Pinboard.Util ((</>)) import Data.Text (unwords) import Data.Maybe (catMaybes) import Pinboard.ApiTypes -import Pinboard.Client.Types (ResultFormatType (..))+import Pinboard.Types (ResultFormatType (..)) import Control.Applicative import Prelude hiding (unwords)
src/Pinboard/Client.hs view
@@ -30,8 +30,7 @@ -- * Sending , sendPinboardRequest -- * Manager (http-client)- , mgrOpenRaw- , mgrOpen+ , newMgr , mgrFail -- * JSON Handling ,parseJSONResponse@@ -44,13 +43,13 @@ ,createParserErr ,httpStatusPinboardError -- * Client Dependencies- , module Pinboard.Client.Error- , module Pinboard.Client.Types- , module Pinboard.Client.Util+ , module Pinboard.Error+ , module Pinboard.Types+ , module Pinboard.Util ) where -import Control.Exception (catch, SomeException, try)+import Control.Exception (catch, SomeException) import Control.Monad.IO.Class import Control.Monad.Reader import Control.Monad.Except@@ -68,9 +67,9 @@ import Network.HTTP.Client.TLS -import Pinboard.Client.Types-import Pinboard.Client.Error-import Pinboard.Client.Util+import Pinboard.Types+import Pinboard.Error+import Pinboard.Util import qualified Data.ByteString.Lazy as LBS import qualified Data.Text as T@@ -91,16 +90,19 @@ => PinboardConfig -> PinboardT m a -> m (Either PinboardError a)-runPinboard config f = mgrOpenRaw >>= go+runPinboard config f = newMgr >>= go where go mgr = runPinboardT (config, mgr) f -- | Create a Pinboard value from a PinboardRequest w/ json deserialization-pinboardJson :: (MonadPinboard m, FromJSON a) => PinboardRequest -> m a+pinboardJson + :: (MonadPinboard m, FromJSON a) + => PinboardRequest + -> m a pinboardJson req = do env <- ask- res <- sendPinboardRequest env (ensureResultFormatType FormatJson req) parseJSONResponse- res+ res <- sendPinboardRequest env (ensureResultFormatType FormatJson req) + parseJSONResponse res -------------------------------------------------------------------------------- @@ -108,10 +110,9 @@ :: MonadIO m => PinboardConfig -> PinboardRequest- -> (Response LBS.ByteString -> a)- -> m (Either PinboardError a)-runPinboardSingleRaw config req handler = liftIO $ mgrOpenRaw >>= go- where go mgr = (Right <$> sendPinboardRequest (config, mgr) req handler)+ -> m (Either PinboardError (Response LBS.ByteString))+runPinboardSingleRaw config req = liftIO $ newMgr >>= go+ where go mgr = (Right <$> sendPinboardRequest (config, mgr) req) `catch` mgrFail UnknownErrorType runPinboardSingleRawBS@@ -120,7 +121,7 @@ -> PinboardRequest -> m (Either PinboardError LBS.ByteString) runPinboardSingleRawBS config req = do- res <- runPinboardSingleRaw config req id+ res <- runPinboardSingleRaw config req return $ do r <- res responseBody r <$ checkStatusCodeResponse r@@ -139,15 +140,14 @@ :: MonadIO m => PinboardEnv -> PinboardRequest - -> (Response LBS.ByteString -> a)- -> m a-sendPinboardRequest (PinboardConfig{..}, man) PinboardRequest{..} handler = do+ -> m (Response LBS.ByteString)+sendPinboardRequest (PinboardConfig{..}, mgr) PinboardRequest{..} = do let url = T.concat [ requestPath , "?" , T.decodeUtf8 $ paramsToByteString $ ("auth_token", urlEncode False apiToken) : encodeParams requestParams ] req <- buildReq $ T.unpack url- res <- liftIO $ httpLbs req man- return $ handler res+ res <- liftIO $ httpLbs req mgr+ return res -------------------------------------------------------------------------------- @@ -155,7 +155,7 @@ buildReq url = do req <- liftIO $ parseUrl $ "https://api.pinboard.in/v1/" <> url return $ req - { requestHeaders = [("User-Agent","pinboard.hs/0.8.10")]+ { requestHeaders = [("User-Agent","pinboard.hs/0.9.0")] , checkStatus = \_ _ _ -> Nothing } @@ -212,12 +212,9 @@ -------------------------------------------------------------------------------- -mgrOpenRaw :: MonadIO m => m Manager-mgrOpenRaw = liftIO $ withSocketsDo . newManager +newMgr :: MonadIO m => m Manager+newMgr = liftIO $ withSocketsDo . newManager $ managerSetProxy (proxyEnvironment Nothing) tlsManagerSettings--mgrOpen :: MonadIO m => m (Either SomeException Manager)-mgrOpen = liftIO $ try mgrOpenRaw mgrFail :: MonadIO m => PinboardErrorType -> SomeException -> m (Either PinboardError b) mgrFail e msg = return $ Left $ PinboardError e (toText msg) Nothing Nothing Nothing
− src/Pinboard/Client/Error.hs
@@ -1,56 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--- |--- Module : Pinboard.Client.Error--- Copyright : (c) Jon Schoning, 2015--- Maintainer : jonschoning@gmail.com--- Stability : experimental--- Portability : POSIX-module Pinboard.Client.Error - ( defaultPinboardError- , PinboardErrorHTTPCode (..)- , PinboardErrorType (..)- , PinboardErrorCode (..)- , PinboardError (..)- ) where--import Data.Text (Text)--import Data.Monoid-import Prelude---------------------------------------------------------------------------------data PinboardErrorHTTPCode = - BadRequest -- ^ 400- | UnAuthorized -- ^ 401- | RequestFailed -- ^ 402- | Forbidden -- ^ 403- | NotFound -- ^ 404- | TooManyRequests -- ^ 429- | PinboardServerError -- ^ (>=500)- | UnknownHTTPCode -- ^ All other codes- deriving Show---------------------------------------------------------------------------------data PinboardErrorType =- ConnectionFailure- | HttpStatusFailure- | ParseFailure- | UnknownErrorType - deriving Show---------------------------------------------------------------------------------data PinboardErrorCode =- UnknownError - deriving Show---------------------------------------------------------------------------------data PinboardError = PinboardError {- errorType :: PinboardErrorType- , errorMsg :: Text- , errorCode :: Maybe PinboardErrorCode- , errorParam :: Maybe Text- , errorHTTP :: Maybe PinboardErrorHTTPCode- } deriving Show--defaultPinboardError :: PinboardError-defaultPinboardError = PinboardError UnknownErrorType mempty Nothing Nothing Nothing
− src/Pinboard/Client/Types.hs
@@ -1,107 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE OverloadedStrings #-}---- |--- Module : Pinboard.Client.Types--- Copyright : (c) Jon Schoning, 2015--- Maintainer : jonschoning@gmail.com--- Stability : experimental--- Portability : POSIX-module Pinboard.Client.Types- ( PinboardEnv- , PinboardT- , runPinboardT- , MonadPinboard- , PinboardRequest (..)- , PinboardConfig (..)- , ResultFormatType (..)- , Param (..)- , ParamsBS- ) where--import Control.Monad.Reader (ReaderT)-import Control.Monad.Reader.Class (MonadReader)-import Control.Monad.Trans.Except (ExceptT, runExceptT)-import Control.Monad.Trans.Reader (runReaderT)-import Control.Monad.Error.Class (MonadError)-import Control.Monad.IO.Class (MonadIO)--import Data.ByteString (ByteString)-import Data.Text (Text)-import Data.Time.Calendar(Day)-import Data.Time.Clock(UTCTime)-import Network.HTTP.Client (Manager)--import Pinboard.Client.Error (PinboardError (..))--import Control.Applicative-import Prelude----------------------------------------------------------------------------------type PinboardEnv = (PinboardConfig, Manager)--type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a--runPinboardT - :: PinboardEnv- -> PinboardT m a- -> m (Either PinboardError a)-runPinboardT e f = runExceptT (runReaderT f e)---- |Typeclass alias for the return type of the API functions (keeps the--- signatures less verbose)-type MonadPinboard m =- ( Functor m- , Applicative m- , Monad m- , MonadIO m- , MonadIO m- , MonadReader PinboardEnv m- , MonadError PinboardError m- )----------------------------------------------------------------------------------data PinboardRequest = PinboardRequest- { requestPath :: Text -- ^ url path of PinboardRequest- , requestParams :: [Param] -- ^ Query Parameters of PinboardRequest- } deriving Show---------------------------------------------------------------------------------data PinboardConfig = PinboardConfig- { apiToken :: ByteString- , debug :: Bool- } deriving Show----------------------------------------------------------------------------------type ParamsBS = [(ByteString, ByteString)]----------------------------------------------------------------------------------data ResultFormatType = FormatJson | FormatXml- deriving (Show, Eq)--data Param = Format ResultFormatType- | Tag Text- | Tags Text- | Old Text- | New Text- | Count Int- | Start Int- | Results Int- | Url Text- | Date Day- | DateTime UTCTime- | FromDateTime UTCTime- | ToDateTime UTCTime- | Replace Bool- | Shared Bool- | ToRead Bool- | Description Text- | Extended Text- | Meta Int- deriving (Show, Eq)-
− src/Pinboard/Client/Util.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-}--- |--- Module : Pinboard.Client.Util--- Copyright : (c) Jon Schoning, 2015--- Maintainer : jonschoning@gmail.com--- Stability : experimental--- Portability : POSIX-module Pinboard.Client.Util- ( - mkConfig- , paramsToByteString- , toText- , toTextLower- , (</>)- , paramToName- , paramToText- , encodeParams- , ensureResultFormatType- ) where--import Data.String (IsString)-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import Pinboard.Client.Types (PinboardRequest (..), PinboardConfig (..), ResultFormatType (..), Param (..), ParamsBS)-import Network.HTTP.Types(urlEncode)--import Data.Monoid-import Prelude----------------------------------------------------------------------------------mkConfig :: PinboardConfig-mkConfig = PinboardConfig { debug = False, apiToken = mempty }----------------------------------------------------------------------------------- | Conversion from a `Show` constrained type to `Text`-toText- :: Show a- => a - -> Text -toText = T.pack . show----------------------------------------------------------------------------------- | Conversion from a `Show` constrained type to lowercase `Text`-toTextLower- :: Show a- => a - -> Text -toTextLower = T.toLower . T.pack . show----------------------------------------------------------------------------------- | Conversion of a key value pair to a query parameterized string-paramsToByteString- :: (Monoid m, IsString m)- => [(m, m)]- -> m-paramsToByteString [] = mempty-paramsToByteString [(x,y)] = x <> "=" <> y-paramsToByteString ((x,y) : xs) =- mconcat [ x, "=", y, "&" ] <> paramsToByteString xs---- | Retrieve and encode the optional parameters-encodeParams :: [Param] -> ParamsBS-encodeParams xs = do - x <- xs - let (k, v) = paramToText x- return ( T.encodeUtf8 k- , (urlEncode True . T.encodeUtf8 ) v- )-ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest-ensureResultFormatType fmt req = - if hasFormat then req else req { requestParams = Format fmt : params }- where params = requestParams req- hasFormat = Format fmt `elem` params---paramToText :: Param -> (Text, Text)-paramToText (Tag a) = ("tag", a)-paramToText (Tags a) = ("tags", a)-paramToText (Old a) = ("old", a)-paramToText (New a) = ("new", a)-paramToText (Format FormatJson) = ("format", "json")-paramToText (Format FormatXml) = ("format", "xml")-paramToText (Count a) = ("count", toText a)-paramToText (Start a) = ("start", toText a)-paramToText (Results a) = ("results", toText a)-paramToText (Url a) = ("url", a)-paramToText (Date a) = ("dt", toText a)-paramToText (DateTime a) = ("dt", toText a)-paramToText (FromDateTime a) = ("fromdt", toText a)-paramToText (ToDateTime a) = ("todt", toText a)-paramToText (Replace a) = ("replace", if a then "yes" else "no")-paramToText (Shared a) = ("shared", if a then "yes" else "no")-paramToText (ToRead a) = ("toread", if a then "yes" else "no")-paramToText (Description a) = ("description", a)-paramToText (Extended a) = ("extended", a)-paramToText (Meta a) = ("meta", toText a)--paramToName :: Param -> Text-paramToName = fst . paramToText---------------------------------------------------------------------------------- | Forward slash interspersion on `Monoid` and `IsString`--- constrained types-(</>)- :: (Monoid m, IsString m)- => m- -> m- -> m-m1 </> m2 = m1 <> "/" <> m2
+ src/Pinboard/Error.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Pinboard.Error+-- Copyright : (c) Jon Schoning, 2015+-- Maintainer : jonschoning@gmail.com+-- Stability : experimental+-- Portability : POSIX+module Pinboard.Error + ( defaultPinboardError+ , PinboardErrorHTTPCode (..)+ , PinboardErrorType (..)+ , PinboardErrorCode (..)+ , PinboardError (..)+ ) where++import Data.Text (Text)++import Data.Monoid+import Prelude++------------------------------------------------------------------------------+data PinboardErrorHTTPCode = + BadRequest -- ^ 400+ | UnAuthorized -- ^ 401+ | RequestFailed -- ^ 402+ | Forbidden -- ^ 403+ | NotFound -- ^ 404+ | TooManyRequests -- ^ 429+ | PinboardServerError -- ^ (>=500)+ | UnknownHTTPCode -- ^ All other codes+ deriving Show++------------------------------------------------------------------------------+data PinboardErrorType =+ ConnectionFailure+ | HttpStatusFailure+ | ParseFailure+ | UnknownErrorType + deriving Show++------------------------------------------------------------------------------+data PinboardErrorCode =+ UnknownError + deriving Show++------------------------------------------------------------------------------+data PinboardError = PinboardError {+ errorType :: PinboardErrorType+ , errorMsg :: Text+ , errorCode :: Maybe PinboardErrorCode+ , errorParam :: Maybe Text+ , errorHTTP :: Maybe PinboardErrorHTTPCode+ } deriving Show++defaultPinboardError :: PinboardError+defaultPinboardError = PinboardError UnknownErrorType mempty Nothing Nothing Nothing
+ src/Pinboard/Types.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE OverloadedStrings #-}++-- |+-- Module : Pinboard.Types+-- Copyright : (c) Jon Schoning, 2015+-- Maintainer : jonschoning@gmail.com+-- Stability : experimental+-- Portability : POSIX+module Pinboard.Types+ ( PinboardEnv+ , PinboardT+ , runPinboardT+ , MonadPinboard+ , PinboardRequest (..)+ , PinboardConfig (..)+ , ResultFormatType (..)+ , Param (..)+ , ParamsBS+ ) where++import Control.Monad.Reader (ReaderT)+import Control.Monad.Reader.Class (MonadReader)+import Control.Monad.Trans.Except (ExceptT, runExceptT)+import Control.Monad.Trans.Reader (runReaderT)+import Control.Monad.Error.Class (MonadError)+import Control.Monad.IO.Class (MonadIO)++import Data.ByteString (ByteString)+import Data.Text (Text)+import Data.Time.Calendar(Day)+import Data.Time.Clock(UTCTime)+import Network.HTTP.Client (Manager)++import Pinboard.Error (PinboardError (..))++import Control.Applicative+import Prelude++------------------------------------------------------------------------------++type PinboardEnv = (PinboardConfig, Manager)++type PinboardT m a = ReaderT PinboardEnv (ExceptT PinboardError m) a++runPinboardT + :: PinboardEnv+ -> PinboardT m a+ -> m (Either PinboardError a)+runPinboardT e f = runExceptT (runReaderT f e)++-- |Typeclass alias for the return type of the API functions (keeps the+-- signatures less verbose)+type MonadPinboard m =+ ( Functor m+ , Applicative m+ , Monad m+ , MonadIO m+ , MonadReader PinboardEnv m+ , MonadError PinboardError m+ )++------------------------------------------------------------------------------++data PinboardRequest = PinboardRequest+ { requestPath :: Text -- ^ url path of PinboardRequest+ , requestParams :: [Param] -- ^ Query Parameters of PinboardRequest+ } deriving Show++------------------------------------------------------------------------------+data PinboardConfig = PinboardConfig+ { apiToken :: ByteString+ , debug :: Bool+ } deriving Show++------------------------------------------------------------------------------++type ParamsBS = [(ByteString, ByteString)]++------------------------------------------------------------------------------++data ResultFormatType = FormatJson | FormatXml+ deriving (Show, Eq)++data Param = Format ResultFormatType+ | Tag Text+ | Tags Text+ | Old Text+ | New Text+ | Count Int+ | Start Int+ | Results Int+ | Url Text+ | Date Day+ | DateTime UTCTime+ | FromDateTime UTCTime+ | ToDateTime UTCTime+ | Replace Bool+ | Shared Bool+ | ToRead Bool+ | Description Text+ | Extended Text+ | Meta Int+ deriving (Show, Eq)+
+ src/Pinboard/Util.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}+-- |+-- Module : Pinboard.Util+-- Copyright : (c) Jon Schoning, 2015+-- Maintainer : jonschoning@gmail.com+-- Stability : experimental+-- Portability : POSIX+module Pinboard.Util+ ( + mkConfig+ , paramsToByteString+ , toText+ , toTextLower+ , (</>)+ , paramToName+ , paramToText+ , encodeParams+ , ensureResultFormatType+ ) where++import Data.String (IsString)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import Pinboard.Types (PinboardRequest (..), PinboardConfig (..), ResultFormatType (..), Param (..), ParamsBS)+import Network.HTTP.Types(urlEncode)++import Data.Monoid+import Prelude++------------------------------------------------------------------------------++mkConfig :: PinboardConfig+mkConfig = PinboardConfig { debug = False, apiToken = mempty }++------------------------------------------------------------------------------+-- | Conversion from a `Show` constrained type to `Text`+toText+ :: Show a+ => a + -> Text +toText = T.pack . show++------------------------------------------------------------------------------+-- | Conversion from a `Show` constrained type to lowercase `Text`+toTextLower+ :: Show a+ => a + -> Text +toTextLower = T.toLower . T.pack . show++------------------------------------------------------------------------------+-- | Conversion of a key value pair to a query parameterized string+paramsToByteString+ :: (Monoid m, IsString m)+ => [(m, m)]+ -> m+paramsToByteString [] = mempty+paramsToByteString [(x,y)] = x <> "=" <> y+paramsToByteString ((x,y) : xs) =+ mconcat [ x, "=", y, "&" ] <> paramsToByteString xs++-- | Retrieve and encode the optional parameters+encodeParams :: [Param] -> ParamsBS+encodeParams xs = do + x <- xs + let (k, v) = paramToText x+ return ( T.encodeUtf8 k+ , (urlEncode True . T.encodeUtf8 ) v+ )+ensureResultFormatType :: ResultFormatType -> PinboardRequest -> PinboardRequest+ensureResultFormatType fmt req = + if hasFormat then req else req { requestParams = Format fmt : params }+ where params = requestParams req+ hasFormat = Format fmt `elem` params+++paramToText :: Param -> (Text, Text)+paramToText (Tag a) = ("tag", a)+paramToText (Tags a) = ("tags", a)+paramToText (Old a) = ("old", a)+paramToText (New a) = ("new", a)+paramToText (Format FormatJson) = ("format", "json")+paramToText (Format FormatXml) = ("format", "xml")+paramToText (Count a) = ("count", toText a)+paramToText (Start a) = ("start", toText a)+paramToText (Results a) = ("results", toText a)+paramToText (Url a) = ("url", a)+paramToText (Date a) = ("dt", toText a)+paramToText (DateTime a) = ("dt", toText a)+paramToText (FromDateTime a) = ("fromdt", toText a)+paramToText (ToDateTime a) = ("todt", toText a)+paramToText (Replace a) = ("replace", if a then "yes" else "no")+paramToText (Shared a) = ("shared", if a then "yes" else "no")+paramToText (ToRead a) = ("toread", if a then "yes" else "no")+paramToText (Description a) = ("description", a)+paramToText (Extended a) = ("extended", a)+paramToText (Meta a) = ("meta", toText a)++paramToName :: Param -> Text+paramToName = fst . paramToText+------------------------------------------------------------------------------+-- | Forward slash interspersion on `Monoid` and `IsString`+-- constrained types+(</>)+ :: (Monoid m, IsString m)+ => m+ -> m+ -> m+m1 </> m2 = m1 <> "/" <> m2