Skip to content

Commit 2f73600

Browse files
committed
feature(watching): Add support for ignoring or subscribing to repos
See: https://developer.github.com/v3/activity/watching/
1 parent 83775a1 commit 2f73600

5 files changed

Lines changed: 188 additions & 4 deletions

File tree

lib/GitHub.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Repository from './Repository';
1515
import Organization from './Organization';
1616
import Team from './Team';
1717
import Markdown from './Markdown';
18+
import Watching from './Watching';
1819

1920
/**
2021
* GitHub encapsulates the functionality to create various API wrapper objects.
@@ -113,6 +114,14 @@ class GitHub {
113114
return new Markdown(this.__auth, this.__apiBase);
114115
}
115116

117+
/**
118+
* Create a new Watching wrapper
119+
* @return {Watching}
120+
*/
121+
watching() {
122+
return new Watching(this.__auth, this.__apiBase);
123+
}
124+
116125
/**
117126
* Computes the full repository name
118127
* @param {string} user - the username (or the full name)

lib/Watching.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* @file
3+
* @copyright 2016 Matt Smith (Development Seed)
4+
* @license Licensed under {@link https://spdx.org/licenses/BSD-3-Clause-Clear.html BSD-3-Clause-Clear}.
5+
* Github.js is freely distributable.
6+
*/
7+
8+
import Requestable from './Requestable';
9+
import debug from 'debug';
10+
const log = debug('github:watching');
11+
12+
/**
13+
* Watching a Repository registers the user to receive notifications on new discussions, as well as events in the user's
14+
* activity feed.
15+
*/
16+
export default class Watching extends Requestable {
17+
/**
18+
* Watching wrapper
19+
* @param {Requestable.auth} [auth] - information required to authenticate to Github
20+
* @param {string} [apiBase=https://api.github.com] - the base Github API URL
21+
*/
22+
constructor(auth, apiBase) {
23+
super(auth, apiBase);
24+
}
25+
26+
/**
27+
* Get Watchers for repo
28+
* @see https://developer.github.com/v3/activity/watching/#list-watchers
29+
* @param {string} owner - username or organization
30+
* @param {string} repo - repo name
31+
* @param {Requestable.callback} [cb] - list of watchers
32+
* @return {Promise} - the promise for the http request
33+
*/
34+
listWatchers(owner, repo, cb) {
35+
log(`Fetching watchers for ${owner}/${repo}`);
36+
return this._requestAllPages(`/repos/${owner}/${repo}/subscribers`, undefined, cb);
37+
}
38+
39+
/**
40+
* Subscribe to repo
41+
* @see https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
42+
* @param {string} owner - username or organization
43+
* @param {string} repo - repo name
44+
* @param {Requestable.callback} [cb] - subscription status
45+
* @return {Promise} - the promise for the http request
46+
*/
47+
subscribe(owner, repo, cb) {
48+
log(`Subscribing to ${owner}/${repo}`);
49+
return this._setSubscription(owner, repo, true, cb);
50+
}
51+
52+
/**
53+
* Ignore a repo
54+
* @see https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
55+
* @param {string} owner - username or organization
56+
* @param {string} repo - repo name
57+
* @param {Requestable.callback} [cb] - subscription status
58+
* @return {Promise} - the promise for the http request
59+
*/
60+
ignore(owner, repo, cb) {
61+
log(`Ignoring ${owner}/${repo}`);
62+
return this._setSubscription(owner, repo, false, cb);
63+
}
64+
65+
/**
66+
* Remove all subscription settings for repo
67+
* @see https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
68+
* @param {string} owner - username or organization
69+
* @param {string} repo - repo name
70+
* @param {Requestable.callback} [cb] - subscription status
71+
* @return {Promise} - the promise for the http request
72+
*/
73+
removeSubscription(owner, repo, cb) {
74+
log(`Removing subscription settings for ${owner}/${repo}`);
75+
return this._request204or404(`/repos/${owner}/${repo}/subscription`, undefined, cb, 'DELETE');
76+
}
77+
78+
/**
79+
* General subscription method
80+
* @private
81+
* @see https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
82+
* @param {string} owner - username or organization
83+
* @param {string} repo - repo name
84+
* @param {boolean} subscribed - subscribed or ignored
85+
* @param {Requestable.callback} [cb] - subscription status
86+
* @return {Promise} - the promise for the http request
87+
*/
88+
_setSubscription(owner, repo, subscribed, cb) {
89+
log(`Subscribing to ${owner}/${repo}`);
90+
return this._request('PUT', `/repos/${owner}/${repo}/subscription`, {
91+
subscribed,
92+
ignored: !subscribed
93+
}, cb);
94+
}
95+
}

