{-# LANGUAGE CPP #-}

----------------------------------------------------------------------

----------------------------------------------------------------------

-- |
-- Module: Web.Slack.Classy
-- Description: For compatibility with Web.Slack prior to v0.4.0.0.
module Web.Slack.Classy
  ( SlackConfig (..),
    mkSlackConfig,
    apiTest,
    authTest,
    chatPostMessage,
    conversationsList,
    conversationsHistory,
    conversationsHistoryAll,
    conversationsReplies,
    repliesFetchAll,
    getUserDesc,
    usersList,
    userLookupByEmail,
    authenticateReq,
    Response,
    LoadPage,
    HasManager (..),
    HasToken (..),
  )
where

-- FIXME: Web.Slack.Prelude

-- base
import Control.Arrow ((&&&))
-- containers

-- http-client

-- mtl
import Control.Monad.Reader
import Data.Map qualified as Map
import Data.Maybe
-- slack-web

-- text
import Data.Text (Text)
import Network.HTTP.Client (Manager)
import Web.Slack (SlackConfig (..), authenticateReq, mkSlackConfig)
import Web.Slack qualified as NonClassy
import Web.Slack.Api qualified as Api
import Web.Slack.Auth qualified as Auth
import Web.Slack.Chat qualified as Chat
import Web.Slack.Common qualified as Common
import Web.Slack.Conversation qualified as Conversation
import Web.Slack.Pager
import Web.Slack.User qualified as User
import Prelude

#if !MIN_VERSION_servant(0,13,0)
mkClientEnv :: Manager -> BaseUrl -> ClientEnv
mkClientEnv = ClientEnv
#endif

-- | Implemented by 'SlackConfig'
class HasManager a where
  getManager :: a -> Manager

-- | Implemented by 'SlackConfig'
class HasToken a where
  getToken :: a -> Text

instance HasManager SlackConfig where
  getManager :: SlackConfig -> Manager
getManager = SlackConfig -> Manager
slackConfigManager

instance HasToken SlackConfig where
  getToken :: SlackConfig -> Text
getToken = SlackConfig -> Text
slackConfigToken

-- |
--
-- Check API calling code.
--
-- <https://api.slack.com/methods/api.test>
apiTest ::
  (MonadReader env m, HasManager env, MonadIO m) =>
  Api.TestReq ->
  m (Response Api.TestRsp)
apiTest :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, MonadIO m) =>
TestReq -> m (Response TestRsp)
apiTest = forall env (m :: * -> *) a.
(MonadReader env m, MonadIO m) =>
(env -> IO a) -> m a
liftToReader forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip (Manager -> TestReq -> IO (Response TestRsp)
NonClassy.apiTest forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasManager a => a -> Manager
getManager)

-- |
--
-- Check authentication and identity.
--
-- <https://api.slack.com/methods/auth.test>
authTest ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  m (Response Auth.TestRsp)
authTest :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
m (Response TestRsp)
authTest = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy SlackConfig -> IO (Response TestRsp)
NonClassy.authTest

-- |
--
-- Retrieve conversations list.
--
-- <https://api.slack.com/methods/conversations.list>
conversationsList ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  Conversation.ListReq ->
  m (Response Conversation.ListRsp)
conversationsList :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
ListReq -> m (Response ListRsp)
conversationsList = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip SlackConfig -> ListReq -> IO (Response ListRsp)
NonClassy.conversationsList

-- |
--
-- Retrieve ceonversation history.
-- Consider using 'historyFetchAll' in combination with this function.
--
-- <https://api.slack.com/methods/conversations.history>
conversationsHistory ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  Conversation.HistoryReq ->
  m (Response Conversation.HistoryRsp)
conversationsHistory :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
HistoryReq -> m (Response HistoryRsp)
conversationsHistory = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip SlackConfig -> HistoryReq -> IO (Response HistoryRsp)
NonClassy.conversationsHistory

-- |
--
-- Retrieve replies of a conversation.
-- Consider using 'repliesFetchAll' if you want to get entire replies
-- of a conversation.
--
-- <https://api.slack.com/methods/conversations.replies>
conversationsReplies ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  Conversation.RepliesReq ->
  m (Response Conversation.HistoryRsp)
conversationsReplies :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
RepliesReq -> m (Response HistoryRsp)
conversationsReplies = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip SlackConfig -> RepliesReq -> IO (Response HistoryRsp)
NonClassy.conversationsReplies

-- |
--
-- Send a message to a channel.
--
-- <https://api.slack.com/methods/chat.postMessage>
chatPostMessage ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  Chat.PostMsgReq ->
  m (Response Chat.PostMsgRsp)
chatPostMessage :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
PostMsgReq -> m (Response PostMsgRsp)
chatPostMessage = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip SlackConfig -> PostMsgReq -> IO (Response PostMsgRsp)
NonClassy.chatPostMessage

