-
Notifications
You must be signed in to change notification settings - Fork 3
/
extension.js
145 lines (129 loc) · 4.13 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'use strict';
const request = require('request-promise');
const app = require('express')();
let nodecg;
let accessToken;
let _session;
module.exports = function (extensionApi) {
nodecg = extensionApi;
if (!nodecg.config.login.enabled) {
throw new Error('Login security is not enabled, lfg-twitchapi will not load.');
}
if (!nodecg.config.login.twitch.enabled) {
throw new Error('Twitch authentication is not enabled, lfg-twitchapi will not load.');
}
if (!Object.keys(nodecg.bundleConfig).length) {
throw new Error('No config found in cfg/lfg-twitch.json, aborting!');
}
const loginLib = require('../../lib/login');
// Non-confidential session details are made available to dashboard & view
const sessionReplicant = nodecg.Replicant('session', {defaultValue: null, persistent: false});
// Capture the relevant session data the moment our user logs in
loginLib.on('login', session => {
const user = session.passport.user;
_session = session;
if (user.provider === 'twitch' && user.username === nodecg.bundleConfig.username) {
// Update the 'session' syncedconst with only the non-confidential information
sessionReplicant.value = {
provider: user.provider, // should ALWAYS be 'twitch'
username: user.username,
displayName: user.displayName,
logo: user._json.logo,
url: user._json._links.self
};
accessToken = user.accessToken;
}
});
// If our target user logs out, we can't do anything else until they log back in
loginLib.on('logout', session => {
const user = session.passport.user;
if (user.provider === 'twitch' && user.username === nodecg.bundleConfig.username) {
sessionReplicant.value = null;
accessToken = null;
_session = null;
}
});
app.get('/lfg-twitchapi/checkuser', (req, res) => {
if (req.session.passport && req.session.passport.user) {
const user = req.session.passport.user;
if (user.username === nodecg.bundleConfig.username) {
// Update the 'session' Replicant with only the non-confidential information
sessionReplicant.value = {
provider: user.provider, // should ALWAYS be 'twitch'
username: user.username,
displayName: user.displayName,
logo: user._json.logo,
url: user._json._links.self
};
accessToken = user.accessToken;
_session = req.session;
}
}
res.sendStatus(200);
});
nodecg.mount(app);
// Return the function used to make API calls, so other bundles can use it
return {
get(path, qs, body) {
return apiCall('GET', path, qs, body);
},
post(path, qs, body) {
return apiCall('POST', path, qs, body);
},
put(path, qs, body) {
return apiCall('PUT', path, qs, body);
},
delete(path, qs, body) {
return apiCall('DELETE', path, qs, body);
},
destroySession() {
if (_session) {
_session.destroy(err => {
if (err) {
nodecg.log.error(err.stack);
} else {
const username = _session.passport.user.displayName;
sessionReplicant.value = null;
accessToken = null;
_session = null;
nodecg.sendMessage('destroyed', username);
}
});
}
},
channel: nodecg.bundleConfig.username
};
};
function apiCall(method = 'GET', path = '', qs = {}, body = {}) {
const requestOptions = {
method,
url: `https://api.twitch.tv/kraken${path}`,
headers: {
'Accept': 'application/vnd.twitchtv.v3+json',
'content-type': 'application/json',
'Client-ID': nodecg.config.login.twitch.clientID
},
qs,
body,
json: true,
resolveWithFullResponse: true,
simple: false
};
// If {{username}} is present in the url string, replace it with the username from bundleConfig
if (requestOptions.url.indexOf('{{username}}') >= 0) {
// If we don't have an active session, error
if (!accessToken) {
return new Promise((resolve, reject) => {
process.nextTick(() => {
reject(`Access token for "${nodecg.bundleConfig.username}" has not been captured yet.` +
' Once they sign in, this error will stop.');
});
});
}
requestOptions.url = requestOptions.url.replace('{{username}}', nodecg.bundleConfig.username);
}
if (accessToken) {
requestOptions.headers.Authorization = `OAuth ${accessToken}`;
}
return request(requestOptions);
}