Skip to content

Commit

Permalink
Add Wikiapiary Extension Badge [WikiapiaryInstalls] (#6678)
Browse files Browse the repository at this point in the history
* feat: add wikiapiary extension badge

* fix: refactor wikiapiary badge

* fix: display correct message when not found

Co-authored-by: chris48s <chris48s@users.noreply.github.com>

* fix: weird behavior with casing

* fix: test malformed api response

* chore: use options.qs for query parameters

* chore: rename file to match class name

Co-authored-by: chris48s <chris48s@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jul 7, 2021
1 parent 90831e6 commit 23678fe
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 0 deletions.
110 changes: 110 additions & 0 deletions services/wikiapiary/wikiapiary-installs.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use strict'

const Joi = require('joi')
const { metric } = require('../text-formatters')
const { BaseJsonService, NotFound } = require('..')

const documentation = `
<p>
The name of an extension is case-sensitive excluding the first character.
</p>
<p>
For example, in the case of <code>ParserFunctions</code>, the following are
valid:
<ul>
<li><code>ParserFunctions</code></li>
<li><code>parserFunctions</code></li>
</ul>
However, the following are invalid:
<ul>
<li><code>parserfunctions</code></li>
<li><code>Parserfunctions</code></li>
<li><code>pARSERfUNCTIONS</code></li>
</ul>
</p>
`

const schema = Joi.object({
query: Joi.object({
results: Joi.alternatives([
Joi.object()
.required()
.pattern(/^\w+:.+$/, {
printouts: Joi.object({
'Has website count': Joi.array()
.required()
.items(Joi.number().required()),
}).required(),
}),
Joi.array().required(),
]).required(),
}).required(),
}).required()

/**
* This badge displays the total installations of a MediaWiki extensions, skins,
* etc via Wikiapiary.
*
* {@link https://www.mediawiki.org/wiki/Manual:Extensions MediaWiki Extensions Manual}
*/
module.exports = class WikiapiaryInstalls extends BaseJsonService {
static category = 'downloads'
static route = {
base: 'wikiapiary',
pattern: ':variant(extension|skin|farm|generator|host)/installs/:name',
}

static examples = [
{
title: 'Wikiapiary installs',
namedParams: { variant: 'extension', name: 'ParserFunctions' },
staticPreview: this.render({ usage: 11170 }),
documentation,
keywords: ['mediawiki'],
},
]

static defaultBadgeData = { label: 'installs', color: 'informational' }

static render({ usage }) {
return { message: metric(usage) }
}

static validate({ results }) {
if (Array.isArray(results))
throw new NotFound({ prettyMessage: 'not found' })
}

async fetch({ variant, name }) {
return this._requestJson({
schema,
url: `https://wikiapiary.com/w/api.php`,
options: {
qs: {
action: 'ask',
query: `[[${variant}:${name}]]|?Has_website_count`,
format: 'json',
},
},
})
}

async handle({ variant, name }) {
const response = await this.fetch({ variant, name })
const { results } = response.query

this.constructor.validate({ results })

const keyLowerCase = `${variant}:${name.toLowerCase()}`
const resultKey = Object.keys(results).find(
key => keyLowerCase === key.toLowerCase()
)

if (resultKey === undefined)
throw new NotFound({ prettyMessage: 'not found' })

const [usage] = results[resultKey].printouts['Has website count']
return this.constructor.render({ usage })
}
}
44 changes: 44 additions & 0 deletions services/wikiapiary/wikiapiary-installs.tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

const t = (module.exports = require('../tester').createServiceTester())
const { isMetric } = require('../test-validators')

t.create('Extension')
.get('/extension/installs/ParserFunctions.json')
.expectBadge({ label: 'installs', message: isMetric })

t.create('Skins')
.get('/skin/installs/Vector.json')
.expectBadge({ label: 'installs', message: isMetric })

t.create('Extension Not Found')
.get('/extension/installs/FakeExtensionThatDoesNotExist.json')
.expectBadge({ label: 'installs', message: 'not found' })

t.create('Name Lowercase')
.get('/extension/installs/parserfunctions.json')
.expectBadge({ label: 'installs', message: 'not found' })

t.create('Name Title Case')
.get('/extension/installs/parserFunctions.json')
.expectBadge({ label: 'installs', message: isMetric })

t.create('Malformed API Response')
.get('/extension/installs/ParserFunctions.json')
.intercept(nock =>
nock('https://wikiapiary.com')
.get('/w/api.php')
.query({
action: 'ask',
query: '[[extension:ParserFunctions]]|?Has_website_count',
format: 'json',
})
.reply(200, {
query: {
results: {
'Extension:Malformed': { printouts: { 'Has website count': [0] } },
},
},
})
)
.expectBadge({ label: 'installs', message: 'not found' })

0 comments on commit 23678fe

Please sign in to comment.