Skip to content

Commit d844cef

Browse files
committed
add a svg badge to show slack user status
close outsideris#114
1 parent c6230d4 commit d844cef

File tree

4 files changed

+72
-4
lines changed

4 files changed

+72
-4
lines changed

config.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ module.exports = {
44
// your slack team url (ex: socketio.slack.com)
55
slackUrl: process.env.SLACK_URL || 'YOUR-TEAM.slack.com',
66
// access token of slack
7-
// You can generate it in https://api.slack.com/web#auth
8-
// You should generate the token in admin user, not owner.
9-
// If you generate the token in owner user, missing_scope error will be occurred.
7+
// see https://github.com/outsideris/slack-invite-automation#issue-token
108
//
119
// You can test your token via curl:
1210
// curl -X POST 'https://YOUR-SLACK-TEAM.slack.com/api/users.admin.invite' \

lib/badge.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const pug = require('pug')
2+
3+
const title = 'slack';
4+
const color = '#39AE85';
5+
6+
function width(str) {
7+
return 6 * str.length;
8+
}
9+
10+
const svgTmpl =
11+
`svg(xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width=wd height="20")\n` +
12+
` linearGradient(x2="0" y2="100%")#b\n` +
13+
` stop(offset="0" stop-color="#bbb" stop-opacity=".1")\n` +
14+
` stop(offset="1" stop-opacity=".1")\n` +
15+
` clipPath#a\n` +
16+
` rect(width=wd height="20" rx="3" fill="#fff")\n` +
17+
` g(clip-path="url(#a)")\n` +
18+
` path(fill="#555" d='M0 0h' + left + 'v20H0z')\n` +
19+
` path(fill="${color}" d='M'+left + ' 0h' + (wd-left) + 'v20H' + left +'z')\n` +
20+
` path(fill="url(#b)" d='M0 0h' + wd + 'v20H0z')\n` +
21+
` g(fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110")\n` +
22+
` text(x="195" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="${title.length*54}") ${title}\n` +
23+
` text(x="195" y="140" transform="scale(.1)" textLength="${title.length*54}") ${title}\n` +
24+
` text(x=(wd * 5 + 195) y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength=(value.length*60)) #{value}\n` +
25+
` text(x=(wd * 5 + 195) y="140" transform="scale(.1)" textLength=(value.length*60)) #{value}\n`;
26+
27+
module.exports = {
28+
badge: function(presence, total) {
29+
const fn = pug.compile(svgTmpl);
30+
const value = `${presence}/${total}`;
31+
const left = width(title) + 8;
32+
const wd = left + width(value) + 22;
33+
return fn({ value, wd, left });
34+
},
35+
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"i18n": "^0.8.3",
1515
"jade": "^1.11.0",
1616
"morgan": "^1.6.0",
17+
"pug": "^2.0.0-rc.4",
1718
"request": "^2.62.0",
1819
"serve-favicon": "^2.3.0"
1920
}

routes/index.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const express = require('express');
22
const router = express.Router();
33
const request = require('request');
4+
45
const config = require('../config');
6+
const { badge } = require('../lib/badge');
57

68
router.get('/', function(req, res) {
79
res.setLocale(config.locale);
@@ -33,7 +35,7 @@ router.post('/invite', function(req, res) {
3335
message: 'Success! Check “'+ req.body.email +'” for an invite from Slack.'
3436
});
3537
} else {
36-
const error = body.error;
38+
let error = body.error;
3739
if (error === 'already_invited' || error === 'already_in_team') {
3840
res.render('result', {
3941
community: config.community,
@@ -105,4 +107,36 @@ router.post('/invite', function(req, res) {
105107
}
106108
});
107109

110+
router.get('/badge.svg', (req, res) => {
111+
request.get({
112+
url: 'https://'+ config.slackUrl + '/api/users.list',
113+
qs: {
114+
token: config.slacktoken,
115+
presence: true
116+
}
117+
}, function(err, httpResponse, body) {
118+
try {
119+
body = JSON.parse(body);
120+
} catch(e) {
121+
return res.status(404).send('');
122+
}
123+
if (!body.members) {
124+
return res.status(404).send('');
125+
}
126+
127+
const members = body.members.filter(function(m) {
128+
return !m.is_bot;
129+
});
130+
const total = members.length;
131+
const presence = members.filter(function(m) {
132+
return m.presence === 'active';
133+
}).length;
134+
135+
res.type('svg');
136+
res.set('Cache-Control', 'max-age=0, no-cache');
137+
res.set('Pragma', 'no-cache');
138+
res.send(badge(presence, total));
139+
});
140+
});
141+
108142
module.exports = router;

0 commit comments

Comments
 (0)