textlocal (empty) → 0.1.0.0
raw patch · 5 files changed
+290/−0 lines, 5 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, http-client, http-client-tls, http-conduit, text, unix-time
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- src/Network/Api/TextLocal.hs +176/−0
- src/Network/Api/Types.hs +49/−0
- textlocal.cabal +33/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Sibi Prabakaran (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Network/Api/TextLocal.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Network.Api.TextLocal+ (Credential+ ,createApiKey+ ,createUserHash+ ,SMSSettings+ ,defaultSMSSettings+ ,setManager+ ,setDestinationNumber+ ,setMessage+ ,setAuth+ ,runSettings+ ,sendSMS)+ where++import Data.Text (Text)+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Data.UnixTime (UnixTime)+import Network.HTTP.Simple -- (setRequestManager, httpJSONEither)+import Network.HTTP.Client (Manager, parseRequest, newManager)+import Network.HTTP.Client.TLS (tlsManagerSettings)+import Network.HTTP.Client.MultipartFormData (formDataBody, partBS)+import Data.Monoid ((<>))+import Network.Api.Types++-- |+-- Credential for making request to textLocal server.+data Credential+ = ApiKey ByteString+ | UserHash ByteString -- ^ Email address+ ByteString -- ^ Secure hash that is found within the messenger.++baseUrl :: String+baseUrl = "https://api.textlocal.in/"++-- Create 'Credential' for textLocal.+createApiKey+ :: ByteString -- ^ api key+ -> Credential+createApiKey apiKey = ApiKey apiKey++createUserHash :: ByteString -> ByteString -> Credential+createUserHash email hash = UserHash email hash++formCred (ApiKey apikey) = [partBS "apiKey" apikey]+formCred (UserHash user hash) = [partBS "username" user, partBS "hash" hash]++data SMSSettings = SMSSettings+ { settingsSender :: ByteString -- ^ Sender name must be 6 alpha+ -- characters and should be+ -- pre-approved by Textlocal. In+ -- the absence of approved sender+ -- names, use the default 'TXTLCL'+ , settingsMessage :: ByteString -- ^ The message content. This+ -- parameter should be no longer+ -- than 766 characters. The+ -- message also must be URL+ -- Encoded to support symbols like+ -- &.+ , settingsAuth :: Credential+ , settingsNumber :: [ByteString]+ , settingsManager :: Maybe Manager+ , settingsGroupId :: Maybe Int+ , settingsScheduleTime :: Maybe UnixTime+ , settingsReceiptUrl :: Maybe ByteString+ , settingsCustom :: Maybe Text+ , settingsOptOut :: Maybe Bool+ , settingsValidity :: Maybe UnixTime+ , settingsUnicode :: Maybe Bool+ , settingsTest :: Maybe Bool+ }++-- | 'defaultSMSSettings' has the default settings, duh! The+-- 'settingsSender' has a value of "TXTLCL". The accessors+-- 'settingsMessage', 'settingsAuth', 'settingsNumber' contains a+-- value of bottom. They have to be initialized to a proper value+-- before sending SMS.+defaultSMSSettings =+ SMSSettings+ { settingsSender = "TXTLCL"+ , settingsMessage = error "defaultSMSSettings: message content not present"+ , settingsAuth = error "defaultSMSSettings: credential not present"+ , settingsNumber = error "defaultSMSSettings: no number present"+ , settingsManager = Nothing+ , settingsGroupId = Nothing+ , settingsScheduleTime = Nothing+ , settingsReceiptUrl = Nothing+ , settingsCustom = Nothing+ , settingsOptOut = Nothing+ , settingsValidity = Nothing+ , settingsUnicode = Nothing+ , settingsTest = Just False+ }++setMessage :: ByteString -> SMSSettings -> SMSSettings+setMessage msg def =+ def+ { settingsMessage = msg+ }++setAuth :: Credential -> SMSSettings -> SMSSettings+setAuth cred def =+ def+ { settingsAuth = cred+ }++setDestinationNumber :: [ByteString] -> SMSSettings -> SMSSettings+setDestinationNumber num def =+ def+ { settingsNumber = num+ }++-- | Use an existing manager instead of creating a new one+setManager+ :: Manager -> SMSSettings -> SMSSettings+setManager mgr def =+ def+ { settingsManager = Just mgr+ }++setTest :: Bool -> SMSSettings -> SMSSettings+setTest test set =+ set+ { settingsTest = Just test+ }++sendSMS+ :: ByteString -- ^ Text to send+ -> [ByteString] -- ^ Destination numbers+ -> Credential+ -> IO (Either JSONException TLResponse)+sendSMS msg num cred =+ runSettings+ SendSMS+ defaultSMSSettings+ { settingsAuth = cred+ , settingsNumber = num+ , settingsMessage = msg+ }++data Command =+ SendSMS+ deriving (Show,Eq,Ord)++runSettings :: Command -> SMSSettings -> IO (Either JSONException TLResponse)+runSettings cmd set = do+ let epoint = endpointUrl cmd+ req <- parseRequest epoint+ mgr <- getManager (settingsManager set)+ req' <-+ formDataBody+ ([ partBS "sender" (settingsSender set)+ , partBS "message" (settingsMessage set)+ , partBS "numbers" (B.intercalate "," $ settingsNumber set)+ , partBS "test" (boolByteString $ settingsTest set)] <>+ formCred (settingsAuth set))+ req+ let req'' = setRequestManager mgr req'+ (response :: Response (Either JSONException TLResponse)) <-+ httpJSONEither req''+ return $ getResponseBody response++boolByteString :: Maybe Bool -> ByteString+boolByteString Nothing = "false"+boolByteString (Just False) = "false"+boolByteString (Just True) = "true"++getManager :: Maybe Manager -> IO Manager+getManager Nothing = newManager tlsManagerSettings+getManager (Just mgr) = return mgr++endpointUrl :: Command -> String+endpointUrl SendSMS = baseUrl <> "send/"
+ src/Network/Api/Types.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.Api.Types where++import Data.Text (Text)+import Data.Aeson ((.:), Value(..), FromJSON(..), (.:?))+import Control.Applicative (empty)++data Error = Error+ { ecode :: Int+ , emessage :: Text+ } deriving (Eq,Ord,Show)++instance FromJSON Error where+ parseJSON (Object v) = Error <$> v .: "code" <*> v .: "message"+ parseJSON _ = empty++data Warning = Warning+ { wcode :: Int+ , wmessage :: Text+ } deriving (Eq,Ord,Show)++instance FromJSON Warning where+ parseJSON (Object v) = Warning <$> v .: "code" <*> v .: "message"+ parseJSON _ = empty++data TLStatus+ = Success+ | Failure+ deriving (Show,Eq,Ord)++instance FromJSON TLStatus where+ parseJSON (String v) =+ if (v == "success")+ then return Success+ else return Failure+ parseJSON _ = empty++data TLResponse = TLResponse+ { status :: TLStatus+ , warnings :: Maybe [Warning]+ , errors :: Maybe [Error]+ } deriving (Eq,Ord,Show)++instance FromJSON TLResponse where+ parseJSON (Object resp) =+ TLResponse <$> resp .: "status" <*> resp .:? "warnings" <*>+ resp .:? "errors"+ parseJSON _ = empty
+ textlocal.cabal view
@@ -0,0 +1,33 @@+name: textlocal+version: 0.1.0.0+synopsis: Haskell wrapper for textlocal SMS gateway+description: Please see README.md+homepage: https://github.com/just-chow/textlocal+license: BSD3+license-file: LICENSE+author: Sibi Prabakaran+maintainer: sibi@psibi.in+copyright: 2016 Sibi Prabakaran+category: Web+build-type: Simple+bug-reports: https://github.com/just-chow/textlocal/issues+-- extra-source-files:+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Network.Api.Types,+ Network.Api.TextLocal+ build-depends: base >= 4.7 && < 4.9,+ text, + bytestring,+ unix-time,+ http-client,+ http-client-tls,+ http-conduit,+ aeson+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/githubuser/textlocal