Skip to content

Commit 6d7b176

Browse files
colonelpanic8phadej
authored andcommitted
Add notifications endpoint
Fixes #323
1 parent 7f4c802 commit 6d7b176

4 files changed

Lines changed: 125 additions & 2 deletions

File tree

github.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ library
101101
GitHub.Data.Webhooks.Validate
102102
GitHub.Endpoints.Activity.Events
103103
GitHub.Endpoints.Activity.Starring
104+
GitHub.Endpoints.Activity.Notifications
104105
GitHub.Endpoints.Activity.Watching
105106
GitHub.Endpoints.Gists
106107
GitHub.Endpoints.Gists.Comments

src/GitHub/Data/Activities.hs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
--
66
module GitHub.Data.Activities where
77

8-
import GitHub.Data.Repos (Repo)
8+
import GitHub.Data.Id (Id, mkId)
9+
import GitHub.Data.Repos (Repo, RepoRef)
10+
import GitHub.Data.URL (URL)
911
import GitHub.Internal.Prelude
12+
1013
import Prelude ()
1114

1215
data RepoStarred = RepoStarred
@@ -24,3 +27,82 @@ instance FromJSON RepoStarred where
2427
<$> o .: "starred_at"
2528
<*> o .: "repo"
2629

30+
data Subject = Subject
31+
{ subjectTitle :: !Text
32+
, subjectURL :: !URL
33+
, subjectLatestCommentURL :: !(Maybe URL)
34+
-- https://developer.github.com/v3/activity/notifications/ doesn't indicate
35+
-- what the possible values for this field are.
36+
-- TODO: Make an ADT for this.
37+
, subjectType :: !Text
38+
}
39+
deriving (Show, Data, Typeable, Eq, Ord, Generic)
40+
41+
instance NFData Subject where rnf = genericRnf
42+
instance Binary Subject
43+
44+
instance FromJSON Subject where
45+
parseJSON = withObject "Subject" $ \o -> Subject
46+
<$> o .: "title"
47+
<*> o .: "url"
48+
<*> o .:? "latest_comment_url"
49+
<*> o .: "type"
50+
51+
data NotificationReason
52+
= AssignReason
53+
| AuthorReason
54+
| CommentReason
55+
| InvitationReason
56+
| ManualReason
57+
| MentionReason
58+
| ReviewRequestedReason
59+
| StateChangeReason
60+
| SubscribedReason
61+
| TeamMentionReason
62+
deriving (Show, Data, Enum, Bounded, Typeable, Eq, Ord, Generic)
63+
64+
instance NFData NotificationReason where rnf = genericRnf
65+
instance Binary NotificationReason
66+
67+
instance FromJSON NotificationReason where
68+
parseJSON = withText "NotificationReason" $ \t -> case t of
69+
"assign" -> pure AssignReason
70+
"author" -> pure AuthorReason
71+
"comment" -> pure CommentReason
72+
"invitation" -> pure InvitationReason
73+
"manual" -> pure ManualReason
74+
"mention" -> pure MentionReason
75+
"review_requested" -> pure ReviewRequestedReason
76+
"state_change" -> pure StateChangeReason
77+
"subscribed" -> pure SubscribedReason
78+
"team_mention" -> pure TeamMentionReason
79+
_ -> fail $ "Unknown NotificationReason " ++ show t
80+
81+
data Notification = Notification
82+
-- XXX: The notification id field type IS in fact string. Not sure why gh
83+
-- chose to do this when all the other ids are Numbers...
84+
{ notificationId :: !(Id Notification)
85+
, notificationRepo :: !RepoRef
86+
, notificationSubject :: !Subject
87+
, notificationReason :: !NotificationReason
88+
, notificationUnread :: !Bool
89+
, notificationUpdatedAt :: !(Maybe UTCTime)
90+
, notificationLastReadAt :: !(Maybe UTCTime)
91+
, notificationUrl :: !URL
92+
}
93+
deriving (Show, Data, Typeable, Eq, Ord, Generic)
94+
95+
instance NFData Notification where rnf = genericRnf
96+
instance Binary Notification
97+
98+
instance FromJSON Notification where
99+
parseJSON = withObject "Notification" $ \o -> Notification
100+
<$> (mkId undefined . read <$> o .: "id")
101+
<*> o .: "repository"
102+
<*> o .: "subject"
103+
<*> o .: "reason"
104+
<*> o .: "unread"
105+
<*> o .: "updated_at"
106+
<*> o .: "last_read_at"
107+
<*> o .: "url"
108+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
-----------------------------------------------------------------------------
2+
-- |
3+
-- License : BSD-3-Clause
4+
-- Maintainer : Oleg Grenrus <oleg.grenrus@iki.fi>
5+
--
6+
-- The repo watching API as described on
7+
-- <https://developer.github.com/v3/activity/notifications/>.
8+
9+
module GitHub.Endpoints.Activity.Notifications where
10+
11+
import GitHub.Data
12+
import GitHub.Internal.Prelude
13+
import GitHub.Request
14+
import Prelude ()
15+
16+
getNotifications :: Auth -> IO (Either Error (Vector Notification))
17+
getNotifications auth =
18+
executeRequest auth $ getNotificationsR FetchAll
19+
20+
getNotificationsR :: FetchCount -> Request 'RA (Vector Notification)
21+
getNotificationsR =
22+
pagedQuery ["notifications"] []
23+
24+
markNotificationAsRead :: Auth -> Id Notification -> IO (Either Error ())
25+
markNotificationAsRead auth notificationId =
26+
executeRequest auth $ markNotificationAsReadR notificationId
27+
28+
markNotificationAsReadR :: Id Notification -> Request 'RW ()
29+
markNotificationAsReadR notificationId = SimpleQuery $
30+
Command Patch ["notifications", "threads", toPathPart notificationId]
31+
(encode ())
32+
33+
markNotificationsAsRead :: Auth -> IO (Either Error ())
34+
markNotificationsAsRead auth =
35+
executeRequest auth markAllNotificationsAsReadR
36+
37+
markAllNotificationsAsReadR :: Request 'RW ()
38+
markAllNotificationsAsReadR = SimpleQuery $
39+
Command Put ["notifications"] $ encode emptyObject

src/GitHub/Internal/Prelude.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module GitHub.Internal.Prelude (
2222
Semigroup(..),
2323
-- * Aeson
2424
FromJSON(..), ToJSON(..), Value(..), Object,
25+
emptyObject,
2526
encode,
2627
withText, withObject, (.:), (.:?), (.!=), (.=), object, typeMismatch,
2728
-- * Control.Applicative
@@ -40,7 +41,7 @@ import Control.DeepSeq.Generics (genericRnf)
4041
import Data.Aeson
4142
(FromJSON (..), Object, ToJSON (..), Value (..), encode, object,
4243
withObject, withText, (.!=), (.:), (.:?), (.=))
43-
import Data.Aeson.Types (typeMismatch)
44+
import Data.Aeson.Types (emptyObject, typeMismatch)
4445
import Data.Binary (Binary)
4546
import Data.Binary.Instances ()
4647
import Data.Data (Data, Typeable)

0 commit comments

Comments
 (0)