{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Network.Ipfs.Api.Core
-- Copyright   :  Aleksandr Krupenkin 2016-2021
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  unknown
--
-- Core IPFS API calls.
--

module Network.Ipfs.Api.Core where

import qualified Codec.Archive.Tar                as Tar
import           Control.Monad.IO.Class           (MonadIO (..))
import           Data.Aeson                       (decode)
import           Data.ByteString.Lazy             (fromStrict)
import           Data.Text                        (Text)
import           Data.Text.Encoding               (encodeUtf8)
import           Network.HTTP.Client              (responseBody)
import           Servant.API.ContentTypes         (NoContent)

import           Network.Ipfs.Api.Internal        (_cat, _dns, _get, _id,
                                                   _idPeer, _ls, _shutdown,
                                                   _version)
import           Network.Ipfs.Api.Internal.Call   (call, multipartCall,
                                                   streamCall)
import           Network.Ipfs.Api.Internal.Stream (_ping, _refs, _refsLocal)
import           Network.Ipfs.Api.Types           (AddObj, CatReturnType,
                                                   DnsObj, IdObj, LsObj,
                                                   VersionObj)
import           Network.Ipfs.Client              (IpfsT)

-- | Show IPFS object data.
cat :: MonadIO m => Text -> IpfsT m CatReturnType
cat :: Text -> IpfsT m Text
cat = ClientM Text -> IpfsT m Text
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call (ClientM Text -> IpfsT m Text)
-> (Text -> ClientM Text) -> Text -> IpfsT m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM Text
_cat

-- | Add a file or directory to ipfs.
add :: MonadIO m => Text -> IpfsT m (Maybe AddObj)
add :: Text -> IpfsT m (Maybe AddObj)
add = (Response ByteString -> Maybe AddObj)
-> IpfsT m (Response ByteString) -> IpfsT m (Maybe AddObj)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Response ByteString -> Maybe AddObj
decodeResponse (IpfsT m (Response ByteString) -> IpfsT m (Maybe AddObj))
-> (Text -> IpfsT m (Response ByteString))
-> Text
-> IpfsT m (Maybe AddObj)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> IpfsT m (Response ByteString)
forall (m :: * -> *).
MonadIO m =>
Text -> Text -> IpfsT m (Response ByteString)
multipartCall Text
"add"
  where
    decodeResponse :: Response ByteString -> Maybe AddObj
decodeResponse = ByteString -> Maybe AddObj
forall a. FromJSON a => ByteString -> Maybe a
decode (ByteString -> Maybe AddObj)
-> (Response ByteString -> ByteString)
-> Response ByteString
-> Maybe AddObj
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response ByteString -> ByteString
forall body. Response body -> body
responseBody

-- | List directory contents for Unix filesystem objects.
ls :: MonadIO m => Text -> IpfsT m LsObj
ls :: Text -> IpfsT m LsObj
ls = ClientM LsObj -> IpfsT m LsObj
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call (ClientM LsObj -> IpfsT m LsObj)
-> (Text -> ClientM LsObj) -> Text -> IpfsT m LsObj
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM LsObj
_ls

-- | Download IPFS objects.
get :: MonadIO m => Text -> IpfsT m Text
get :: Text -> IpfsT m Text
get Text
hash = do
    Text
ret <- ClientM Text -> IpfsT m Text
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call (ClientM Text -> IpfsT m Text) -> ClientM Text -> IpfsT m Text
forall a b. (a -> b) -> a -> b
$ Text -> ClientM Text
_get Text
hash
    do IO () -> IpfsT m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IpfsT m ()) -> IO () -> IpfsT m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> Entries FormatError -> IO ()
forall e. Exception e => FilePath -> Entries e -> IO ()
Tar.unpack FilePath
"getResponseDirectory" (Entries FormatError -> IO ())
-> (ByteString -> Entries FormatError) -> ByteString -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Entries FormatError
Tar.read (ByteString -> Entries FormatError)
-> (ByteString -> ByteString) -> ByteString -> Entries FormatError
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fromStrict (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> ByteString
encodeUtf8 Text
ret
       Text -> IpfsT m Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"The content has been stored in getResponseDirectory."

-- | Show ipfs version information.
version :: MonadIO m => IpfsT m VersionObj
version :: IpfsT m VersionObj
version = ClientM VersionObj -> IpfsT m VersionObj
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call ClientM VersionObj
_version

-- | Show ipfs node id info.
id :: MonadIO m => IpfsT m IdObj
id :: IpfsT m IdObj
id = ClientM IdObj -> IpfsT m IdObj
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call ClientM IdObj
_id

-- | Show ipfs node id info of the given peerId.
idPeer :: MonadIO m => Text -> IpfsT m IdObj
idPeer :: Text -> IpfsT m IdObj
idPeer = ClientM IdObj -> IpfsT m IdObj
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call (ClientM IdObj -> IpfsT m IdObj)
-> (Text -> ClientM IdObj) -> Text -> IpfsT m IdObj
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM IdObj
_idPeer

-- | Resolve DNS links.
dns :: MonadIO m => Text -> IpfsT m DnsObj
dns :: Text -> IpfsT m DnsObj
dns = ClientM DnsObj -> IpfsT m DnsObj
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call (ClientM DnsObj -> IpfsT m DnsObj)
-> (Text -> ClientM DnsObj) -> Text -> IpfsT m DnsObj
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM DnsObj
_dns

-- | List links (references) from an object.
refs :: MonadIO m => Text -> m ()
refs :: Text -> m ()
refs = ClientM (SourceT IO RefsObj) -> m ()
forall (m :: * -> *) a.
(MonadIO m, Show a) =>
ClientM (SourceT IO a) -> m ()
streamCall (ClientM (SourceT IO RefsObj) -> m ())
-> (Text -> ClientM (SourceT IO RefsObj)) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM (SourceT IO RefsObj)
_refs

-- | List all local references.
refsLocal :: MonadIO m => m ()
refsLocal :: m ()
refsLocal = ClientM (SourceT IO RefsObj) -> m ()
forall (m :: * -> *) a.
(MonadIO m, Show a) =>
ClientM (SourceT IO a) -> m ()
streamCall ClientM (SourceT IO RefsObj)
_refsLocal

-- | Send echo request packets to IPFS hosts.
ping :: MonadIO m => Text -> m ()
ping :: Text -> m ()
ping = ClientM (SourceT IO PingObj) -> m ()
forall (m :: * -> *) a.
(MonadIO m, Show a) =>
ClientM (SourceT IO a) -> m ()
streamCall (ClientM (SourceT IO PingObj) -> m ())
-> (Text -> ClientM (SourceT IO PingObj)) -> Text -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ClientM (SourceT IO PingObj)
_ping

-- | Shut down the ipfs daemon.
shutdown :: MonadIO m => IpfsT m NoContent
shutdown :: IpfsT m NoContent
shutdown = ClientM NoContent -> IpfsT m NoContent
forall (m :: * -> *) a. MonadIO m => ClientM a -> IpfsT m a
call ClientM NoContent
_shutdown