module HipBot
( HipBot
, HipBotAPI(..)
, newHipBot
, hipBotResources
, configResource
, verifySignature
, sendNotification
, module HipBot.Internal.Types
) where
import Control.Applicative
import Control.Lens hiding ((.=))
import Control.Monad.Catch
import Control.Monad.Trans
import Control.Monad.Trans.Either
import Data.Aeson ((.=))
import qualified Data.Aeson as A
import Data.Bifunctor
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Time.Clock
import Network.HTTP.Types
import qualified Network.Wreq as Wreq
import HipBot.API
import HipBot.Internal.HipBot
import HipBot.Internal.OAuth
import HipBot.Internal.Resources
import HipBot.Internal.Types
data NotificationError
= NoSuchRegistration OAuthId
| TokenError OAuthError
sendNotification
:: (Applicative m, MonadCatch m, MonadIO m)
=> HipBot m
-> OAuthId
-> Either RoomName RoomId
-> Notification
-> m (Maybe NotificationError)
sendNotification bot oid room n = getToken bot oid >>= either (return . Just) send where
send (reg, tok) = Nothing <$ liftIO (Wreq.postWith (opts tok) (notificationUrl room reg) msg)
opts tok = wreqDefaults bot
& Wreq.header hAuthorization .~ [("Bearer " <>) . T.encodeUtf8 . view accessToken $ tok]
& Wreq.header hContentType .~ ["application/json"]
msg = case n of
TextNotification t -> A.object
[ "message_format" .= ("text" :: Text)
, "message" .= t
]
HtmlNotification t -> A.object
[ "message_format" .= ("html" :: Text)
, "message" .= t
]
getToken
:: (Applicative m, MonadCatch m, MonadIO m)
=> HipBot m
-> OAuthId
-> m (Either NotificationError (Registration, AccessToken))
getToken bot oid = runEitherT (lookupReg >>= fetch) where
lookupReg = EitherT .
fmap (maybe (Left . NoSuchRegistration $ oid) Right) .
apiLookupRegistration (view hipBotAPI bot) $
oid
fetch (reg, tok) = do
now <- liftIO getCurrentTime
tok' <- if now > addUTCTime 300 (tok ^. expires)
then right tok
else do
tok' <- EitherT .
fmap (first TokenError) .
obtainAccessToken bot $
reg
lift . apiUpdateAccessToken (bot ^. hipBotAPI) oid $ tok'
return tok'
return (reg, tok')
notificationUrl :: Either RoomName RoomId -> Registration -> String
notificationUrl room =
show .
relativeTo ["room", either id (T.pack . show) room, "notification"] .
view capabilitiesUrl