2 Module : Gargantext.Prelude.Utils
3 Description : Useful Tools near Prelude of the project
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
12 module Gargantext.Prelude.Utils
15 import Data.Tuple.Extra (both)
16 import Control.Exception
17 import Control.Lens (view)
18 import Control.Monad.Reader (MonadReader)
19 import Control.Monad.Random.Class (MonadRandom)
20 import Data.Text (Text)
21 import qualified Data.Text as Text
22 import GHC.IO (FilePath)
23 import System.Directory (createDirectoryIfMissing)
24 import qualified System.Directory as SD
25 import System.IO.Error
26 import System.Random (newStdGen)
27 import qualified System.Random.Shuffle as SRS
29 import Gargantext.Prelude.Config
30 import Gargantext.Prelude.Crypto.Hash
31 import Gargantext.Database.Prelude (HasConfig(..))
32 import Gargantext.Database.Admin.Types.Node (NodeId, NodeType)
33 import Gargantext.Prelude
35 --------------------------------------------------------------------------
36 shuffle :: MonadRandom m => [a] -> m [a]
37 shuffle ns = SRS.shuffleM ns
39 --------------------------------------------------------------------------
40 data NodeToHash = NodeToHash { nodeType :: NodeType
43 -------------------------------------------------------------------
44 type FolderPath = FilePath
45 type FileName = FilePath
47 -- | toPath' example of use:
49 >>> toPath' (1,2) ("","helloword")
52 >>> toPath' (2,2) ("","helloword")
55 >>> toPath' (2,3) ("","helloword")
59 toPath :: Int -> Text -> (FolderPath, FileName)
60 toPath n tx = both Text.unpack $ toPath' (2,n) ("", tx)
62 toPath' :: (Int,Int) -> (Text,Text) -> (Text,Text)
63 toPath' (n,m) (t,x) = foldl' (\tx _ -> toPath'' m tx) (t,x) [1..n]
65 toPath'' :: Int -> (Text, Text) -> (Text, Text)
66 toPath'' n (fp,fn) = (fp'',fn')
68 (fp',fn') = Text.splitAt n fn
69 fp'' = Text.intercalate "/" [fp,fp']
71 -------------------------------------------------------------------
72 -------------------------------------------------------------------
73 class SaveFile a where
74 saveFile' :: FilePath -> a -> IO ()
76 class ReadFile a where
77 readFile' :: FilePath -> IO a
80 folderFilePath :: (MonadReader env m, MonadBase IO m) => m (FolderPath, FileName)
82 (foldPath, fileName) <- liftBase $ (toPath 3) . hash . show <$> newStdGen
84 pure (foldPath, fileName)
87 writeFile :: (MonadReader env m, MonadBase IO m, HasConfig env, SaveFile a)
90 dataPath <- view $ hasConfig . gc_datafilepath
92 (foldPath, fileName) <- folderFilePath
94 let filePath = foldPath <> "/" <> fileName
95 dataFoldPath = dataPath <> "/" <> foldPath
96 dataFileName = dataPath <> "/" <> filePath
98 _ <- liftBase $ createDirectoryIfMissing True dataFoldPath
99 _ <- liftBase $ saveFile' dataFileName a
104 readFile :: (MonadReader env m, MonadBase IO m, HasConfig env, ReadFile a)
107 dataPath <- view $ hasConfig . gc_datafilepath
108 liftBase $ readFile' $ dataPath <> "/" <> fp
110 removeFile :: (MonadReader env m, MonadBase IO m, HasConfig env)
113 dataPath <- view $ hasConfig . gc_datafilepath
114 liftBase $ SD.removeFile (dataPath <> "/" <> fp) `catch` handleExists
117 | isDoesNotExistError e = return ()
118 | otherwise = throwIO e