diff --git a/package.json b/package.json index 4f227e312b..6f3ec2dafb 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "camp": "~16.2.3", "chrome-web-store-item-property": "~1.1.2", "dot": "~1.0.3", + "pretty-bytes": "^3.0.1", "gm": "^1.23.0", "json-autosave": "~1.1.2", "pdfkit": "~0.8.0", diff --git a/server.js b/server.js index dae571b0d2..5fe07b7a8d 100644 --- a/server.js +++ b/server.js @@ -31,6 +31,7 @@ var svg2img = require('./lib/svg-to-img.js'); var loadLogos = require('./lib/load-logos.js'); var githubAuth = require('./lib/github-auth.js'); var querystring = require('querystring'); +var prettyBytes = require('pretty-bytes'); var xml2js = require('xml2js'); var serverSecrets = require('./lib/server-secrets'); if (serverSecrets && serverSecrets.gh_client_id) { @@ -3436,6 +3437,48 @@ cache(function(data, match, sendBadge, request) { }); })); +// GitHub file size. +camp.route(/^\/github\/size\/([^\/]+)\/([^\/]+)\/(.*)\.(svg|png|gif|jpg|json)$/, +cache(function(data, match, sendBadge, request) { + var user = match[1]; // eg, mashape + var repo = match[2]; // eg, apistatus + var path = match[3]; + var format = match[4]; + var apiUrl = githubApiUrl + '/repos/' + user + '/' + repo + '/contents/' + path; + + var badgeData = getBadgeData('size', data); + if (badgeData.template === 'social') { + badgeData.logo = badgeData.logo || logos.github; + } + + githubAuth.request(request, apiUrl, {}, function(err, res, buffer) { + if (err != null) { + badgeData.text[1] = 'inaccessible'; + sendBadge(format, badgeData); + return; + } + try { + if (res.statusCode === 404) { + badgeData.text[1] = 'repo or file not found'; + sendBadge(format, badgeData); + return; + } + var body = JSON.parse(buffer); + if (body && Number.isInteger(body.size)) { + badgeData.text[1] = prettyBytes(body.size); + badgeData.colorscheme = 'green'; + sendBadge(format, badgeData); + } else { + badgeData.text[1] = 'not a regular file'; + sendBadge(format, badgeData); + } + } catch(e) { + badgeData.text[1] = 'invalid'; + sendBadge(format, badgeData); + } + }); +})); + // Bitbucket issues integration. camp.route(/^\/bitbucket\/issues(-raw)?\/([^\/]+)\/([^\/]+)\.(svg|png|gif|jpg|json)$/, cache(function(data, match, sendBadge, request) { diff --git a/service-tests/github.js b/service-tests/github.js new file mode 100644 index 0000000000..6bc95aab2c --- /dev/null +++ b/service-tests/github.js @@ -0,0 +1,28 @@ +'use strict'; + +const Joi = require('joi'); +const ServiceTester = require('./runner/service-tester'); + +const t = new ServiceTester({ id: 'github', title: 'Github' }); +module.exports = t; + +t.create('File size') + .get('/size/webcaetano/craft/build/craft.min.js.json') + .expectJSONTypes(Joi.object().keys({ + name: Joi.equal('size'), + value: Joi.string().regex(/^[0-9]*[.]?[0-9]+\s(B|kB|MB|GB|TB|PB|EB|ZB|YB)$/), + })); + +t.create('File size 404') + .get('/size/webcaetano/craft/build/does-not-exist.min.js.json') + .expectJSONTypes(Joi.object().keys({ + name: Joi.equal('size'), + value: Joi.string().regex(/^repo or file not found$/), + })); + +t.create('File size for "not a regular file"') + .get('/size/webcaetano/craft/build.json') + .expectJSONTypes(Joi.object().keys({ + name: Joi.equal('size'), + value: Joi.string().regex(/^not a regular file$/), + })); diff --git a/try.html b/try.html index 1d48e2b62b..e22a3b4989 100644 --- a/try.html +++ b/try.html @@ -798,6 +798,10 @@ Pixel-perfect Retina-ready Fast Consistent Hackable
https://img.shields.io/github/license/mashape/apistatus.svghttps://img.shields.io/github/size/webcaetano/craft/build/craft.min.js.svghttps://img.shields.io/bitbucket/issues/atlassian/python-bitbucket.svg