Skip to content

Commit

Permalink
refactor [liberapay] service (#2879)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris48s authored Jan 28, 2019
1 parent 97e2ec1 commit a9d6809
Show file tree
Hide file tree
Showing 11 changed files with 339 additions and 214 deletions.
76 changes: 76 additions & 0 deletions services/liberapay/liberapay-base.js
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,
}
37 changes: 37 additions & 0 deletions services/liberapay/liberapay-gives.service.js
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' })
}
}
}
32 changes: 32 additions & 0 deletions services/liberapay/liberapay-gives.tester.js
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' })
41 changes: 41 additions & 0 deletions services/liberapay/liberapay-goal.service.js
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' })
}
}
}
32 changes: 32 additions & 0 deletions services/liberapay/liberapay-goal.tester.js
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' })
34 changes: 34 additions & 0 deletions services/liberapay/liberapay-patrons.service.js
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 })
}
}
18 changes: 18 additions & 0 deletions services/liberapay/liberapay-patrons.tester.js
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' })
37 changes: 37 additions & 0 deletions services/liberapay/liberapay-receives.service.js
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' })
}
}
}
32 changes: 32 additions & 0 deletions services/liberapay/liberapay-receives.tester.js
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' })
Loading

0 comments on commit a9d6809

Please sign in to comment.