-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor [liberapay] service (#2879)
- Loading branch information
Showing
11 changed files
with
339 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { metric } = require('../../lib/text-formatters') | ||
const { BaseJsonService } = require('..') | ||
const { colorScale } = require('../../lib/color-formatters') | ||
const { nonNegativeInteger } = require('../validators') | ||
|
||
const schema = Joi.object({ | ||
npatrons: nonNegativeInteger, | ||
giving: Joi.object() | ||
.keys({ | ||
amount: Joi.string().required(), | ||
currency: Joi.string().required(), | ||
}) | ||
.allow(null) | ||
.required(), | ||
receiving: Joi.object() | ||
.keys({ | ||
amount: Joi.string().required(), | ||
currency: Joi.string().required(), | ||
}) | ||
.allow(null) | ||
.required(), | ||
goal: Joi.object() | ||
.keys({ | ||
amount: Joi.string().required(), | ||
}) | ||
.allow(null) | ||
.required(), | ||
}).required() | ||
|
||
const isCurrencyOverTime = Joi.string().regex( | ||
/^([0-9]*[1-9][0-9]*(\.[0-9]+)?|[0]+\.[0-9]*[1-9][0-9]*)[ A-Za-z]{4}\/week/ | ||
) | ||
|
||
function renderCurrencyBadge({ label, amount, currency }) { | ||
return { | ||
label, | ||
message: `${metric(amount)} ${currency}/week`, | ||
color: colorScale([0, 10, 100])(amount), | ||
} | ||
} | ||
|
||
class LiberapayBase extends BaseJsonService { | ||
static get category() { | ||
return 'funding' | ||
} | ||
|
||
static get defaultBadgeData() { | ||
return { | ||
label: 'liberapay', | ||
namedLogo: 'liberapay', | ||
} | ||
} | ||
|
||
async fetch({ entity }) { | ||
return this._requestJson({ | ||
schema, | ||
url: `https://liberapay.com/${entity}/public.json`, | ||
}) | ||
} | ||
|
||
static buildRoute(badgeName) { | ||
return { | ||
base: `liberapay/${badgeName}`, | ||
pattern: ':entity', | ||
} | ||
} | ||
} | ||
|
||
module.exports = { | ||
renderCurrencyBadge, | ||
LiberapayBase, | ||
isCurrencyOverTime, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use strict' | ||
|
||
const { InvalidResponse } = require('..') | ||
const { renderCurrencyBadge, LiberapayBase } = require('./liberapay-base') | ||
|
||
module.exports = class LiberapayGives extends LiberapayBase { | ||
static get route() { | ||
return this.buildRoute('gives') | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'Liberapay giving', | ||
namedParams: { entity: 'Changaco' }, | ||
staticPreview: renderCurrencyBadge({ | ||
label: 'gives', | ||
amount: '2.58', | ||
currency: 'EUR', | ||
}), | ||
}, | ||
] | ||
} | ||
|
||
async handle({ entity }) { | ||
const data = await this.fetch({ entity }) | ||
if (data.giving) { | ||
return renderCurrencyBadge({ | ||
label: 'gives', | ||
amount: data.giving.amount, | ||
currency: data.giving.currency, | ||
}) | ||
} else { | ||
throw new InvalidResponse({ prettyMessage: 'no public giving stats' }) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { isCurrencyOverTime } = require('./liberapay-base') | ||
const t = (module.exports = require('..').createServiceTester()) | ||
|
||
t.create('Giving (valid)') | ||
.get('/Changaco.json') | ||
.expectJSONTypes( | ||
Joi.object().keys({ | ||
name: 'gives', | ||
value: isCurrencyOverTime, | ||
}) | ||
) | ||
|
||
t.create('Giving (not found)') | ||
.get('/does-not-exist.json') | ||
.expectJSON({ name: 'liberapay', value: 'not found' }) | ||
|
||
t.create('Giving (null)') | ||
.get('/Liberapay.json') | ||
.intercept(nock => | ||
nock('https://liberapay.com') | ||
.get('/Liberapay/public.json') | ||
.reply(200, { | ||
npatrons: 0, | ||
giving: null, | ||
receiving: null, | ||
goal: null, | ||
}) | ||
) | ||
.expectJSON({ name: 'liberapay', value: 'no public giving stats' }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
'use strict' | ||
|
||
const { InvalidResponse } = require('..') | ||
const { LiberapayBase } = require('./liberapay-base') | ||
const { colorScale } = require('../../lib/color-formatters') | ||
|
||
module.exports = class LiberapayGoal extends LiberapayBase { | ||
static get route() { | ||
return this.buildRoute('goal') | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'Liberapay goal progress', | ||
namedParams: { entity: 'Changaco' }, | ||
staticPreview: this.render({ percentAcheived: 33 }), | ||
}, | ||
] | ||
} | ||
|
||
static render({ percentAcheived }) { | ||
return { | ||
label: 'goal progress', | ||
message: `${percentAcheived}%`, | ||
color: colorScale([0, 10, 100])(percentAcheived), | ||
} | ||
} | ||
|
||
async handle({ entity }) { | ||
const data = await this.fetch({ entity }) | ||
if (data.goal) { | ||
const percentAcheived = Math.round( | ||
(data.receiving.amount / data.goal.amount) * 100 | ||
) | ||
return this.constructor.render({ percentAcheived }) | ||
} else { | ||
throw new InvalidResponse({ prettyMessage: 'no public goals' }) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { isIntegerPercentage } = require('../test-validators') | ||
const t = (module.exports = require('..').createServiceTester()) | ||
|
||
t.create('Goal Progress (valid)') | ||
.get('/Liberapay.json') | ||
.expectJSONTypes( | ||
Joi.object().keys({ | ||
name: 'goal progress', | ||
value: isIntegerPercentage, | ||
}) | ||
) | ||
|
||
t.create('Goal Progress (not found)') | ||
.get('/does-not-exist.json') | ||
.expectJSON({ name: 'liberapay', value: 'not found' }) | ||
|
||
t.create('Goal Progress (no goal set)') | ||
.get('/Liberapay.json') | ||
.intercept(nock => | ||
nock('https://liberapay.com') | ||
.get('/Liberapay/public.json') | ||
.reply(200, { | ||
npatrons: 0, | ||
giving: null, | ||
receiving: null, | ||
goal: null, | ||
}) | ||
) | ||
.expectJSON({ name: 'liberapay', value: 'no public goals' }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
'use strict' | ||
|
||
const { LiberapayBase } = require('./liberapay-base') | ||
const { metric } = require('../../lib/text-formatters') | ||
const { colorScale } = require('../../lib/color-formatters') | ||
|
||
module.exports = class LiberapayPatrons extends LiberapayBase { | ||
static get route() { | ||
return this.buildRoute('patrons') | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'Liberapay patrons', | ||
namedParams: { entity: 'Changaco' }, | ||
staticPreview: this.render({ patrons: 10 }), | ||
}, | ||
] | ||
} | ||
|
||
static render({ patrons }) { | ||
return { | ||
label: 'patrons', | ||
message: metric(patrons), | ||
color: colorScale([0, 10, 100])(patrons), | ||
} | ||
} | ||
|
||
async handle({ entity }) { | ||
const data = await this.fetch({ entity }) | ||
return this.constructor.render({ patrons: data.npatrons }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { isMetric } = require('../test-validators') | ||
const t = (module.exports = require('..').createServiceTester()) | ||
|
||
t.create('Patrons (valid)') | ||
.get('/Liberapay.json') | ||
.expectJSONTypes( | ||
Joi.object().keys({ | ||
name: 'patrons', | ||
value: isMetric, | ||
}) | ||
) | ||
|
||
t.create('Patrons (not found)') | ||
.get('/does-not-exist.json') | ||
.expectJSON({ name: 'liberapay', value: 'not found' }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use strict' | ||
|
||
const { InvalidResponse } = require('..') | ||
const { renderCurrencyBadge, LiberapayBase } = require('./liberapay-base') | ||
|
||
module.exports = class LiberapayReceives extends LiberapayBase { | ||
static get route() { | ||
return this.buildRoute('receives') | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'Liberapay receiving', | ||
namedParams: { entity: 'Changaco' }, | ||
staticPreview: renderCurrencyBadge({ | ||
label: 'receives', | ||
amount: '98.32', | ||
currency: 'EUR', | ||
}), | ||
}, | ||
] | ||
} | ||
|
||
async handle({ entity }) { | ||
const data = await this.fetch({ entity }) | ||
if (data.receiving) { | ||
return renderCurrencyBadge({ | ||
label: 'receives', | ||
amount: data.receiving.amount, | ||
currency: data.receiving.currency, | ||
}) | ||
} else { | ||
throw new InvalidResponse({ prettyMessage: 'no public receiving stats' }) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { isCurrencyOverTime } = require('./liberapay-base') | ||
const t = (module.exports = require('..').createServiceTester()) | ||
|
||
t.create('Receiving (valid)') | ||
.get('/Changaco.json') | ||
.expectJSONTypes( | ||
Joi.object().keys({ | ||
name: 'receives', | ||
value: isCurrencyOverTime, | ||
}) | ||
) | ||
|
||
t.create('Receiving (not found)') | ||
.get('/does-not-exist.json') | ||
.expectJSON({ name: 'liberapay', value: 'not found' }) | ||
|
||
t.create('Receiving (null)') | ||
.get('/Liberapay.json') | ||
.intercept(nock => | ||
nock('https://liberapay.com') | ||
.get('/Liberapay/public.json') | ||
.reply(200, { | ||
npatrons: 0, | ||
giving: null, | ||
receiving: null, | ||
goal: null, | ||
}) | ||
) | ||
.expectJSON({ name: 'liberapay', value: 'no public receiving stats' }) |
Oops, something went wrong.