{-# LANGUAGE QuasiQuotes #-}
module Network.Globus.Transfer where
import Control.Monad.Catch (MonadCatch, MonadThrow)
import Control.Monad.IO.Class
import Data.Aeson
import Data.Char (toUpper)
import Data.Function ((&))
import Data.Tagged
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Encoding (encodeUtf8)
import GHC.Generics (Generic)
import Network.Globus.Request as Request
import Network.Globus.Types
import Network.HTTP.Client as Http
import Network.HTTP.Types (Header)
import Network.URI
import Network.URI.Static (uri)
fetchSubmissionId :: (MonadThrow m, MonadCatch m, MonadIO m) => Manager -> Token Access -> m (Id Submission)
fetchSubmissionId :: forall (m :: * -> *).
(MonadThrow m, MonadCatch m, MonadIO m) =>
Manager -> Token 'Access -> m (Id 'Submission)
fetchSubmissionId Manager
mgr Token 'Access
access = do
req <- Uri Any -> [Header] -> m Request
forall {k} (m :: * -> *) (a :: k).
(MonadThrow m, MonadCatch m) =>
Uri a -> [Header] -> m Request
Request.get (Uri Any
forall {k} (a :: k). Uri a
transferEndpoint Uri Any -> String -> Uri Any
forall {k} (a :: k). Uri a -> String -> Uri a
/: String
"submission_id") [Token 'Access -> Header
transferAuth Token 'Access
access]
DataKey _ s <- sendJSON mgr req
pure $ Tagged s
transferAuth :: Token Access -> Header
transferAuth :: Token 'Access -> Header
transferAuth (Tagged Text
access) = (HeaderName
"Authorization", ByteString
"Bearer " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
encodeUtf8 Text
access)
transferEndpoint :: Uri a
transferEndpoint :: forall {k} (a :: k). Uri a
transferEndpoint = URI -> Tagged a URI
forall {k} (s :: k) b. b -> Tagged s b
Tagged (URI -> Tagged a URI) -> URI -> Tagged a URI
forall a b. (a -> b) -> a -> b
$ [uri|https://transfer.api.globus.org/v0.10|]
sendTransfer :: (MonadIO m, MonadThrow m, MonadCatch m) => Manager -> Token Access -> TransferRequest -> m TransferResponse
sendTransfer :: forall (m :: * -> *).
(MonadIO m, MonadThrow m, MonadCatch m) =>
Manager -> Token 'Access -> TransferRequest -> m TransferResponse
sendTransfer Manager
mgr Token 'Access
access TransferRequest
treq = do
req <- Uri Any -> [Header] -> TransferRequest -> m Request
forall {k} (m :: * -> *) b (a :: k).
(MonadThrow m, MonadCatch m, ToJSON b) =>
Uri a -> [Header] -> b -> m Request
Request.post (Uri Any
forall {k} (a :: k). Uri a
transferEndpoint Uri Any -> String -> Uri Any
forall {k} (a :: k). Uri a -> String -> Uri a
/: String
"transfer") [Token 'Access -> Header
transferAuth Token 'Access
access] TransferRequest
treq
sendJSON mgr req
fetchTask :: (MonadIO m, MonadThrow m, MonadCatch m) => Manager -> Token Access -> Id Task -> m Task
fetchTask :: forall (m :: * -> *).
(MonadIO m, MonadThrow m, MonadCatch m) =>
Manager -> Token 'Access -> Id Task -> m Task
fetchTask Manager
mgr Token 'Access
access (Tagged Text
ti) = do
req <- Uri Any -> [Header] -> m Request
forall {k} (m :: * -> *) (a :: k).
(MonadThrow m, MonadCatch m) =>
Uri a -> [Header] -> m Request
Request.get (Uri Any
forall {k} (a :: k). Uri a
transferEndpoint Uri Any -> String -> Uri Any
forall {k} (a :: k). Uri a -> String -> Uri a
/: String
"task" Uri Any -> String -> Uri Any
forall {k} (a :: k). Uri a -> String -> Uri a
/: Text -> String
T.unpack Text
ti) [Token 'Access -> Header
transferAuth Token 'Access
access]
sendJSON mgr req
newtype TaskFilters = TaskFilters
{ TaskFilters -> [TaskStatus]
status :: [TaskStatus]
}
deriving (Int -> TaskFilters -> ShowS
[TaskFilters] -> ShowS
TaskFilters -> String
(Int -> TaskFilters -> ShowS)
-> (TaskFilters -> String)
-> ([TaskFilters] -> ShowS)
-> Show TaskFilters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TaskFilters -> ShowS
showsPrec :: Int -> TaskFilters -> ShowS
$cshow :: TaskFilters -> String
show :: TaskFilters -> String
$cshowList :: [TaskFilters] -> ShowS
showList :: [TaskFilters] -> ShowS
Show, TaskFilters -> TaskFilters -> Bool
(TaskFilters -> TaskFilters -> Bool)
-> (TaskFilters -> TaskFilters -> Bool) -> Eq TaskFilters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TaskFilters -> TaskFilters -> Bool
== :: TaskFilters -> TaskFilters -> Bool
$c/= :: TaskFilters -> TaskFilters -> Bool
/= :: TaskFilters -> TaskFilters -> Bool
Eq)
instance Monoid TaskFilters where
mempty :: TaskFilters
mempty = [TaskStatus] -> TaskFilters
TaskFilters []
instance Semigroup TaskFilters where
TaskFilters
tf1 <> :: TaskFilters -> TaskFilters -> TaskFilters
<> TaskFilters
tf2 = TaskFilters{status :: [TaskStatus]
status = TaskFilters
tf1.status [TaskStatus] -> [TaskStatus] -> [TaskStatus]
forall a. Semigroup a => a -> a -> a
<> TaskFilters
tf2.status}
fetchTasks :: (MonadIO m, MonadThrow m, MonadCatch m) => Manager -> Token Access -> TaskFilters -> m TaskList
fetchTasks :: forall (m :: * -> *).
(MonadIO m, MonadThrow m, MonadCatch m) =>
Manager -> Token 'Access -> TaskFilters -> m TaskList
fetchTasks Manager
mgr Token 'Access
access TaskFilters
tf = do
req <- Uri Any -> [Header] -> m Request
forall {k} (m :: * -> *) (a :: k).
(MonadThrow m, MonadCatch m) =>
Uri a -> [Header] -> m Request
Request.get (Uri Any
forall {k} (a :: k). Uri a
transferEndpoint Uri Any -> String -> Uri Any
forall {k} (a :: k). Uri a -> String -> Uri a
/: String
"task_list" Uri Any -> (Uri Any -> Uri Any) -> Uri Any
forall a b. a -> (a -> b) -> b
& Text -> Text -> Uri Any -> Uri Any
forall {k} (a :: k). Text -> Text -> Uri a -> Uri a
param Text
"filter" ([TaskStatus] -> Text
status TaskFilters
tf.status)) [Token 'Access -> Header
transferAuth Token 'Access
access]
sendJSON mgr req
where
status :: [TaskStatus] -> Text
status :: [TaskStatus] -> Text
status [] = Text
""
status [TaskStatus]
ss = Text
"status:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
"," ((TaskStatus -> Text) -> [TaskStatus] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Text
T.toUpper (Text -> Text) -> (TaskStatus -> Text) -> TaskStatus -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (TaskStatus -> String) -> TaskStatus -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TaskStatus -> String
forall a. Show a => a -> String
show) [TaskStatus]
ss)
activityUrl :: Id Task -> Tagged App URI
activityUrl :: Id Task -> Tagged 'App URI
activityUrl (Tagged Text
t) =
URI -> Tagged 'App URI
forall {k} (s :: k) b. b -> Tagged s b
Tagged [uri|https://app.globus.org/activity|] Tagged 'App URI -> String -> Tagged 'App URI
forall {k} (a :: k). Uri a -> String -> Uri a
/: Text -> String
T.unpack Text
t
taskPercentComplete :: Task -> Float
taskPercentComplete :: Task -> Float
taskPercentComplete Task
t
| Task
t.status TaskStatus -> TaskStatus -> Bool
forall a. Eq a => a -> a -> Bool
== TaskStatus
Succeeded = Float
1
| Bool
otherwise = Float -> Float -> Float
forall a. Ord a => a -> a -> a
max Float
bytesProgress Float
filesProgress
where
bytesProgress :: Float
bytesProgress
| Task
t.bytes_checksummed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Float
0
| Bool
otherwise = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Task
t.bytes_transferred Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Task
t.bytes_checksummed
filesProgress :: Float
filesProgress
| Task
t.files Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Float
0
| Bool
otherwise = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Task
t.files_skipped Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Task
t.files_transferred) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Task
t.files
data IdResponse = IdResponse
{ IdResponse -> Text
value :: Text
}
deriving ((forall x. IdResponse -> Rep IdResponse x)
-> (forall x. Rep IdResponse x -> IdResponse) -> Generic IdResponse
forall x. Rep IdResponse x -> IdResponse
forall x. IdResponse -> Rep IdResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. IdResponse -> Rep IdResponse x
from :: forall x. IdResponse -> Rep IdResponse x
$cto :: forall x. Rep IdResponse x -> IdResponse
to :: forall x. Rep IdResponse x -> IdResponse
Generic, Maybe IdResponse
Value -> Parser [IdResponse]
Value -> Parser IdResponse
(Value -> Parser IdResponse)
-> (Value -> Parser [IdResponse])
-> Maybe IdResponse
-> FromJSON IdResponse
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser IdResponse
parseJSON :: Value -> Parser IdResponse
$cparseJSONList :: Value -> Parser [IdResponse]
parseJSONList :: Value -> Parser [IdResponse]
$comittedField :: Maybe IdResponse
omittedField :: Maybe IdResponse
FromJSON, Int -> IdResponse -> ShowS
[IdResponse] -> ShowS
IdResponse -> String
(Int -> IdResponse -> ShowS)
-> (IdResponse -> String)
-> ([IdResponse] -> ShowS)
-> Show IdResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> IdResponse -> ShowS
showsPrec :: Int -> IdResponse -> ShowS
$cshow :: IdResponse -> String
show :: IdResponse -> String
$cshowList :: [IdResponse] -> ShowS
showList :: [IdResponse] -> ShowS
Show)
data Task = Task
{ Task -> TaskStatus
status :: TaskStatus
, Task -> Id Task
task_id :: Id Task
, Task -> Text
label :: Text
,
Task -> Int
files :: Int
, Task -> Int
directories :: Int
, Task -> Int
files_skipped :: Int
, Task -> Int
files_transferred :: Int
, Task -> Int
bytes_transferred :: Int
, Task -> Int
bytes_checksummed :: Int
, Task -> Int
effective_bytes_per_second :: Int
, Task -> Maybe Text
nice_status :: Maybe Text
, Task -> Id 'Collection
source_endpoint_id :: Id Collection
, Task -> Id 'Collection
destination_endpoint_id :: Id Collection
}
deriving ((forall x. Task -> Rep Task x)
-> (forall x. Rep Task x -> Task) -> Generic Task
forall x. Rep Task x -> Task
forall x. Task -> Rep Task x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Task -> Rep Task x
from :: forall x. Task -> Rep Task x
$cto :: forall x. Rep Task x -> Task
to :: forall x. Rep Task x -> Task
Generic, Maybe Task
Value -> Parser [Task]
Value -> Parser Task
(Value -> Parser Task)
-> (Value -> Parser [Task]) -> Maybe Task -> FromJSON Task
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser Task
parseJSON :: Value -> Parser Task
$cparseJSONList :: Value -> Parser [Task]
parseJSONList :: Value -> Parser [Task]
$comittedField :: Maybe Task
omittedField :: Maybe Task
FromJSON, Int -> Task -> ShowS
[Task] -> ShowS
Task -> String
(Int -> Task -> ShowS)
-> (Task -> String) -> ([Task] -> ShowS) -> Show Task
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Task -> ShowS
showsPrec :: Int -> Task -> ShowS
$cshow :: Task -> String
show :: Task -> String
$cshowList :: [Task] -> ShowS
showList :: [Task] -> ShowS
Show, Task -> Task -> Bool
(Task -> Task -> Bool) -> (Task -> Task -> Bool) -> Eq Task
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Task -> Task -> Bool
== :: Task -> Task -> Bool
$c/= :: Task -> Task -> Bool
/= :: Task -> Task -> Bool
Eq)
data TaskStatus
= Active
| Inactive
| Succeeded
| Failed
deriving ((forall x. TaskStatus -> Rep TaskStatus x)
-> (forall x. Rep TaskStatus x -> TaskStatus) -> Generic TaskStatus
forall x. Rep TaskStatus x -> TaskStatus
forall x. TaskStatus -> Rep TaskStatus x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TaskStatus -> Rep TaskStatus x
from :: forall x. TaskStatus -> Rep TaskStatus x
$cto :: forall x. Rep TaskStatus x -> TaskStatus
to :: forall x. Rep TaskStatus x -> TaskStatus
Generic, Int -> TaskStatus -> ShowS
[TaskStatus] -> ShowS
TaskStatus -> String
(Int -> TaskStatus -> ShowS)
-> (TaskStatus -> String)
-> ([TaskStatus] -> ShowS)
-> Show TaskStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TaskStatus -> ShowS
showsPrec :: Int -> TaskStatus -> ShowS
$cshow :: TaskStatus -> String
show :: TaskStatus -> String
$cshowList :: [TaskStatus] -> ShowS
showList :: [TaskStatus] -> ShowS
Show, TaskStatus -> TaskStatus -> Bool
(TaskStatus -> TaskStatus -> Bool)
-> (TaskStatus -> TaskStatus -> Bool) -> Eq TaskStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TaskStatus -> TaskStatus -> Bool
== :: TaskStatus -> TaskStatus -> Bool
$c/= :: TaskStatus -> TaskStatus -> Bool
/= :: TaskStatus -> TaskStatus -> Bool
Eq)
instance FromJSON TaskStatus where
parseJSON :: Value -> Parser TaskStatus
parseJSON = Options -> Value -> Parser TaskStatus
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions{constructorTagModifier = fmap toUpper}
data TaskList = TaskList
{ TaskList -> Int
length :: Int
, TaskList -> Int
limit :: Int
, TaskList -> Int
offset :: Int
, TaskList -> Int
total :: Int
, TaskList -> [Task]
data_ :: [Task]
}
deriving ((forall x. TaskList -> Rep TaskList x)
-> (forall x. Rep TaskList x -> TaskList) -> Generic TaskList
forall x. Rep TaskList x -> TaskList
forall x. TaskList -> Rep TaskList x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TaskList -> Rep TaskList x
from :: forall x. TaskList -> Rep TaskList x
$cto :: forall x. Rep TaskList x -> TaskList
to :: forall x. Rep TaskList x -> TaskList
Generic, Int -> TaskList -> ShowS
[TaskList] -> ShowS
TaskList -> String
(Int -> TaskList -> ShowS)
-> (TaskList -> String) -> ([TaskList] -> ShowS) -> Show TaskList
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TaskList -> ShowS
showsPrec :: Int -> TaskList -> ShowS
$cshow :: TaskList -> String
show :: TaskList -> String
$cshowList :: [TaskList] -> ShowS
showList :: [TaskList] -> ShowS
Show)
instance FromJSON TaskList where
parseJSON :: Value -> Parser TaskList
parseJSON = Options -> Value -> Parser TaskList
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
defaultOptions{fieldLabelModifier = dataLabels}
data TransferResponse = TransferResponse
{ TransferResponse -> Id Task
task_id :: Id Task
, TransferResponse -> Id 'Submission
submission_id :: Id Submission
,
TransferResponse -> Text
message :: Text
, TransferResponse -> Text
resource :: Text
, TransferResponse -> Token Request
request_id :: Token Request
}
deriving ((forall x. TransferResponse -> Rep TransferResponse x)
-> (forall x. Rep TransferResponse x -> TransferResponse)
-> Generic TransferResponse
forall x. Rep TransferResponse x -> TransferResponse
forall x. TransferResponse -> Rep TransferResponse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TransferResponse -> Rep TransferResponse x
from :: forall x. TransferResponse -> Rep TransferResponse x
$cto :: forall x. Rep TransferResponse x -> TransferResponse
to :: forall x. Rep TransferResponse x -> TransferResponse
Generic, Maybe TransferResponse
Value -> Parser [TransferResponse]
Value -> Parser TransferResponse
(Value -> Parser TransferResponse)
-> (Value -> Parser [TransferResponse])
-> Maybe TransferResponse
-> FromJSON TransferResponse
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser TransferResponse
parseJSON :: Value -> Parser TransferResponse
$cparseJSONList :: Value -> Parser [TransferResponse]
parseJSONList :: Value -> Parser [TransferResponse]
$comittedField :: Maybe TransferResponse
omittedField :: Maybe TransferResponse
FromJSON)
data TransferRequest = TransferRequest
{ TransferRequest -> DataType "transfer"
data_type :: DataType "transfer"
, TransferRequest -> Id 'Submission
submission_id :: Id Submission
, TransferRequest -> Maybe Text
label :: Maybe Text
,
TransferRequest -> Id 'Collection
source_endpoint :: Id Collection
, TransferRequest -> Id 'Collection
destination_endpoint :: Id Collection
, TransferRequest -> [TransferItem]
data_ :: [TransferItem]
,
TransferRequest -> SyncLevel
sync_level :: SyncLevel
,
TransferRequest -> Bool
store_base_path_info :: Bool
}
deriving ((forall x. TransferRequest -> Rep TransferRequest x)
-> (forall x. Rep TransferRequest x -> TransferRequest)
-> Generic TransferRequest
forall x. Rep TransferRequest x -> TransferRequest
forall x. TransferRequest -> Rep TransferRequest x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TransferRequest -> Rep TransferRequest x
from :: forall x. TransferRequest -> Rep TransferRequest x
$cto :: forall x. Rep TransferRequest x -> TransferRequest
to :: forall x. Rep TransferRequest x -> TransferRequest
Generic)
instance ToJSON TransferRequest where
toJSON :: TransferRequest -> Value
toJSON = TransferRequest -> Value
forall a. (Generic a, GToJSON' Value Zero (Rep a)) => a -> Value
dataLabelsToJSON
data TransferItem = TransferItem
{ TransferItem -> DataType "transfer_item"
data_type :: DataType "transfer_item"
, TransferItem -> String
source_path :: FilePath
, TransferItem -> String
destination_path :: FilePath
, TransferItem -> Bool
recursive :: Bool
}
deriving ((forall x. TransferItem -> Rep TransferItem x)
-> (forall x. Rep TransferItem x -> TransferItem)
-> Generic TransferItem
forall x. Rep TransferItem x -> TransferItem
forall x. TransferItem -> Rep TransferItem x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. TransferItem -> Rep TransferItem x
from :: forall x. TransferItem -> Rep TransferItem x
$cto :: forall x. Rep TransferItem x -> TransferItem
to :: forall x. Rep TransferItem x -> TransferItem
Generic)
instance ToJSON TransferItem where
toJSON :: TransferItem -> Value
toJSON = TransferItem -> Value
forall a. (Generic a, GToJSON' Value Zero (Rep a)) => a -> Value
dataLabelsToJSON
data SyncLevel
= SyncExists
| SyncSize
| SyncTimestamp
| SyncChecksum
instance ToJSON SyncLevel where
toJSON :: SyncLevel -> Value
toJSON = Scientific -> Value
Number (Scientific -> Value)
-> (SyncLevel -> Scientific) -> SyncLevel -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SyncLevel -> Scientific
forall {a}. Num a => SyncLevel -> a
toInt
where
toInt :: SyncLevel -> a
toInt SyncLevel
SyncExists = a
0
toInt SyncLevel
SyncSize = a
1
toInt SyncLevel
SyncTimestamp = a
2
toInt SyncLevel
SyncChecksum = a
3