Skip to content

Commit

Permalink
Load config and load projects
Browse files Browse the repository at this point in the history
  • Loading branch information
nodew committed Jul 16, 2022
1 parent 8b34b8b commit c13877f
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 135 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.stack-work/
stargaze-cli.cabal
2 changes: 1 addition & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Changelog for github-star-atlas-cli
# Changelog for stargaze-cli

## Unreleased changes
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# github-star-atlas-cli
# stargaze-cli
4 changes: 2 additions & 2 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Main where


import CLI (loadProjects)
import Stargaze.CLI (loadAllProjects)

main :: IO ()
main = loadProjects
main = loadAllProjects "nodew"
76 changes: 0 additions & 76 deletions github-star-atlas-cli.cabal

This file was deleted.

6 changes: 3 additions & 3 deletions hie.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
cradle:
stack:
- path: "./src"
component: "github-star-atlas-cli:lib"
component: "stargaze-cli:lib"
- path: "./app"
component: "github-star-atlas-cli:exe:github-star-atlas-cli-exe"
component: "stargaze-cli:exe:stargaze-cli-exe"
- path: "./test"
component: "github-star-atlas-cli:test:github-star-atlas-cli-test"
component: "stargaze-cli:test:stargaze-cli-test"
28 changes: 12 additions & 16 deletions package.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: github-star-atlas-cli
name: stargaze-cli
version: 0.1.0.0
github: "nodew/github-star-atlas-cli"
github: "nodew/stargaze-cli"
license: BSD3
author: "Qiao Wang"
maintainer: "[email protected]"
Expand All @@ -10,44 +10,40 @@ extra-source-files:
- README.md
- ChangeLog.md

# Metadata used when publishing your package
# synopsis: Short description of your package
# category: Web

# To avoid duplicated efforts in documentation and dealing with the
# complications of embedding Haddock markup inside cabal files, it is
# common to point users to the README.md file.
description: Please see the README on GitHub at <https://github.com/nodew/github-star-atlas-cli#readme>
description: Please see the README on GitHub at <https://github.com/nodew/stargaze-cli#readme>

dependencies:
- base >= 4.7 && < 5
- time
- aeson
- text
- aeson-pretty
- bytestring
- req
- path
- path-io
- text
- time

library:
source-dirs: src

executables:
github-star-atlas-cli-exe:
stargaze:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- github-star-atlas-cli
- stargaze-cli

tests:
github-star-atlas-cli-test:
stargaze-cli-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- github-star-atlas-cli
- stargaze-cli
30 changes: 0 additions & 30 deletions src/CLI.hs

This file was deleted.

134 changes: 134 additions & 0 deletions src/Stargaze/CLI.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module Stargaze.CLI
( loadConfig
, writeConfig
, loadAllProjects
) where

import Network.HTTP.Req
( (/:),
defaultHttpConfig,
header,
https,
jsonResponse,
req,
responseBody,
runReq,
GET(GET),
NoReqBody(NoReqBody),
QueryParam(queryParam) )
import Data.Aeson (decode)
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.Data (Proxy(Proxy))
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as B
import Control.Monad.IO.Class (MonadIO(liftIO))
import qualified Control.Monad as T
import Path
( Path, Dir, Abs, File, toFilePath, (</>), mkRelDir, mkRelFile )
import Path.IO
( createDir, doesDirExist, doesFileExist, getHomeDir )
import System.Exit (exitFailure, exitSuccess)

import Stargaze.Types ( Project, Config(cfgUser) )

{- Maximum allowed page size -}
pageSize :: Int
pageSize = 100

loadConfig :: IO (Either String Config)
loadConfig = do
configFilePath <- getConfigFilePath
existed <- doesFileExist configFilePath
if not existed then do
return $ Left "Config file doesn't exist, try \"stargaze config --user [GitHub Username]\""
else do
content <- B.readFile $ toFilePath configFilePath
case decode content of
Just cfg ->
if cfgUser cfg /= "" then
return $ Right cfg
else do
return $ Left "GitHub user name hasn't been config yet, try \"stargaze config --user [GitHub Username]\""
_ -> do
return $ Left $ "Invalid config, please check your config at " ++ toFilePath configFilePath

writeConfig :: Config -> IO ()
writeConfig cfg = do
configFilePath <- getConfigFilePath
let content = encodePretty cfg
B.writeFile (toFilePath configFilePath) content

