module Network.IPFS.DAG
  ( put
  , putNode
  , putRemote
  ) where

import           Data.ByteString.Lazy.Char8        as CL
import qualified Network.IPFS.Internal.UTF8        as UTF8
import qualified RIO.ByteString.Lazy               as Lazy

import           Servant.Client
import qualified Servant.Multipart.Client          as Multipart.Client

import           Network.IPFS.Prelude

import           Network.IPFS.Add.Error            as IPFS.Add
import qualified Network.IPFS.Client               as IPFS.Client
import           Network.IPFS.Client.DAG.Put.Types as DAG.Put
import           Network.IPFS.DAG.Node.Types       as DAG
import           Network.IPFS.File.Form.Types      as File
import           Network.IPFS.File.Types           as File
import           Network.IPFS.Local.Class          as IPFS
import           Network.IPFS.Remote.Class         as IPFS
import           Network.IPFS.Types                as IPFS

put :: MonadLocalIPFS m => Lazy.ByteString -> m (Either IPFS.Add.Error IPFS.CID)
put :: ByteString -> m (Either Error CID)
put ByteString
raw = [Opt] -> ByteString -> m (Either Error ByteString)
forall (m :: * -> *).
MonadLocalIPFS m =>
[Opt] -> ByteString -> m (Either Error ByteString)
IPFS.runLocal [Item [Opt]
"dag", Item [Opt]
"put", Item [Opt]
"-f", Item [Opt]
"dag-pb"] ByteString
raw m (Either Error ByteString)
-> (Either Error ByteString -> m (Either Error CID))
-> m (Either Error CID)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
  Right ByteString
result ->
    case ByteString -> [ByteString]
CL.lines ByteString
result of
      [Item [ByteString]
cid] ->
        ByteString
Item [ByteString]
cid
          ByteString -> (ByteString -> Text) -> Text
forall a b. a -> (a -> b) -> b
|> ByteString -> Text
forall a. Show a => a -> Text
UTF8.textShow
          Text -> (Text -> Text) -> Text
forall a b. a -> (a -> b) -> b
|> Natural -> Text -> Text
UTF8.stripN Natural
1
          Text -> (Text -> CID) -> CID
forall a b. a -> (a -> b) -> b
|> Text -> CID
mkCID
          CID -> (CID -> Either Error CID) -> Either Error CID
forall a b. a -> (a -> b) -> b
|> CID -> Either Error CID
forall a b. b -> Either a b
Right
          Either Error CID
-> (Either Error CID -> m (Either Error CID))
-> m (Either Error CID)
forall a b. a -> (a -> b) -> b
|> Either Error CID -> m (Either Error CID)
forall (m :: * -> *) a. Monad m => a -> m a
return

      [ByteString]
bad ->
        Either Error CID -> m (Either Error CID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either Error CID -> m (Either Error CID))
-> (Text -> Either Error CID) -> Text -> m (Either Error CID)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Error -> Either Error CID
forall a b. a -> Either a b
Left (Error -> Either Error CID)
-> (Text -> Error) -> Text -> Either Error CID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Error
UnexpectedOutput (Text -> m (Either Error CID)) -> Text -> m (Either Error CID)
forall a b. (a -> b) -> a -> b
$ [ByteString] -> Text
forall a. Show a => a -> Text
UTF8.textShow [ByteString]
bad

  Left Error
err ->
    Either Error CID -> m (Either Error CID)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either Error CID -> m (Either Error CID))
-> (Text -> Either Error CID) -> Text -> m (Either Error CID)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Error -> Either Error CID
forall a b. a -> Either a b
Left (Error -> Either Error CID)
-> (Text -> Error) -> Text -> Either Error CID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Error
UnknownAddErr (Text -> m (Either Error CID)) -> Text -> m (Either Error CID)
forall a b. (a -> b) -> a -> b
$ Error -> Text
forall a. Show a => a -> Text
UTF8.textShow Error
err

putNode :: MonadLocalIPFS m => DAG.Node -> m (Either IPFS.Add.Error IPFS.CID)
putNode :: Node -> m (Either Error CID)
putNode Node
node = ByteString -> m (Either Error CID)
forall (m :: * -> *).
MonadLocalIPFS m =>
ByteString -> m (Either Error CID)
put (ByteString -> m (Either Error CID))
-> ByteString -> m (Either Error CID)
forall a b. (a -> b) -> a -> b
$ Node -> ByteString
forall a. ToJSON a => a -> ByteString
encode Node
node

putRemote :: MonadRemoteIPFS m => File.Serialized -> m (Either ClientError DAG.Put.Response)
putRemote :: Serialized -> m (Either ClientError Response)
putRemote Serialized
file = do
  ByteString
boundary  <- IO ByteString -> m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ByteString
Multipart.Client.genBoundary
  ClientM Response -> m (Either ClientError Response)
forall (m :: * -> *) a.
MonadRemoteIPFS m =>
ClientM a -> m (Either ClientError a)
runRemote (Bool -> (ByteString, Form) -> ClientM Response
IPFS.Client.dagPut Bool
True (ByteString
boundary, Text -> Serialized -> Form
File.Form Text
"file" Serialized
file))