pr-tools-0.1.0.0: src/PRTools/Slack.hs
{-# LANGUAGE OverloadedStrings #-}
module PRTools.Slack where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import Data.Aeson (Value(..), encode, object, (.=), decode)
import qualified Data.Aeson.KeyMap as KM
import Network.HTTP.Client (RequestBody(RequestBodyLBS), httpLbs, method, newManager, parseRequest, requestBody, requestHeaders, responseBody, responseStatus, urlEncodedBody)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Network.HTTP.Types (statusCode)
import System.IO (hPutStrLn, stderr)
import Data.UUID.V4 (nextRandom)
import Data.UUID (toString)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import Data.CaseInsensitive (mk)
import Data.Maybe (fromMaybe)
import qualified Data.ByteString.Char8 as BSC
sendViaWebhook :: String -> String -> IO ()
sendViaWebhook webhook message = do
manager <- newManager tlsManagerSettings
initReq <- parseRequest webhook
let req = initReq
{ method = "POST"
, requestBody = RequestBodyLBS $ encode $ object ["text" .= message]
, requestHeaders = [(mk (TE.encodeUtf8 (T.pack "Content-Type")), TE.encodeUtf8 (T.pack "application/json"))]
}
response <- httpLbs req manager
if statusCode (responseStatus response) == 200
then putStrLn "Sent to Slack"
else hPutStrLn stderr "Error sending to Slack"
sendViaApi :: String -> String -> String -> String -> String -> IO ()
sendViaApi summary fileContent filename channel token = do
manager <- newManager tlsManagerSettings
-- Step 1: Get upload URL
initUrlReq <- parseRequest "https://slack.com/api/files.getUploadURLExternal"
let pairs = [ ("filename", BSC.pack filename)
, ("length", BSC.pack $ show $ BS.length (TE.encodeUtf8 (T.pack fileContent)))
]
let urlReq = urlEncodedBody pairs initUrlReq
{ method = "POST"
, requestHeaders =
[ (mk "Authorization", TE.encodeUtf8 (T.pack ("Bearer " ++ token)))
]
}
urlResp <- httpLbs urlReq manager
let urlStatus = statusCode (responseStatus urlResp)
if urlStatus /= 200
then hPutStrLn stderr $ "HTTP error getting upload URL: " ++ show urlStatus
else case decode (responseBody urlResp) of
Just (Object val) -> case (KM.lookup "ok" val, KM.lookup "upload_url" val, KM.lookup "file_id" val) of
(Just (Bool True), Just (String url), Just (String fileId)) -> do
-- Step 2: Upload file to URL
initUploadReq <- parseRequest (T.unpack url)
let uploadReq = initUploadReq
{ method = "POST"
, requestBody = RequestBodyLBS (LBS.fromStrict (TE.encodeUtf8 (T.pack fileContent)))
, requestHeaders = [(mk "Content-Type", "application/octet-stream")]
}
uploadResp <- httpLbs uploadReq manager
let uploadStatus = statusCode (responseStatus uploadResp)
if uploadStatus /= 200
then hPutStrLn stderr $ "HTTP error uploading file: " ++ show uploadStatus
else do
-- Step 3: Complete upload
initCompleteReq <- parseRequest "https://slack.com/api/files.completeUploadExternal"
let completeReq = initCompleteReq
{ method = "POST"
, requestBody = RequestBodyLBS $ encode $ object
[ "files" .= [object ["id" .= fileId, "title" .= filename]]
, "channel_id" .= channel
, "initial_comment" .= summary
]
, requestHeaders =
[ (mk "Authorization", TE.encodeUtf8 (T.pack ("Bearer " ++ token)))
, (mk "Content-Type", "application/json")
]
}
completeResp <- httpLbs completeReq manager
let completeStatus = statusCode (responseStatus completeResp)
if completeStatus /= 200
then hPutStrLn stderr $ "HTTP error completing upload: " ++ show completeStatus
else case decode (responseBody completeResp) of
Just (Object cVal) -> case KM.lookup "ok" cVal of
Just (Bool True) -> putStrLn "Sent to Slack as attachment"
_ -> do
let errMsg = fromMaybe "Unknown error" (KM.lookup "error" cVal >>= \v -> case v of {String s -> Just (T.unpack s); _ -> Nothing})
hPutStrLn stderr $ "Slack API error: " ++ errMsg
_ -> hPutStrLn stderr "Failed to parse complete response"
_ -> do
let errMsg = fromMaybe "Unknown error" (KM.lookup "error" val >>= \v -> case v of {String s -> Just (T.unpack s); _ -> Nothing})
hPutStrLn stderr $ "Slack API error getting URL: " ++ errMsg
_ -> hPutStrLn stderr "Failed to parse URL response"