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://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#list-watchers
31func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) {
32	u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo)
33	u, err := addOptions(u, opts)
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://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#list-repositories-watched-by-the-authenticated-user
56// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#list-repositories-watched-by-a-user
57func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) {
58	var u string
59	if user != "" {
60		u = fmt.Sprintf("users/%v/subscriptions", user)
61	} else {
62		u = "user/subscriptions"
63	}
64	u, err := addOptions(u, opts)
65	if err != nil {
66		return nil, nil, err
67	}
68
69	req, err := s.client.NewRequest("GET", u, nil)
70	if err != nil {
71		return nil, nil, err
72	}
73
74	var watched []*Repository
75	resp, err := s.client.Do(ctx, req, &watched)
76	if err != nil {
77		return nil, resp, err
78	}
79
80	return watched, resp, nil
81}
82
83// GetRepositorySubscription returns the subscription for the specified
84// repository for the authenticated user. If the authenticated user is not
85// watching the repository, a nil Subscription is returned.
86//
87// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#get-a-repository-subscription
88func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) {
89	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
90
91	req, err := s.client.NewRequest("GET", u, nil)
92	if err != nil {
93		return nil, nil, err
94	}
95
96	sub := new(Subscription)
97	resp, err := s.client.Do(ctx, req, sub)
98	if err != nil {
99		// if it's just a 404, don't return that as an error
100		_, err = parseBoolResponse(err)
101		return nil, resp, err
102	}
103
104	return sub, resp, nil
105}
106
107// SetRepositorySubscription sets the subscription for the specified repository
108// for the authenticated user.
109//
110// To watch a repository, set subscription.Subscribed to true.
111// To ignore notifications made within a repository, set subscription.Ignored to true.
112// To stop watching a repository, use DeleteRepositorySubscription.
113//
114// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#set-a-repository-subscription
115func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) {
116	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
117
118	req, err := s.client.NewRequest("PUT", u, subscription)
119	if err != nil {
120		return nil, nil, err
121	}
122
123	sub := new(Subscription)
124	resp, err := s.client.Do(ctx, req, sub)
125	if err != nil {
126		return nil, resp, err
127	}
128
129	return sub, resp, nil
130}
131
132// DeleteRepositorySubscription deletes the subscription for the specified
133// repository for the authenticated user.
134//
135// This is used to stop watching a repository. To control whether or not to
136// receive notifications from a repository, use SetRepositorySubscription.
137//
138// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/activity/#delete-a-repository-subscription
139func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) {
140	u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
141	req, err := s.client.NewRequest("DELETE", u, nil)
142	if err != nil {
143		return nil, err
144	}
145
146	return s.client.Do(ctx, req, nil)
147}
148