test/fixtures/alt-user.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"USERNAME": "mtscout6-test",
3+
"PASSWORD": "test1324"
4+
}

test/team.spec.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import expect from 'must';
22

33
import Github from '../lib/GitHub';
44
import testUser from './fixtures/user.json';
5+
import altUser from './fixtures/alt-user.json';
56
import {assertFailure} from './helpers/callbacks';
67
import getTestRepoName from './helpers/getTestRepoName';
78

8-
const altUser = {
9-
USERNAME: 'mtscout6-test'
10-
};
11-
129
function createTestTeam() {
1310
const name = getTestRepoName();
1411

test/watching.spec.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import expect from 'must';
2+
3+
import Github from '../lib/GitHub';
4+
import testUser from './fixtures/user.json';
5+
import altUser from './fixtures/alt-user.json';
6+
import getTestRepoName from './helpers/getTestRepoName';
7+
8+
describe('Watching', function() {
9+
const testRepoName = getTestRepoName();
10+
let githubUser;
11+
let githubAltUser;
12+
let organization;
13+
14+
before(function() {
15+
githubUser = new Github({
16+
username: testUser.USERNAME,
17+
password: testUser.PASSWORD,
18+
auth: 'basic'
19+
});
20+
21+
githubAltUser = new Github({
22+
username: altUser.USERNAME,
23+
password: altUser.PASSWORD,
24+
auth: 'basic'
25+
});
26+
27+
organization = githubUser.getOrganization(testUser.ORGANIZATION);
28+
29+
const options = {
30+
name: testRepoName,
31+
description: 'test repo watchers',
32+
homepage: 'https://github.com/',
33+
private: false,
34+
has_issues: false, // eslint-disable-line
35+
has_wiki: false, // eslint-disable-line
36+
has_downloads: false // eslint-disable-line
37+
};
38+
39+
return organization.createRepo(options);
40+
});
41+
42+
it('should list watchers', function() {
43+
return githubUser.watching()
44+
.listWatchers(testUser.ORGANIZATION, 'fixed-test-repo-1')
45+
.then(({data}) => {
46+
const watchers = data.map((x) => x.login);
47+
expect(watchers).must.include('mikedeboertest');
48+
});
49+
});
50+
51+
it('should add a subscription to a repo', function() {
52+
const watching = githubAltUser.watching();
53+
54+
return watching.subscribe(testUser.ORGANIZATION, testRepoName)
55+
.then(({data}) => {
56+
expect(data.subscribed).to.be.true();
57+
expect(data.ignored).to.be.false();
58+
});
59+
});
60+
61+
it('should ignore a repo', function() {
62+
const watching = githubAltUser.watching();
63+
64+
return watching.ignore(testUser.ORGANIZATION, testRepoName)
65+
.then(({data}) => {
66+
expect(data.subscribed).to.be.false();
67+
expect(data.ignored).to.be.true();
68+
});
69+
});
70+
71+
it('should remove subscription settings', function() {
72+
const watching = githubAltUser.watching();
73+
74+
return watching.removeSubscription(testUser.ORGANIZATION, testRepoName)
75+
.then((result) => {
76+
expect(result).to.be.true();
77+
});
78+
});
79+
});

0 commit comments

Comments
 (0)