loadAllProjects :: IO ()
loadAllProjects = do
config <- loadConfig
case config of
Left err -> putStrLn err
Right config -> loadAllProjectsOfUser $ cfgUser config

loadAllProjectsOfUser :: String -> IO ()
loadAllProjectsOfUser user = do
projects <- loadAllProjects' user 1
saveProjectsToLocal projects
putStrLn "Data load completed"

loadAllProjects' :: String -> Int -> IO [Project]
loadAllProjects' user page = do
projects <- loadPagedProjects user page
if length projects < pageSize then do -- Last page
putStrLn $ " Loaded" ++ show (page * pageSize + length projects) ++ " projects"
return projects
else do
putStrLn $ "Loaded " ++ show (page * pageSize) ++ " projects"
nextPageProjects <- loadAllProjects' user (page + 1)
return $ projects ++ nextPageProjects

loadPagedProjects :: String -> Int -> IO [Project]
loadPagedProjects user page = runReq defaultHttpConfig $ do
let url = https "api.github.com" /: "users" /: T.pack user /: "starred"
let options = queryParam "page" (Just $ show page)
<> queryParam "per_page" (Just $ show pageSize)
<> header "User-Agent" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49"
response <- req GET url NoReqBody jsonResponse options
return $ responseBody response

saveProjectsToLocal :: [Project] -> IO ()
saveProjectsToLocal projects = do
projectsFilePath <- getProjectsFilePath
let content = encodePretty projects
B.writeFile (toFilePath projectsFilePath) content

loadLocalProjects :: IO (Either String [Project])
loadLocalProjects = do
projectsFilePath <- getProjectsFilePath
existed <- doesFileExist projectsFilePath
if not existed then
return $ Left "Run \"stargaze update\" first"
else do
content <- B.readFile (toFilePath projectsFilePath)
case decode content of
Just projects -> return $ Right projects
_ -> return $ Left "Run \"stargaze update\" first"

getConfigFilePath :: IO (Path Abs File)
getConfigFilePath = do
dotDir <- getOrCeateDotPath
return $ dotDir </> $(mkRelFile "config.json")

getProjectsFilePath :: IO (Path Abs File)
getProjectsFilePath = do
dotDir <- getOrCeateDotPath
return $ dotDir </> $(mkRelFile "projects.json")

getOrCeateDotPath :: IO (Path Abs Dir)
getOrCeateDotPath = do
homeDir <- getHomeDir
let dotDir = homeDir </> $(mkRelDir ".stargaze")
existed <- doesDirExist dotDir
if existed then
return dotDir
else do
createDir dotDir
return dotDir
22 changes: 16 additions & 6 deletions src/Types.hs → src/Stargaze/Types.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}

module Types where
module Stargaze.Types where

import Data.Time ( UTCTime )
import Data.Int (Int64, Int32)
Expand All @@ -18,23 +18,23 @@ import Data.Aeson
Options(fieldLabelModifier),
Value(Object),
KeyValue((.=)),
ToJSON(toJSON) )
ToJSON(toJSON), genericToJSON )

data Config = Config
{ cfgUser :: String
, cfgUpdatedAt :: UTCTime
, cfgUpdatedAt :: Maybe UTCTime
} deriving (Show)

instance FromJSON Config where
parseJSON (Object o) =
Config <$> o .: "user"
<*> o .: "updatedAt"
<*> o .: "updated_at"
parseJSON _ = mzero

instance ToJSON Config where
toJSON cfg = object
[ "user" .= toJSON (cfgUser cfg)
, "updatedAt" .= toJSON (cfgUpdatedAt cfg)
[ "user" .= toJSON (cfgUser cfg)
, "updated_at" .= toJSON (cfgUpdatedAt cfg)
]

data Project = Project
Expand All @@ -58,6 +58,11 @@ instance FromJSON Project where
defaultOptions
{ fieldLabelModifier = camelTo2 '_' . drop 7 }

instance ToJSON Project where
toJSON = genericToJSON
defaultOptions
{ fieldLabelModifier = camelTo2 '_' . drop 7 }

data Author = Author
{ authorLogin :: String
, authorId :: Int64
Expand All @@ -70,3 +75,8 @@ instance FromJSON Author where
parseJSON = genericParseJSON
defaultOptions
{ fieldLabelModifier = camelTo2 '_' . drop 6 }

instance ToJSON Author where
toJSON = genericToJSON
defaultOptions
{ fieldLabelModifier = camelTo2 '_' . drop 6 }

0 comments on commit c13877f

Please sign in to comment.