packages feed

funbot-ext-events 0.2.0.0 → 0.3.0.0

raw patch · 4 files changed

+337/−164 lines, 4 filesdep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: text

API changes (from Hackage documentation)

- FunBot.ExtEvents: Branch :: String -> String -> String -> Branch
- FunBot.ExtEvents: [branchName] :: Branch -> String
- FunBot.ExtEvents: [branchRepoOwner] :: Branch -> String
- FunBot.ExtEvents: [branchRepo] :: Branch -> String
- FunBot.ExtEvents: [mrRepoOwner] :: MergeRequest -> String
- FunBot.ExtEvents: [mrRepo] :: MergeRequest -> String
- FunBot.ExtEvents: [tagRepoOwner] :: Tag -> String
- FunBot.ExtEvents: [tagRepo] :: Tag -> String
- FunBot.ExtEvents: data Branch
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.Branch
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.Commit
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.ExtEvent
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.MergeRequest
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.NewsItem
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.Paste
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.Push
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.FromJSON FunBot.ExtEvents.Tag
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.Branch
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.Commit
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.ExtEvent
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.MergeRequest
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.NewsItem
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.Paste
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.Push
- FunBot.ExtEvents: instance Data.Aeson.Types.Class.ToJSON FunBot.ExtEvents.Tag
- FunBot.ExtEvents: instance GHC.Show.Show FunBot.ExtEvents.Branch
+ FunBot.ExtEvents: Issue :: Text -> Int -> Text -> Text -> Text -> Issue
+ FunBot.ExtEvents: IssueEvent :: (ProjectObject Issue) -> ExtEvent
+ FunBot.ExtEvents: Note :: Text -> Text -> Text -> Text -> Note
+ FunBot.ExtEvents: NoteEvent :: (ProjectObject Note) -> ExtEvent
+ FunBot.ExtEvents: ProjectObject :: Repository -> a -> ProjectObject a
+ FunBot.ExtEvents: Repository :: Text -> Text -> Text -> Repository
+ FunBot.ExtEvents: [commitAdded] :: Commit -> [Text]
+ FunBot.ExtEvents: [commitModified] :: Commit -> [Text]
+ FunBot.ExtEvents: [commitRemoved] :: Commit -> [Text]
+ FunBot.ExtEvents: [issueAction] :: Issue -> Text
+ FunBot.ExtEvents: [issueAuthor] :: Issue -> Text
+ FunBot.ExtEvents: [issueId] :: Issue -> Int
+ FunBot.ExtEvents: [issueTitle] :: Issue -> Text
+ FunBot.ExtEvents: [issueUrl] :: Issue -> Text
+ FunBot.ExtEvents: [noteAuthor] :: Note -> Text
+ FunBot.ExtEvents: [noteContent] :: Note -> Text
+ FunBot.ExtEvents: [noteTarget] :: Note -> Text
+ FunBot.ExtEvents: [noteUrl] :: Note -> Text
+ FunBot.ExtEvents: [poObj] :: ProjectObject a -> a
+ FunBot.ExtEvents: [poRepo] :: ProjectObject a -> Repository
+ FunBot.ExtEvents: [repoHost] :: Repository -> Text
+ FunBot.ExtEvents: [repoName] :: Repository -> Text
+ FunBot.ExtEvents: [repoSpace] :: Repository -> Text
+ FunBot.ExtEvents: data Issue
+ FunBot.ExtEvents: data Note
+ FunBot.ExtEvents: data ProjectObject a
+ FunBot.ExtEvents: data Repository
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Commit
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.ExtEvent
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Issue
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.MergeRequest
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.NewsItem
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Note
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Paste
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Push
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Repository
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON FunBot.ExtEvents.Tag
+ FunBot.ExtEvents: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (FunBot.ExtEvents.ProjectObject a)
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Commit
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.ExtEvent
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Issue
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.MergeRequest
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.NewsItem
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Note
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Paste
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Push
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Repository
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON FunBot.ExtEvents.Tag
+ FunBot.ExtEvents: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (FunBot.ExtEvents.ProjectObject a)
+ FunBot.ExtEvents: instance GHC.Show.Show FunBot.ExtEvents.Issue
+ FunBot.ExtEvents: instance GHC.Show.Show FunBot.ExtEvents.Note
+ FunBot.ExtEvents: instance GHC.Show.Show FunBot.ExtEvents.Repository
+ FunBot.ExtEvents: instance GHC.Show.Show a => GHC.Show.Show (FunBot.ExtEvents.ProjectObject a)
- FunBot.ExtEvents: Commit :: String -> String -> String -> Commit
+ FunBot.ExtEvents: Commit :: Text -> Text -> Text -> [Text] -> [Text] -> [Text] -> Commit
- FunBot.ExtEvents: GitPushEvent :: Push -> ExtEvent
+ FunBot.ExtEvents: GitPushEvent :: (ProjectObject Push) -> ExtEvent
- FunBot.ExtEvents: GitTagEvent :: Tag -> ExtEvent
+ FunBot.ExtEvents: GitTagEvent :: (ProjectObject Tag) -> ExtEvent
- FunBot.ExtEvents: MergeRequest :: String -> Int -> String -> String -> String -> String -> String -> MergeRequest
+ FunBot.ExtEvents: MergeRequest :: Text -> Int -> Text -> Text -> Text -> MergeRequest
- FunBot.ExtEvents: MergeRequestEvent :: MergeRequest -> ExtEvent
+ FunBot.ExtEvents: MergeRequestEvent :: (ProjectObject MergeRequest) -> ExtEvent
- FunBot.ExtEvents: NewsItem :: String -> Maybe String -> String -> Maybe String -> Maybe String -> NewsItem
+ FunBot.ExtEvents: NewsItem :: Text -> Maybe Text -> Text -> Maybe Text -> Maybe Text -> NewsItem
- FunBot.ExtEvents: Paste :: String -> String -> String -> String -> String -> Paste
+ FunBot.ExtEvents: Paste :: Text -> Text -> Text -> Text -> Text -> Paste
- FunBot.ExtEvents: Push :: Branch -> [Commit] -> Push
+ FunBot.ExtEvents: Push :: Text -> [Commit] -> Push
- FunBot.ExtEvents: Tag :: String -> String -> String -> String -> Tag
+ FunBot.ExtEvents: Tag :: Text -> Text -> Tag
- FunBot.ExtEvents: WelcomeEvent :: String -> String -> ExtEvent
+ FunBot.ExtEvents: WelcomeEvent :: Text -> Text -> ExtEvent
- FunBot.ExtEvents: [commitAuthor] :: Commit -> String
+ FunBot.ExtEvents: [commitAuthor] :: Commit -> Text
- FunBot.ExtEvents: [commitTitle] :: Commit -> String
+ FunBot.ExtEvents: [commitTitle] :: Commit -> Text
- FunBot.ExtEvents: [commitUrl] :: Commit -> String
+ FunBot.ExtEvents: [commitUrl] :: Commit -> Text
- FunBot.ExtEvents: [itemAuthor] :: NewsItem -> Maybe String
+ FunBot.ExtEvents: [itemAuthor] :: NewsItem -> Maybe Text
- FunBot.ExtEvents: [itemFeedLabel] :: NewsItem -> String
+ FunBot.ExtEvents: [itemFeedLabel] :: NewsItem -> Text
- FunBot.ExtEvents: [itemFeedTitle] :: NewsItem -> Maybe String
+ FunBot.ExtEvents: [itemFeedTitle] :: NewsItem -> Maybe Text
- FunBot.ExtEvents: [itemTitle] :: NewsItem -> String
+ FunBot.ExtEvents: [itemTitle] :: NewsItem -> Text
- FunBot.ExtEvents: [itemUrl] :: NewsItem -> Maybe String
+ FunBot.ExtEvents: [itemUrl] :: NewsItem -> Maybe Text
- FunBot.ExtEvents: [mrAction] :: MergeRequest -> String
+ FunBot.ExtEvents: [mrAction] :: MergeRequest -> Text
- FunBot.ExtEvents: [mrAuthor] :: MergeRequest -> String
+ FunBot.ExtEvents: [mrAuthor] :: MergeRequest -> Text
- FunBot.ExtEvents: [mrTitle] :: MergeRequest -> String
+ FunBot.ExtEvents: [mrTitle] :: MergeRequest -> Text
- FunBot.ExtEvents: [mrUrl] :: MergeRequest -> String
+ FunBot.ExtEvents: [mrUrl] :: MergeRequest -> Text
- FunBot.ExtEvents: [pasteAuthor] :: Paste -> String
+ FunBot.ExtEvents: [pasteAuthor] :: Paste -> Text
- FunBot.ExtEvents: [pasteChannel] :: Paste -> String
+ FunBot.ExtEvents: [pasteChannel] :: Paste -> Text
- FunBot.ExtEvents: [pasteTitle] :: Paste -> String
+ FunBot.ExtEvents: [pasteTitle] :: Paste -> Text
- FunBot.ExtEvents: [pasteUrl] :: Paste -> String
+ FunBot.ExtEvents: [pasteUrl] :: Paste -> Text
- FunBot.ExtEvents: [pasteVerb] :: Paste -> String
+ FunBot.ExtEvents: [pasteVerb] :: Paste -> Text
- FunBot.ExtEvents: [pushBranch] :: Push -> Branch
+ FunBot.ExtEvents: [pushBranch] :: Push -> Text
- FunBot.ExtEvents: [tagAuthor] :: Tag -> String
+ FunBot.ExtEvents: [tagAuthor] :: Tag -> Text
- FunBot.ExtEvents: [tagRef] :: Tag -> String
+ FunBot.ExtEvents: [tagRef] :: Tag -> Text

