{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module : Network.GitHub.Types -- Copyright : (c) Finlay Thompson, 2015 -- License : BSD3 -- Maintainer : finlay.thompson@gmail.com -- Stability : experimental -- -- Most of the types only parse part of the data availble in the return -- values from the GitHub API. These will be added to as required. module Network.GitHub.Types ( CountedList(..) , Organisation(..) , OrganisationMember(..) , OrgLogin , Owner , UserLogin(..) , Team(..) , TeamId , Member(..) , MemberId , Repository(..) , Repositories(..) , Permission(..) , RepositoryName , User(..) , RepoName -- short version , Sha , Commit(..) , Content(..) , Issue(..) , Label(..) , Milestone(..) , EarlyAccessJSON , Installation(..) , Installations(..) , InstallationAccessToken(..) , InstallationUser(..) ) where import Control.Monad import GHC.Generics import GHC.TypeLits (KnownSymbol, symbolVal, Symbol) import Data.Aeson import Data.Text import qualified Data.Text as T (pack) import Data.Time import Data.Proxy (Proxy(..)) import qualified Data.List.NonEmpty as NE (NonEmpty(..)) import qualified Network.HTTP.Media as M ((//)) import Servant.API (JSON, Accept(..), MimeUnrender(..)) -- | List of results including a total count data CountedList (name :: Symbol) a = CountedList { totalCount :: Int , items :: [a] } instance (FromJSON a, KnownSymbol name) => FromJSON (CountedList name a) where parseJSON (Object o) = CountedList <$> o .: "total_count" <*> o .: T.pack (symbolVal (Proxy :: Proxy name)) parseJSON _ = mzero -- | Organisation data Organisation = Organisation { orgLogin :: OrgLogin , orgId :: Int , orgDescription :: Maybe Text } deriving (Eq, Show) -- | Primary identifier for an organisation is the login type OrgLogin = Text type Owner = Text instance FromJSON Organisation where parseJSON (Object o) = Organisation <$> o .: "login" <*> o .: "id" <*> o .: "description" parseJSON _ = mzero -- | Team data Team = Team { teamId :: TeamId , teamName :: Text , teamDescription :: Maybe Text , teamPermission :: Maybe Text } deriving (Eq, Show) -- | Identifier for a team id type TeamId = Integer instance FromJSON Team where parseJSON (Object o) = Team <$> o .: "id" <*> o .: "name" <*> o .: "description" <*> o .: "permission" parseJSON _ = mzero -- | Member data Member = Member { memberId :: MemberId , memberLogin :: Text } deriving (Eq, Show) -- | members are identified by ids type MemberId = Integer instance FromJSON Member where parseJSON (Object o) = Member <$> o .: "id" <*> o .: "login" parseJSON _ = mzero -- | OrganisationMember data OrganisationMember = OrganisationMember { orgmemberRole :: Text , orgmemberState :: Text , orgmemberOrganisation :: Organisation , orgmemberUser :: Member } deriving (Eq, Show) instance FromJSON OrganisationMember where parseJSON (Object o) = OrganisationMember <$> o .: "role" <*> o .: "state" <*> o .: "organization" <*> o .: "user" parseJSON _ = mzero -- | Repository data Repository = Repository { repositoryName :: RepositoryName , repositoryDescription :: Maybe Text , repositoryDefaultBranch :: Maybe Text , repositoryPrivate :: Bool , repositoryPermissions :: Maybe Permission } deriving (Eq, Show) -- | repositories are identified by their name type RepositoryName = Text data Permission = Push | Pull | Admin deriving (Eq) instance Show Permission where show Push = "push" show Pull = "pull" show Admin = "admin" instance FromJSON Permission where parseJSON (Object o) = do admin <- o .: "admin" push <- o .: "push" return $ if admin then Admin else if push then Push else Pull parseJSON _ = mzero instance FromJSON Repository where parseJSON (Object o) = Repository <$> o .: "full_name" <*> o .:? "description" <*> o .:? "default_branch" <*> o .: "private" <*> o .:? "permissions" parseJSON _ = mzero -- | Repositories type Repositories = CountedList "repositories" Repository -- | Organisation data User = User { userLogin :: Text , userId :: Int , userName :: Maybe Text , userCompany :: Maybe Text , userEmail :: Maybe Text } deriving (Eq, Show) instance FromJSON User where parseJSON (Object o) = User <$> o .: "login" <*> o .: "id" <*> o .: "name" <*> o .: "company" <*> o .: "email" parseJSON _ = mzero instance ToJSON User where toJSON u = object [ "login" .= userLogin u , "id" .= userId u , "name" .= userName u , "company" .= userCompany u , "email" .= userEmail u ] -- | Commit type RepoName = Text type Sha = Text data Commit = Commit { commitMessage :: Text , commitUrl :: Text } deriving (Eq, Show) -- TODO: fix this instance instance FromJSON Commit where parseJSON (Object o) = do html_url <- o .: "html_url" commit <- o .: "commit" message <- commit .: "message" return $ Commit message html_url parseJSON _ = mzero instance ToJSON Commit where toJSON c = let head_commit = object [ "message" .= commitMessage c , "url" .= commitUrl c ] in object [ "commits" .= toJSON [ head_commit ] , "head_commit" .= head_commit ] -- | Content data Content = Content { contentType :: Text , contentEncoding :: Text , contentSize :: Int , contentName :: Text , contentPath :: Text , contentContent :: Text } deriving (Eq, Show) instance FromJSON Content where parseJSON (Object o) = Content <$> o .: "type" <*> o .: "encoding" <*> o .: "size" <*> o .: "name" <*> o .: "path" <*> o .: "content" parseJSON _ = mzero newtype UserLogin = UserLogin Text deriving (Show, Eq) instance FromJSON UserLogin where parseJSON (Object o) = UserLogin <$> o .: "login" parseJSON _ = mzero data Milestone = Milestone { milestoneNumber :: Int , milestoneState :: Text , milestoneTitle :: Text , milestoneDescripiton :: Maybe Text , milestoneCreator :: UserLogin , milestoneOpenIssues :: Int , milestoneClosedIssues :: Int , milestoneCreated :: UTCTime , milestoneUpdated :: Maybe UTCTime , milestoneClosed :: Maybe UTCTime , milestoneDueOn :: Maybe UTCTime } deriving (Show, Eq) instance FromJSON Milestone where parseJSON (Object o) = Milestone <$> o .: "number" <*> o .: "state" <*> o .: "title" <*> o .:? "description" <*> o .: "creator" <*> o .: "open_issues" <*> o .: "closed_issues" <*> o .: "created_at" <*> o .: "updated_at" <*> o .: "closed_at" <*> o .: "due_on" parseJSON _ = mzero newtype Label = Label Text deriving (Eq, Show) instance FromJSON Label where parseJSON (Object o) = Label <$> o .: "name" parseJSON _ = mzero -- | Issue data Issue = Issue { issueNumber :: Int , issueUrl :: Text , issueState :: Text , issueTitle :: Text , issueBody :: Text , issueUser :: UserLogin , issueAssignee :: Maybe UserLogin , issueMilestone :: Maybe Milestone , issueLabels :: [Label] , issueLocked :: Bool , issueComments :: Int , issueCreated :: UTCTime , issueUpdated :: UTCTime , issueClosed :: Maybe UTCTime } deriving (Generic, Eq, Show) instance FromJSON Issue where parseJSON (Object o) = Issue <$> o .: "number" <*> o .: "html_url" <*> o .: "state" <*> o .: "title" <*> o .: "body" <*> o .: "user" <*> o .:? "assignee" <*> o .:? "milestone" <*> o .: "labels" <*> o .: "locked" <*> o .: "comments" <*> o .: "created_at" <*> o .: "updated_at" <*> o .: "closed_at" parseJSON _ = mzero data EarlyAccessJSON instance FromJSON t => MimeUnrender EarlyAccessJSON t where mimeUnrender _ = mimeUnrender (Proxy :: Proxy JSON) instance Accept EarlyAccessJSON where contentTypes _ = "application" M.// "vnd.github.machine-man-preview+json" NE.:| ["application" M.// "json"] -- | Installation data Installation = Installation { installationId :: Int , installationAppId :: Int , installationTargetId :: Int , installationTargetType :: Text } deriving (Eq, Show) instance FromJSON Installation where parseJSON (Object o) = Installation <$> o .: "id" <*> o .: "app_id" <*> o .: "target_id" <*> o .: "target_type" parseJSON _ = mzero -- | IntegrationInstallations type Installations = CountedList "integration_installations" Installation data InstallationAccessToken = InstallationAccessToken { token :: Text } deriving (Eq, Show, Generic) instance FromJSON InstallationAccessToken instance ToJSON InstallationAccessToken data InstallationUser = InstallationUser { user_id :: Int } deriving (Eq, Show, Generic) instance FromJSON InstallationUser instance ToJSON InstallationUser