{-# LANGUAGE OverloadedStrings #-} module GitHub.Types.Events where import Control.Applicative import Control.Monad import Data.Aeson import Data.Aeson.Types import Data.Monoid import Data.Text hiding (find) import Data.Time import Data.List import GitHub.Types.Base import GitHub.Types.Repository -- | All events which can be produced by GitHub. -- -- See https://developer.github.com/v3/activity/events/ data Event = Event { eventId :: !Text , eventActor :: !Actor , eventRepo :: !Repo , eventCreatedAt :: !UTCTime , eventPublic :: !Bool , eventPayload :: !Payload } deriving (Eq, Show) instance FromJSON Event where parseJSON (Object o) = do eventType <- o .: "type" Event <$> o .: "id" <*> o .: "actor" <*> o .: "repo" <*> o .: "created_at" <*> o .: "public" <*> (eventPayloadParser eventType =<< o .: "payload") parseJSON _ = fail "Event" data Actor = Actor { actorId :: !Integer , actorLogin :: !Text } deriving (Eq, Show) instance FromJSON Actor where parseJSON (Object o) = Actor <$> o .: "id" <*> o .: "login" parseJSON _ = fail "Actor" data Repo = Repo { repoId :: !Integer , repoName :: !Text } deriving (Eq, Show) instance FromJSON Repo where parseJSON (Object o) = Repo <$> o .: "id" <*> o .: "name" parseJSON _ = fail "Repo" data Payload = CommitCommentEventPayload CommitCommentEvent | DeploymentEventPayload DeploymentEvent | DeploymentStatusEventPayload DeploymentStatusEvent | PushEventPayload PushEvent | IssuesEventPayload IssuesEvent | IssueCommentEventPayload IssueCommentEvent | CreateEventPayload CreateEvent | PullRequestEventPayload PullRequestEvent | PullRequestReviewCommentEventPayload PullRequestReviewCommentEvent | WatchEventPayload WatchEvent | DeleteEventPayload DeleteEvent | ForkEventPayload ForkEvent | ReleaseEventPayload ReleaseEvent | GollumEventPayload GollumEvent | MemberEventPayload MemberEvent | PublicEventPayload Value deriving (Eq, Show) eventPayloadParsers :: [(Text, Text, Value -> Parser Payload)] eventPayloadParsers = [ ( "CommitCommentEvent", "commit_comment" , fmap CommitCommentEventPayload . parseJSON) , ( "DeploymentEvent", "deployment" , fmap DeploymentEventPayload . parseJSON) , ( "DeploymentStatusEvent", "deployment_status" , fmap DeploymentStatusEventPayload . parseJSON) , ( "PushEvent", "push" , fmap PushEventPayload . parseJSON) , ( "IssuesEvent", "issues" , fmap IssuesEventPayload . parseJSON) , ( "IssueCommentEvent", "issue_comment" , fmap IssueCommentEventPayload . parseJSON) , ( "CreateEvent", "create" , fmap CreateEventPayload . parseJSON) , ( "PullRequestEvent", "pull_request" , fmap PullRequestEventPayload . parseJSON) , ( "PullRequestReviewCommentEvent", "pull_request_review_comment" , fmap PullRequestReviewCommentEventPayload . parseJSON) , ( "WatchEvent", "watch" , fmap WatchEventPayload . parseJSON) , ( "DeleteEvent", "delete" , fmap DeleteEventPayload . parseJSON) , ( "ForkEvent", "fork" , fmap ForkEventPayload . parseJSON) , ( "ReleaseEvent", "release" , fmap ReleaseEventPayload . parseJSON) , ( "GollumEvent", "gollum" , fmap GollumEventPayload . parseJSON) , ( "MemberEvent", "member" , fmap MemberEventPayload . parseJSON) , ( "PublicEvent", "public" , fmap PublicEventPayload . parseJSON) ] eventPayloadParser :: Text -> Value -> Parser Payload eventPayloadParser eventType x = case find (\(t, _, _) -> t == eventType) eventPayloadParsers of Nothing -> fail $ "eventPayloadParser: Unknown event type: " <> unpack eventType Just (_, _, p) -> p x -- | Since the event type is included through different means (X-GitHub-Event -- header, or inline in the JSON object), it's not possible to make 'Event' -- an instance of 'FromJSON'. But if you know the type, you can use this -- parser. webhookPayloadParser :: Text -> Value -> Parser Payload webhookPayloadParser eventType x = case find (\(_, t, _) -> t == eventType) eventPayloadParsers of Nothing -> fail $ "webhookPayloadParser: Unknown event type: " <> unpack eventType Just (_, _, p) -> p x ------------------------------------------------------------------------------ -- CommitCommentEvent data CommitCommentEvent = CommitCommentEvent { commitCommentEventComment :: Value } deriving (Eq, Show) instance FromJSON CommitCommentEvent where parseJSON (Object x) = CommitCommentEvent <$> x .: "comment" parseJSON _ = fail "CommitCommentEvent" ------------------------------------------------------------------------------ -- DeploymentEvent data DeploymentEvent = DeploymentEvent { deploymentEventDeployment :: Deployment -- ^ The deployment. , deploymentEventRepository :: Repository -- ^ The repository for which the deployment was created (UNDOCUMENTED). } deriving (Eq, Show) instance FromJSON DeploymentEvent where parseJSON (Object x) = DeploymentEvent <$> x .: "deployment" <*> x .: "repository" parseJSON _ = fail "DeploymentEvent" ------------------------------------------------------------------------------ -- DeploymentStatusEvent data DeploymentStatusEvent = DeploymentStatusEvent { deploymentStatusEventDeploymentStatus :: DeploymentStatus -- ^ The deployment status. , deploymentStatusEventDeployment :: Deployment -- ^ The deployment which the status affects. , deploymentStatusEventRepository :: Repository -- ^ The repository for which the deployment was created (UNDOCUMENTED). } deriving (Eq, Show) instance FromJSON DeploymentStatusEvent where parseJSON (Object x) = DeploymentStatusEvent <$> x .: "deployment_status" <*> x .: "deployment" <*> x .: "repository" parseJSON _ = fail "DeploymentStatusEvent" ------------------------------------------------------------------------------ -- PushEvent data PushEvent = PushEvent { pushEventSize :: !Int } deriving (Eq, Show) instance FromJSON PushEvent where parseJSON (Object x) = PushEvent <$> x .: "size" parseJSON _ = fail "PushEvent" ------------------------------------------------------------------------------ -- IssuesEvent data IssuesEvent = IssuesEvent { issuesEventAction :: !Text } deriving (Eq, Show) instance FromJSON IssuesEvent where parseJSON (Object x) = IssuesEvent <$> x .: "action" parseJSON _ = fail "IssuesEvent" ------------------------------------------------------------------------------ -- IssuesEvent data IssueCommentEvent = IssueCommentEvent { issueCommentEventAction :: !Text } deriving (Eq, Show) instance FromJSON IssueCommentEvent where parseJSON (Object x) = IssueCommentEvent <$> x .: "action" parseJSON _ = fail "IssueCommentEvent" ------------------------------------------------------------------------------ -- IssuesEvent data CreateEvent = CreateEvent { createEventRef :: !(Maybe Text) } deriving (Eq, Show) instance FromJSON CreateEvent where parseJSON (Object x) = CreateEvent <$> x .: "ref" parseJSON _ = fail "CreateEvent" ------------------------------------------------------------------------------ -- PullRequestEvent data PullRequestEvent = PullRequestEvent { pullRequestEventAction :: !Text } deriving (Eq, Show) instance FromJSON PullRequestEvent where parseJSON (Object x) = PullRequestEvent <$> x .: "action" parseJSON _ = fail "PullRequestEvent" ------------------------------------------------------------------------------ -- PullRequestEvent data PullRequestReviewCommentEvent = PullRequestReviewCommentEvent { pullRequestReviewCommentEventPullRequest :: !Value } deriving (Eq, Show) instance FromJSON PullRequestReviewCommentEvent where parseJSON (Object x) = PullRequestReviewCommentEvent <$> x .: "pull_request" parseJSON _ = fail "PullRequestReviewCommentEvent" ------------------------------------------------------------------------------ -- WatchEvent data WatchEvent = WatchEvent { watchEventAction :: !Text } deriving (Eq, Show) instance FromJSON WatchEvent where parseJSON (Object x) = WatchEvent <$> x .: "action" parseJSON _ = fail "WatchEvent" ------------------------------------------------------------------------------ -- DeleteEvent data DeleteEvent = DeleteEvent { deleteEventRef :: !Text } deriving (Eq, Show) instance FromJSON DeleteEvent where parseJSON (Object x) = DeleteEvent <$> x .: "ref" parseJSON _ = fail "DeleteEvent" ------------------------------------------------------------------------------ -- ForkEvent data ForkEvent = ForkEvent { forkEventForkee :: !Value } deriving (Eq, Show) instance FromJSON ForkEvent where parseJSON (Object x) = ForkEvent <$> x .: "forkee" parseJSON _ = fail "ForkEvent" ------------------------------------------------------------------------------ -- ReleaseEvent data ReleaseEvent = ReleaseEvent { releaseEventAction :: !Text } deriving (Eq, Show) instance FromJSON ReleaseEvent where parseJSON (Object x) = ReleaseEvent <$> x .: "action" parseJSON _ = fail "ForkEvent" ------------------------------------------------------------------------------ -- GollumEvent data GollumEvent = GollumEvent { gollumEventPages :: !Value } deriving (Eq, Show) instance FromJSON GollumEvent where parseJSON (Object x) = GollumEvent <$> x .: "pages" parseJSON _ = fail "GollumEvent" ------------------------------------------------------------------------------ -- MemberEvent data MemberEvent = MemberEvent { memberEventAction :: !Text } deriving (Eq, Show) instance FromJSON MemberEvent where parseJSON (Object x) = MemberEvent <$> x .: "action" parseJSON _ = fail "MemberEvent"