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