Files

− NEWS
@@ -1,44 +0,0 @@-This file lists the user-visible interesting changes between releases. For a-full list of changes to the source, see the ChangeLog.----funbot-ext-events 0.2.0.0 -- 2015-12-17-=======================================--General, build and documentation changes:--* (None)--New APIs, features and enhancements:--* Add welcome event--Bug fixes:--* (None)--Dependency changes:--* (None)----funbot-ext-events 0.1.0.0 -- 2015-09-19-=======================================--General, build and documentation changes:--* (This is the first release, so everything is new)--New APIs, features and enhancements:--* (This is the first release, so everything is a new feature)--Bug fixes:--* (This is just the first release, many bugs haven't been discovered yet)--Dependency changes:--* (This is the first release)
+ NEWS.md view
@@ -0,0 +1,71 @@+This file lists the user-visible interesting changes between releases. For a+full list of changes to the source, see the ChangeLog.++++funbot-ext-events 0.3.0.0 -- 2016-01-27+=======================================++General, build and documentation changes:++* Write doc comments for all the types and their fields++New APIs, features and enhancements:++* Add file lists to Commit+* Add an issue event type+* Add a note event type+* Move the entire API from `String` to strict `Text`+* Repo identification based on host, namespace and name++Bug fixes:++* (None)++Dependency changes:++* (None)++++++funbot-ext-events 0.2.0.0 -- 2015-12-17+=======================================++General, build and documentation changes:++* (None)++New APIs, features and enhancements:++* Add welcome event++Bug fixes:++* (None)++Dependency changes:++* (None)++++funbot-ext-events 0.1.0.0 -- 2015-09-19+=======================================++General, build and documentation changes:++* (This is the first release, so everything is new)++New APIs, features and enhancements:++* (This is the first release, so everything is a new feature)++Bug fixes:++* (This is just the first release, many bugs haven't been discovered yet)++Dependency changes:++* (This is the first release)
funbot-ext-events.cabal view
@@ -1,5 +1,5 @@ name:                funbot-ext-events-version:             0.2.0.0+version:             0.3.0.0 synopsis:            Interact with FunBot's external events. description:   This is a library providing types and tools for interacting with@@ -10,10 +10,10 @@   Since the provided types change every time an external event type is added or   modified, many of this library's releases are expected to break   compatibility.  In most cases you should either use a higher-level library-  such as <https://notabug.org/fr33domlover/funbot-client.git funbot-client>,-  or perhaps create one yourself.-homepage:            https://notabug.org/fr33domlover/funbot-ext-events/-bug-reports:         https://notabug.org/fr33domlover/funbot-ext-events/issues/+  such as <https://notabug.org/fr33domlover/funbot-client funbot-client>, or+  perhaps create one yourself.+homepage:            https://notabug.org/fr33domlover/funbot-ext-events+bug-reports:         https://notabug.org/fr33domlover/funbot-ext-events/issues license:             PublicDomain license-file:        COPYING author:              fr33domlover@@ -21,7 +21,7 @@ copyright:           ♡ Copying is an act of love. Please copy, reuse and share. category:            Network, Web build-type:          Simple-extra-source-files:  AUTHORS ChangeLog COPYING INSTALL NEWS README.md+extra-source-files:  AUTHORS ChangeLog COPYING INSTALL NEWS.md README.md cabal-version:       >=1.10  source-repository head@@ -34,7 +34,7 @@   -- other-extensions:       build-depends:       aeson >=0.7                      , base  >=4.7 && <5-                     , text+                     , text  >=1   hs-source-dirs:      src   default-language:    Haskell2010   ghc-options:         -Wall
src/FunBot/ExtEvents.hs view
@@ -17,10 +17,13 @@ {-# LANGUAGE OverloadedStrings #-}  module FunBot.ExtEvents-    ( Branch (..)+    ( Repository (..)+    , ProjectObject (..)     , Commit (..)     , Push (..)     , Tag (..)+    , Issue (..)+    , Note (..)     , MergeRequest (..)     , NewsItem (..)     , Paste (..)@@ -29,121 +32,117 @@ where  import Control.Applicative-import Control.Monad (mzero) import Data.Aeson-import Data.Aeson.Types (Parser)--import qualified Data.Text as T--data Branch = Branch-    { branchName      :: String-    , branchRepo      :: String-    , branchRepoOwner :: String-    }-    deriving Show--data Commit = Commit-    { commitAuthor :: String-    , commitTitle  :: String-    , commitUrl    :: String-    }-    deriving Show--data Push = Push-    { pushBranch  :: Branch-    , pushCommits :: [Commit]-    }-    deriving Show+import Data.Aeson.Types (Parser, typeMismatch)+import Data.Text (Text) -data Tag = Tag-    { tagAuthor    :: String-    , tagRef       :: String-    , tagRepo      :: String-    , tagRepoOwner :: String+-- | A version control repository.+data Repository = Repository+    { -- | The repository's name. For example, @funbot-ext-events@.+      repoName  :: Text+      -- | The repository's namespace, i.e. username or team name under which+      -- the repository is being managed. For example, @fr33domlover@.+    , repoSpace :: Text+      -- | Network location where the repository is hosted. For now this should+      -- in most cases be the website URL's host part, but could be something+      -- else if/when we have distributed repository sharing. For example,+      -- @notabug.org@.+    , repoHost  :: Text     }     deriving Show -data MergeRequest = MergeRequest-    { mrAuthor    :: String-    , mrId        :: Int-    , mrRepo      :: String-    , mrRepoOwner :: String-    , mrTitle     :: String-    , mrUrl       :: String-    , mrAction    :: String-    }-    deriving Show+instance FromJSON Repository where+    parseJSON (Object o) =+        Repository <$>+        o .: "name" <*>+        o .: "space" <*>+        o .: "host"+    parseJSON v          = typeMismatch "Repository" v -data NewsItem = NewsItem-    { itemFeedLabel :: String-    , itemFeedTitle :: Maybe String-    , itemTitle     :: String-    , itemAuthor    :: Maybe String-    , itemUrl       :: Maybe String-    }-    deriving Show+instance ToJSON Repository where+    toJSON repo = object+        [ "name"  .= repoName  repo+        , "space" .= repoSpace repo+        , "host"  .= repoHost  repo+        ] -data Paste = Paste-    { pasteAuthor  :: String-    , pasteVerb    :: String-    , pasteTitle   :: String-    , pasteUrl     :: String-    , pasteChannel :: String+-- | An object that is part of a project, such as a merge request or an issue+-- or a series of commits being pushed.+data ProjectObject a = ProjectObject+    { -- | The project repository.+      poRepo :: Repository+      -- | The object itself.+    , poObj  :: a     }     deriving Show --- | An event coming from one of the external event sources.-data ExtEvent-    -- | Git commits pushed into a repo.-    = GitPushEvent Push-    -- | A git tag pushed into a repo.-    | GitTagEvent Tag-    -- | A merge request related event.-    | MergeRequestEvent MergeRequest-    -- | New news item published.-    | NewsEvent NewsItem-    -- | Paste related event in a paste server.-    | PasteEvent Paste-    -- | A new IRC user needs to be welcomed to a channel.-    | WelcomeEvent String String-    deriving Show--instance FromJSON Branch where+instance FromJSON a => FromJSON (ProjectObject a) where     parseJSON (Object o) =-        Branch <$>-        o .: "name" <*>+        ProjectObject <$>         o .: "repo" <*>-        o .: "user"-    parseJSON _          = mzero+        o .: "obj"+    parseJSON v          = typeMismatch "ProjectObject" v -instance ToJSON Branch where-    toJSON (Branch name repo owner) = object-        [ "name" .= name-        , "repo" .= repo-        , "user" .= owner+instance ToJSON a => ToJSON (ProjectObject a) where+    toJSON po = object+        [ "repo" .= poRepo po+        , "obj"  .= poObj  po         ] +-- | A version control system commit, i.e. a set of changes with a description.+data Commit = Commit+    { -- | The author name. For example, @John Doe@.+      commitAuthor   :: Text+      -- | The commit title. For example, @Support encrypted messages@.+    , commitTitle    :: Text+      -- | A web view URL at which the commit details can be displayed.+    , commitUrl      :: Text+      -- | A list of files (relative to the repository top level) added to the+      -- repository in this commit. For example, @src\/FunBot\/ExtEvents.hs@.+    , commitAdded    :: [Text]+      -- | A list of files modified in the repository in this commit.+    , commitModified :: [Text]+      -- | A list of files removed from the repository in this commit.+    , commitRemoved  :: [Text]+    }+    deriving Show+ instance FromJSON Commit where     parseJSON (Object o) =         Commit <$>         o .: "author" <*>         o .: "title" <*>-        o .: "url"-    parseJSON _          = mzero+        o .: "url" <*>+        o .: "added" <*>+        o .: "modified" <*>+        o .: "removed"+    parseJSON v          = typeMismatch "Commit" v  instance ToJSON Commit where-    toJSON (Commit author title url) = object-        [ "author" .= author-        , "title"  .= title-        , "url"    .= url+    toJSON (Commit author title url added modified removed) = object+        [ "author"   .= author+        , "title"    .= title+        , "url"      .= url+        , "added"    .= added+        , "modified" .= modified+        , "removed"  .= removed         ] +-- | A version control push operation, i.e. one or more commits being added to+-- a specific branch or a repsitory. Note that tags can be pushed too, but for+-- that see the 'Tag' type.+data Push = Push+    { pushBranch  :: Text+    , pushCommits :: [Commit]+    }+    deriving Show+ instance FromJSON Push where     parseJSON (Object o) =         Push <$>         o .: "branch" <*>         o .: "commits"-    parseJSON _          = mzero+    parseJSON v          = typeMismatch "Push" v  instance ToJSON Push where     toJSON (Push branch commits) = object@@ -151,46 +150,149 @@         , "commits" .= commits         ] +-- | A version control tag. Allows a specific state of the repository to be+-- referred by name.+data Tag = Tag+    { -- | Tag author name, for example @John Doe@.+      tagAuthor :: Text+      -- | Tag label, for example @0.3.4.1@ (referring to a release version).+    , tagRef    :: Text+    }+    deriving Show+ instance FromJSON Tag where     parseJSON (Object o) =         Tag <$>         o .: "author" <*>-        o .: "ref" <*>-        o .: "repo" <*>-        o .: "user"-    parseJSON _          = mzero+        o .: "ref"+    parseJSON v          = typeMismatch "Tag" v  instance ToJSON Tag where     toJSON tag = object         [ "author" .= tagAuthor tag         , "ref"    .= tagRef tag-        , "repo"   .= tagRepo tag-        , "user"   .= tagRepoOwner tag         ] +-- | A bug, request or other work item attached to a project.+data Issue = Issue+    { -- | Issue author name. For example, @John Doe@.+      issueAuthor    :: Text+      -- | The issue's unique identifier.+    , issueId        :: Int+      -- | Issue title text.+    , issueTitle     :: Text+      -- | A web view URL at which the issue's details can be viewed and+      -- perhaps modified.+    , issueUrl       :: Text+      -- | An action being applied to the issue, which is causing the event to+      -- be sent to the FunBot instance.+    , issueAction    :: Text+    }+    deriving Show++instance FromJSON Issue where+    parseJSON (Object o) =+        Issue <$>+        o .: "author" <*>+        o .: "id" <*>+        o .: "title" <*>+        o .: "url" <*>+        o .: "action"+    parseJSON v          = typeMismatch "Issue" v++instance ToJSON Issue where+    toJSON issue = object+        [ "author" .= issueAuthor issue+        , "id"     .= issueId issue+        , "title"  .= issueTitle issue+        , "url"    .= issueUrl issue+        , "action" .= issueAction issue+        ]++-- | A comment made on some project object.+data Note = Note+    { -- | Note author name, e.g. @John Doe@.+      noteAuthor    :: Text+      -- | Note content for the bot to display. Since notes can be long, this+      -- should be only the portion for the bot to display. The bot should+      -- examine this field and shorten long notes, but you shouldn't rely on+      -- it and provide the right short part here.+    , noteContent   :: Text+      -- | The project object being commented on, e.g. @issue #419@.+    , noteTarget    :: Text+      -- | A web view URL at which the note can be viewed.+    , noteUrl       :: Text+    }+    deriving Show++instance FromJSON Note where+    parseJSON (Object o) =+        Note <$>+        o .: "author" <*>+        o .: "content" <*>+        o .: "target" <*>+        o .: "url"+    parseJSON v          = typeMismatch "Note" v++instance ToJSON Note where+    toJSON (Note author content target url) = object+        [ "author"  .= author+        , "content" .= content+        , "target"  .= target+        , "url"     .= url+        ]++-- | A request from a user to merge their code changes into the project.+data MergeRequest = MergeRequest+    { -- | Merge request author name, e.g. @John Doe@.+      mrAuthor    :: Text+      -- | Merge request unique identifier.+    , mrId        :: Int+      -- | Merge request title.+    , mrTitle     :: Text+      -- | A web view URL at which the merge request can be viewed and perhaps+      -- edited.+    , mrUrl       :: Text+      -- | An action being applied to the merge request, which is causing the+      -- event to be sent to the FunBot instance.+    , mrAction    :: Text+    }+    deriving Show+ instance FromJSON MergeRequest where     parseJSON (Object o) =         MergeRequest <$>         o .: "author" <*>         o .: "id" <*>-        o .: "repo" <*>-        o .: "user" <*>         o .: "title" <*>         o .: "url" <*>         o .: "action"-    parseJSON _          = mzero+    parseJSON v          = typeMismatch "MergeRequest" v  instance ToJSON MergeRequest where     toJSON mr = object         [ "author" .= mrAuthor mr         , "id"     .= mrId mr-        , "repo"   .= mrRepo mr-        , "user"   .= mrRepoOwner mr         , "title"  .= mrTitle mr         , "url"    .= mrUrl mr         , "action" .= mrAction mr         ] +-- | A news feed item.+data NewsItem = NewsItem+    { -- | Short label identifying the new feed to which the item belongs.+      itemFeedLabel :: Text+      -- | The name of the feed to which the item belongs.+    , itemFeedTitle :: Maybe Text+      -- | Item title.+    , itemTitle     :: Text+      -- | Item author name.+    , itemAuthor    :: Maybe Text+      -- | URL at which the item's content can be viewed.+    , itemUrl       :: Maybe Text+    }+    deriving Show+ instance FromJSON NewsItem where     parseJSON (Object o) =         NewsItem <$>@@ -199,7 +301,7 @@         o .: "title" <*>         o .: "author" <*>         o .: "url"-    parseJSON _          = mzero+    parseJSON v          = typeMismatch "NewsItem" v  instance ToJSON NewsItem where     toJSON (NewsItem fLabel fTitle title author url) = object@@ -210,6 +312,21 @@         , "url"        .= url         ] +-- | A piece of text uploaded to a website for quick sharing.+data Paste = Paste+    { -- | Paste author name or IRC nickname.+      pasteAuthor  :: Text+      -- | Verb indicating the action done with the paste.+    , pasteVerb    :: Text+      -- | Paste title.+    , pasteTitle   :: Text+      -- | URL at which the paste content can be viewed.+    , pasteUrl     :: Text+      -- | An IRC channel into which to announce the paste.+    , pasteChannel :: Text+    }+    deriving Show+ instance FromJSON Paste where     parseJSON (Object o) =         Paste <$>@@ -218,7 +335,7 @@         o .: "title" <*>         o .: "url" <*>         o .: "channel"-    parseJSON _          = mzero+    parseJSON v          = typeMismatch "Paste" v  instance ToJSON Paste where     toJSON (Paste author verb title url chan) = object@@ -229,37 +346,66 @@         , "channel" .= chan         ] -text :: Parser T.Text -> T.Text -> Parser T.Text+-- | An event coming from one of the external event sources.+data ExtEvent+    -- | Git commits pushed into a repo.+    = GitPushEvent (ProjectObject Push)+    -- | A git tag pushed into a repo.+    | GitTagEvent (ProjectObject Tag)+    -- | An issue related event.+    | IssueEvent (ProjectObject Issue)+    -- | A merge request related event.+    | MergeRequestEvent (ProjectObject MergeRequest)+    -- | A comment made on an issue or MR or some other object.+    | NoteEvent (ProjectObject Note)+    -- | New news item published.+    | NewsEvent NewsItem+    -- | Paste related event in a paste server.+    | PasteEvent Paste+    -- | A new IRC user needs to be welcomed to a channel.+    | WelcomeEvent Text Text+    deriving Show++text :: Parser Text -> Text -> Parser Text text parser expected = do     got <- parser     if got == expected         then return got-        else mzero+        else empty  instance FromJSON ExtEvent where     parseJSON (Object o) =         let kind = text $ o .: "type"-        in  kind "push"  *> (GitPushEvent      <$> o .: "data") <|>-            kind "tag"   *> (GitTagEvent       <$> o .: "data") <|>-            kind "mr"    *> (MergeRequestEvent <$> o .: "data") <|>-            kind "news"  *> (NewsEvent         <$> o .: "data") <|>-            kind "paste" *> (PasteEvent        <$> o .: "data")-    parseJSON _          = mzero+            event label ctor = kind label *> (ctor <$> o .: "data")+        in  event "push"  GitPushEvent      <|>+            event "tag"   GitTagEvent       <|>+            event "mr"    MergeRequestEvent <|>+            event "note"  NoteEvent         <|>+            event "issue" IssueEvent        <|>+            event "news"  NewsEvent         <|>+            event "paste" PasteEvent+    parseJSON v          = typeMismatch "ExtEvent" v  instance ToJSON ExtEvent where-    toJSON (GitPushEvent commits) = object [ "type" .= ("push" :: T.Text)+    toJSON (GitPushEvent commits) = object [ "type" .= ("push" :: Text)                                            , "data" .= commits                                            ]-    toJSON (GitTagEvent tag)      = object [ "type" .= ("tag" :: T.Text)+    toJSON (GitTagEvent tag)      = object [ "type" .= ("tag" :: Text)                                            , "data" .= tag                                            ]-    toJSON (MergeRequestEvent mr) = object [ "type" .= ("mr" :: T.Text)+    toJSON (IssueEvent issue)     = object [ "type" .= ("issue" :: Text)+                                           , "data" .= issue+                                           ]+    toJSON (MergeRequestEvent mr) = object [ "type" .= ("mr" :: Text)                                            , "data" .= mr                                            ]-    toJSON (NewsEvent item)       = object [ "type" .= ("news" :: T.Text)+    toJSON (NoteEvent note)       = object [ "type" .= ("note" :: Text)+                                           , "data" .= note+                                           ]+    toJSON (NewsEvent item)       = object [ "type" .= ("news" :: Text)                                            , "data" .= item                                            ]-    toJSON (PasteEvent paste)     = object [ "type" .= ("paste" :: T.Text)+    toJSON (PasteEvent paste)     = object [ "type" .= ("paste" :: Text)                                            , "data" .= paste                                            ]     toJSON (WelcomeEvent _ _)     = object []