1// Copyright 2014 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	"fmt"
11)
12
13// Subscription identifies a repository or thread subscription.
14type Subscription struct {
15	Subscribed *bool      `json:"subscribed,omitempty"`
16	Ignored    *bool      `json:"ignored,omitempty"`
17	Reason     *string    `json:"reason,omitempty"`
18	CreatedAt  *Timestamp `json:"created_at,omitempty"`
19	URL        *string    `json:"url,omitempty"`
20
21	// only populated for repository subscriptions
22	RepositoryURL *string `json:"repository_url,omitempty"`
23
24	// only populated for thread subscriptions
25	ThreadURL *string `json:"thread_url,omitempty"`
26}
27
28// ListWatchers lists watchers of a particular repo.
29//
30// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers
31func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opt *ListOptions) ([]*User, *Response, error) {
32	u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo)
33	u, err := addOptions(u, opt)
34	if err != nil {
35		return nil, nil, err
36	}
37
38	req, err := s.client.NewRequest("GET", u, nil)
39	if err != nil {
40		return nil, nil, err
41	}
42
43	var watchers []*User
44	resp, err := s.client.Do(ctx, req, &watchers)
45	if err != nil {
46		return nil, resp, err
47	}
48
49	return watchers, resp, nil
50}
51
52// ListWatched lists the repositories the specified user is watching. Passing
53// the empty string will fetch watched repos for the authenticated user.
54//
55// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched
56func (s *ActivityService) ListWatched(ctx context.Context, user string, opt *ListOptions) ([]*Repository, *Response, error) {
57	var u string
58	if user != "" {
59		u = fmt.Sprintf("users/%v/subscriptions", user)
60	} else {
61		u = "user/subscriptions"
62	}
63	u, err := addOptions(u, opt)
64	if err != nil {
65		return nil, nil, err
66	}
67
68	req, err := s.client.NewRequest("GET", u, nil)
69	if err != nil {
70		return nil, nil, err
71	}
72
73	var watched []*Repository
74	resp, err := s.client.Do(ctx, req, &watched)
75	if err != nil {
76		return nil, resp, err
77	}
78
79	return watched, resp, nil
80}
81
82// GetRepositorySubscription returns the subscription for the specified
83// repository for the authenticated user. If the authenticated user is not
84// watching the repository, a nil Subscription is returned.
85//
86// GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription
87func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) {
88	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
89
90	req, err := s.client.NewRequest("GET", u, nil)
91	if err != nil {
92		return nil, nil, err
93	}
94
95	sub := new(Subscription)
96	resp, err := s.client.Do(ctx, req, sub)
97	if err != nil {
98		// if it's just a 404, don't return that as an error
99		_, err = parseBoolResponse(err)
100		return nil, resp, err
101	}
102
103	return sub, resp, nil
104}
105
106// SetRepositorySubscription sets the subscription for the specified repository
107// for the authenticated user.
108//
109// To watch a repository, set subscription.Subscribed to true.
110// To ignore notifications made within a repository, set subscription.Ignored to true.
111// To stop watching a repository, use DeleteRepositorySubscription.
112//
113// GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
114func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) {
115	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
116
117	req, err := s.client.NewRequest("PUT", u, subscription)
118	if err != nil {
119		return nil, nil, err
120	}
121
122	sub := new(Subscription)
123	resp, err := s.client.Do(ctx, req, sub)
124	if err != nil {
125		return nil, resp, err
126	}
127
128	return sub, resp, nil
129}
130
131// DeleteRepositorySubscription deletes the subscription for the specified
132// repository for the authenticated user.
133//
134// This is used to stop watching a repository. To control whether or not to
135// receive notifications from a repository, use SetRepositorySubscription.
136//
137// GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
138func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) {
139	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
140	req, err := s.client.NewRequest("DELETE", u, nil)
141	if err != nil {
142		return nil, err
143	}
144
145	return s.client.Do(ctx, req, nil)
146}
147