1 {-# LANGUAGE TypeOperators #-}
3 module Gargantext.Core.Text.Upload
13 import qualified Data.Map.Strict as Map
14 import qualified Data.Text as T
15 import qualified Data.Text.Encoding as TE
16 import Gargantext.Utils.Servant (CSV, Markdown)
17 import Network.HTTP.Client (newManager, Request(..))
18 import Network.HTTP.Client.TLS (tlsManagerSettings)
24 newtype Host = Host { fromHost :: Text }
25 newtype DocId = DocId { fromDocId :: Text }
26 newtype Data = Data { fromData :: Text }
30 -- TODO SocialCalc, Excel XML ?
32 instance MimeRender CSV Data where
33 mimeRender p (Data d) = mimeRender p d
34 instance MimeRender PlainText Data where
35 mimeRender p (Data d) = mimeRender p d
37 instance ToHttpApiData DocId where
38 toUrlPiece (DocId docId) = docId
41 -- https://github.com/audreyt/ethercalc/blob/master/API.md
45 ReqBody '[PlainText] Data
46 :> Post '[PlainText] Text
49 :> ReqBody '[PlainText] Data
50 :> Put '[PlainText] Text
55 :> Post '[PlainText, CSV] Text
58 :> ReqBody '[CSV] Data
59 :> Put '[PlainText, CSV] Text
62 ethercalcAPI :: Proxy EthercalcAPI
65 ethercalcNewPlain :: Data -> ClientM Text
66 ethercalcUpdatePlain :: DocId -> Data -> ClientM Text
67 ethercalcNewCSV :: Data -> ClientM Text
68 ethercalcUpdateCSV :: DocId -> Data -> ClientM Text
69 ethercalcNewPlain :<|> ethercalcUpdatePlain
70 :<|> ethercalcNewCSV :<|> ethercalcUpdateCSV = client ethercalcAPI
73 ------------------------------
75 -- | Create new or update existing Ethercalc document (depending on
76 -- `Maybe DocId` constructor). `Data` can be in various formats (CSV,
78 ethercalc :: Host -> Maybe DocId -> ContentType Data -> IO (Either ClientError Text)
79 ethercalc (Host host) mDocId ctD = do
80 manager' <- newManager tlsManagerSettings
81 let env = mkClientEnv manager' (BaseUrl Https (T.unpack host) 443 "")
83 (Nothing, CTPlain d) -> runClientM (ethercalcNewPlain d) env
84 (Nothing, CTCSV d) -> runClientM (ethercalcNewCSV d) env
85 (Just docId, CTPlain d) -> runClientM (ethercalcUpdatePlain docId d) env
86 (Just docId, CTCSV d) -> runClientM (ethercalcUpdateCSV docId d) env
88 -----------------------------------
92 ReqBody '[Markdown] Data
93 :> Post '[Markdown] Text
96 instance MimeRender Markdown Data where
97 mimeRender p (Data d) = mimeRender p d
99 codimdAPI :: Proxy CodiMDAPI
102 codimdAPINew :: Data -> ClientM Text
103 codimdAPINew = client codimdAPI
106 -- | Create a new CodiMD document (with Markdown contents). Please
107 -- note that AFAIK CodiMD update is not supported, see
108 -- https://github.com/hackmdio/codimd/issues/1013
109 codimd :: Host -> Data -> IO (Either Text Text)
110 codimd (Host host) d = do
111 manager' <- newManager tlsManagerSettings
112 let env' = mkClientEnv manager' (BaseUrl Https (T.unpack host) 443 "")
113 let env = env' { makeClientRequest = \burl req -> (defaultMakeClientRequest burl req) { redirectCount = 0 } }
114 eRes <- runClientM (codimdAPINew d) env
116 -- NOTE We actually expect a redirect here (a 302 with the new
117 -- page's URL). Hence we expect a `Left FailureResponse` because
118 -- we have set `redirectCount = 0` above.
119 Left (FailureResponse _req (Response { responseHeaders })) ->
120 case Map.lookup "location" (Map.fromList $ toList responseHeaders) of
121 Nothing -> Left "Cannot find 'Location' header in response"
122 Just loc -> Right $ TE.decodeUtf8 loc
123 err -> Left $ "Error creating codimd document: " <> show err