-- |
--
-- This method returns a list of all users in the team.
-- This includes deleted/deactivated users.
--
-- <https://api.slack.com/methods/users.list>
usersList ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  m (Response User.ListRsp)
usersList :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
m (Response ListRsp)
usersList = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy SlackConfig -> IO (Response ListRsp)
NonClassy.usersList

-- |
--
-- This method returns a list of all users in the team.
-- This includes deleted/deactivated users.
--
-- <https://api.slack.com/methods/users.lookupByEmail>
userLookupByEmail ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  User.Email ->
  m (Response User.UserRsp)
userLookupByEmail :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
Email -> m (Response UserRsp)
userLookupByEmail = forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip SlackConfig -> Email -> IO (Response UserRsp)
NonClassy.userLookupByEmail

-- | Returns a function to get a username from a 'Common.UserId'.
-- Comes in handy to use 'Web.Slack.MessageParser.messageToHtml'
getUserDesc ::
  -- | A function to give a default username in case the username is unknown
  (Common.UserId -> Text) ->
  -- | List of users as known by the slack server. See 'usersList'.
  User.ListRsp ->
  -- | A function from 'Common.UserId' to username.
  (Common.UserId -> Text)
getUserDesc :: (UserId -> Text) -> ListRsp -> UserId -> Text
getUserDesc UserId -> Text
unknownUserFn ListRsp
users =
  let userMap :: Map UserId Text
userMap = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ (User -> UserId
User.userId forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& User -> Text
User.userName) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ListRsp -> [User]
User.listRspMembers ListRsp
users
   in \UserId
userId -> forall a. a -> Maybe a -> a
fromMaybe (UserId -> Text
unknownUserFn UserId
userId) forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup UserId
userId Map UserId Text
userMap

-- | Returns an action to send a request to get the history of a conversation.
--
--   To fetch all messages in the conversation, run the returned 'LoadPage' action
--   repeatedly until it returns an empty list.
conversationsHistoryAll ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  -- | The first request to send. _NOTE_: 'Conversation.historyReqCursor' is silently ignored.
  Conversation.HistoryReq ->
  -- | An action which returns a new page of messages every time called.
  --   If there are no pages anymore, it returns an empty list.
  m (LoadPage m Common.Message)
conversationsHistoryAll :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
HistoryReq -> m (LoadPage m Message)
conversationsHistoryAll = forall (m :: * -> *) req resp.
(MonadIO m, PagedRequest req, PagedResponse resp) =>
(req -> m (Response resp))
-> req -> m (LoadPage m (ResponseObject resp))
fetchAllBy forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
HistoryReq -> m (Response HistoryRsp)
conversationsHistory

-- | Returns an action to send a request to get the replies of a conversation.
--
--   To fetch all replies in the conversation, run the returned 'LoadPage' action
--   repeatedly until it returns an empty list.
--
--   *NOTE*: The conversations.replies endpoint always returns the first message
--           of the thread. So every page returned by the 'LoadPage' action includes
--           the first message of the thread. You should drop it if you want to
--           collect messages in a thread without duplicates.
repliesFetchAll ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  -- | The first request to send. _NOTE_: 'Conversation.repliesReqCursor' is silently ignored.
  Conversation.RepliesReq ->
  -- | An action which returns a new page of messages every time called.
  --   If there are no pages anymore, it returns an empty list.
  m (LoadPage m Common.Message)
repliesFetchAll :: forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
RepliesReq -> m (LoadPage m Message)
repliesFetchAll = forall (m :: * -> *) req resp.
(MonadIO m, PagedRequest req, PagedResponse resp) =>
(req -> m (Response resp))
-> req -> m (LoadPage m (ResponseObject resp))
fetchAllBy forall env (m :: * -> *).
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
RepliesReq -> m (Response HistoryRsp)
conversationsReplies

liftNonClassy ::
  (MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
  (SlackConfig -> IO a) ->
  m a
liftNonClassy :: forall env (m :: * -> *) a.
(MonadReader env m, HasManager env, HasToken env, MonadIO m) =>
(SlackConfig -> IO a) -> m a
liftNonClassy SlackConfig -> IO a
f =
  forall env (m :: * -> *) a.
(MonadReader env m, MonadIO m) =>
(env -> IO a) -> m a
liftToReader forall a b. (a -> b) -> a -> b
$ \env
env -> SlackConfig -> IO a
f forall a b. (a -> b) -> a -> b
$ Manager -> Text -> SlackConfig
SlackConfig (forall a. HasManager a => a -> Manager
getManager env
env) (forall a. HasToken a => a -> Text
getToken env
env)

liftToReader ::
  (MonadReader env m, MonadIO m) =>
  (env -> IO a) ->
  m a
liftToReader :: forall env (m :: * -> *) a.
(MonadReader env m, MonadIO m) =>
(env -> IO a) -> m a
liftToReader env -> IO a
f = do
  env
env <- forall r (m :: * -> *). MonadReader r m => m r
ask
  forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ env -> IO a
f env
env