1// Copyright 2013 The go-github AUTHORS. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6package github
7
8import (
9	"context"
10	"encoding/json"
11	"fmt"
12	"time"
13)
14
15// Event represents a GitHub event.
16type Event struct {
17	Type       *string          `json:"type,omitempty"`
18	Public     *bool            `json:"public,omitempty"`
19	RawPayload *json.RawMessage `json:"payload,omitempty"`
20	Repo       *Repository      `json:"repo,omitempty"`
21	Actor      *User            `json:"actor,omitempty"`
22	Org        *Organization    `json:"org,omitempty"`
23	CreatedAt  *time.Time       `json:"created_at,omitempty"`
24	ID         *string          `json:"id,omitempty"`
25}
26
27func (e Event) String() string {
28	return Stringify(e)
29}
30
31// ParsePayload parses the event payload. For recognized event types,
32// a value of the corresponding struct type will be returned.
33func (e *Event) ParsePayload() (payload interface{}, err error) {
34	switch *e.Type {
35	case "CheckRunEvent":
36		payload = &CheckRunEvent{}
37	case "CheckSuiteEvent":
38		payload = &CheckSuiteEvent{}
39	case "CommitCommentEvent":
40		payload = &CommitCommentEvent{}
41	case "CreateEvent":
42		payload = &CreateEvent{}
43	case "DeleteEvent":
44		payload = &DeleteEvent{}
45	case "DeploymentEvent":
46		payload = &DeploymentEvent{}
47	case "DeploymentStatusEvent":
48		payload = &DeploymentStatusEvent{}
49	case "ForkEvent":
50		payload = &ForkEvent{}
51	case "GollumEvent":
52		payload = &GollumEvent{}
53	case "InstallationEvent":
54		payload = &InstallationEvent{}
55	case "InstallationRepositoriesEvent":
56		payload = &InstallationRepositoriesEvent{}
57	case "IssueCommentEvent":
58		payload = &IssueCommentEvent{}
59	case "IssuesEvent":
60		payload = &IssuesEvent{}
61	case "LabelEvent":
62		payload = &LabelEvent{}
63	case "MarketplacePurchaseEvent":
64		payload = &MarketplacePurchaseEvent{}
65	case "MemberEvent":
66		payload = &MemberEvent{}
67	case "MembershipEvent":
68		payload = &MembershipEvent{}
69	case "MilestoneEvent":
70		payload = &MilestoneEvent{}
71	case "OrganizationEvent":
72		payload = &OrganizationEvent{}
73	case "OrgBlockEvent":
74		payload = &OrgBlockEvent{}
75	case "PageBuildEvent":
76		payload = &PageBuildEvent{}
77	case "PingEvent":
78		payload = &PingEvent{}
79	case "ProjectEvent":
80		payload = &ProjectEvent{}
81	case "ProjectCardEvent":
82		payload = &ProjectCardEvent{}
83	case "ProjectColumnEvent":
84		payload = &ProjectColumnEvent{}
85	case "PublicEvent":
86		payload = &PublicEvent{}
87	case "PullRequestEvent":
88		payload = &PullRequestEvent{}
89	case "PullRequestReviewEvent":
90		payload = &PullRequestReviewEvent{}
91	case "PullRequestReviewCommentEvent":
92		payload = &PullRequestReviewCommentEvent{}
93	case "PushEvent":
94		payload = &PushEvent{}
95	case "ReleaseEvent":
96		payload = &ReleaseEvent{}
97	case "RepositoryEvent":
98		payload = &RepositoryEvent{}
99	case "StatusEvent":
100		payload = &StatusEvent{}
101	case "TeamEvent":
102		payload = &TeamEvent{}
103	case "TeamAddEvent":
104		payload = &TeamAddEvent{}
105	case "WatchEvent":
106		payload = &WatchEvent{}
107	}
108	err = json.Unmarshal(*e.RawPayload, &payload)
109	return payload, err
110}
111
112// Payload returns the parsed event payload. For recognized event types,
113// a value of the corresponding struct type will be returned.
114//
115// Deprecated: Use ParsePayload instead, which returns an error
116// rather than panics if JSON unmarshaling raw payload fails.
117func (e *Event) Payload() (payload interface{}) {
118	var err error
119	payload, err = e.ParsePayload()
120	if err != nil {
121		panic(err)
122	}
123	return payload
124}
125
126// ListEvents drinks from the firehose of all public events across GitHub.
127//
128// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events
129func (s *ActivityService) ListEvents(ctx context.Context, opt *ListOptions) ([]*Event, *Response, error) {
130	u, err := addOptions("events", opt)
131	if err != nil {
132		return nil, nil, err
133	}
134
135	req, err := s.client.NewRequest("GET", u, nil)
136	if err != nil {
137		return nil, nil, err
138	}
139
140	var events []*Event
141	resp, err := s.client.Do(ctx, req, &events)
142	if err != nil {
143		return nil, resp, err
144	}
145
146	return events, resp, nil
147}
148
149// ListRepositoryEvents lists events for a repository.
150//
151// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events
152func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) {
153	u := fmt.Sprintf("repos/%v/%v/events", owner, repo)
154	u, err := addOptions(u, opt)
155	if err != nil {
156		return nil, nil, err
157	}
158
159	req, err := s.client.NewRequest("GET", u, nil)
160	if err != nil {
161		return nil, nil, err
162	}
163
164	var events []*Event
165	resp, err := s.client.Do(ctx, req, &events)
166	if err != nil {
167		return nil, resp, err
168	}
169
170	return events, resp, nil
171}
172
173// ListIssueEventsForRepository lists issue events for a repository.
174//
175// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository
176func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opt *ListOptions) ([]*IssueEvent, *Response, error) {
177	u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
178	u, err := addOptions(u, opt)
179	if err != nil {
180		return nil, nil, err
181	}
182
183	req, err := s.client.NewRequest("GET", u, nil)
184	if err != nil {
185		return nil, nil, err
186	}
187
188	var events []*IssueEvent
189	resp, err := s.client.Do(ctx, req, &events)
190	if err != nil {
191		return nil, resp, err
192	}
193
194	return events, resp, nil
195}
196
197// ListEventsForRepoNetwork lists public events for a network of repositories.
198//
199// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories
200func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opt *ListOptions) ([]*Event, *Response, error) {
201	u := fmt.Sprintf("networks/%v/%v/events", owner, repo)
202	u, err := addOptions(u, opt)
203	if err != nil {
204		return nil, nil, err
205	}
206
207	req, err := s.client.NewRequest("GET", u, nil)
208	if err != nil {
209		return nil, nil, err
210	}
211
212	var events []*Event
213	resp, err := s.client.Do(ctx, req, &events)
214	if err != nil {
215		return nil, resp, err
216	}
217
218	return events, resp, nil
219}
220
221// ListEventsForOrganization lists public events for an organization.
222//
223// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization
224func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opt *ListOptions) ([]*Event, *Response, error) {
225	u := fmt.Sprintf("orgs/%v/events", org)
226	u, err := addOptions(u, opt)
227	if err != nil {
228		return nil, nil, err
229	}
230
231	req, err := s.client.NewRequest("GET", u, nil)
232	if err != nil {
233		return nil, nil, err
234	}
235
236	var events []*Event
237	resp, err := s.client.Do(ctx, req, &events)
238	if err != nil {
239		return nil, resp, err
240	}
241
242	return events, resp, nil
243}
244
245// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is
246// true, only public events will be returned.
247//
248// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user
249func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) {
250	var u string
251	if publicOnly {
252		u = fmt.Sprintf("users/%v/events/public", user)
253	} else {
254		u = fmt.Sprintf("users/%v/events", user)
255	}
256	u, err := addOptions(u, opt)
257	if err != nil {
258		return nil, nil, err
259	}
260
261	req, err := s.client.NewRequest("GET", u, nil)
262	if err != nil {
263		return nil, nil, err
264	}
265
266	var events []*Event
267	resp, err := s.client.Do(ctx, req, &events)
268	if err != nil {
269		return nil, resp, err
270	}
271
272	return events, resp, nil
273}
274
275// ListEventsReceivedByUser lists the events received by a user. If publicOnly is
276// true, only public events will be returned.
277//
278// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received
279func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opt *ListOptions) ([]*Event, *Response, error) {
280	var u string
281	if publicOnly {
282		u = fmt.Sprintf("users/%v/received_events/public", user)
283	} else {
284		u = fmt.Sprintf("users/%v/received_events", user)
285	}
286	u, err := addOptions(u, opt)
287	if err != nil {
288		return nil, nil, err
289	}
290
291	req, err := s.client.NewRequest("GET", u, nil)
292	if err != nil {
293		return nil, nil, err
294	}
295
296	var events []*Event
297	resp, err := s.client.Do(ctx, req, &events)
298	if err != nil {
299		return nil, resp, err
300	}
301
302	return events, resp, nil
303}
304
305// ListUserEventsForOrganization provides the user’s organization dashboard. You
306// must be authenticated as the user to view this.
307//
308// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization
309func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opt *ListOptions) ([]*Event, *Response, error) {
310	u := fmt.Sprintf("users/%v/events/orgs/%v", user, org)
311	u, err := addOptions(u, opt)
312	if err != nil {
313		return nil, nil, err
314	}
315
316	req, err := s.client.NewRequest("GET", u, nil)
317	if err != nil {
318		return nil, nil, err
319	}
320
321	var events []*Event
322	resp, err := s.client.Do(ctx, req, &events)
323	if err != nil {
324		return nil, resp, err
325	}
326
327	return events, resp, nil
328}
329