Refactor [wordpress] downloads and add interval to theme downloads (#4180)
Refactor wordpress downloads service Also add interval for theme downloads
This commit is contained in:
@@ -4,7 +4,7 @@ const Joi = require('@hapi/joi')
|
||||
const { metric } = require('../text-formatters')
|
||||
const { downloadCount } = require('../color-formatters')
|
||||
const BaseWordpress = require('./wordpress-base')
|
||||
const { BaseJsonService, NotFound } = require('..')
|
||||
const { NotFound } = require('..')
|
||||
|
||||
const dateSchema = Joi.object()
|
||||
.pattern(Joi.date().iso(), Joi.number().integer())
|
||||
@@ -21,6 +21,29 @@ const extensionData = {
|
||||
},
|
||||
}
|
||||
|
||||
const intervalMap = {
|
||||
dd: {
|
||||
limit: 1,
|
||||
messageSuffix: '/day',
|
||||
},
|
||||
dw: {
|
||||
limit: 7,
|
||||
messageSuffix: '/week',
|
||||
},
|
||||
dm: {
|
||||
limit: 30,
|
||||
messageSuffix: '/month',
|
||||
},
|
||||
dy: {
|
||||
limit: 365,
|
||||
messageSuffix: '/year',
|
||||
},
|
||||
dt: {
|
||||
limit: null,
|
||||
messageSuffix: '',
|
||||
},
|
||||
}
|
||||
|
||||
function DownloadsForExtensionType(extensionType) {
|
||||
const { capt, exampleSlug } = extensionData[extensionType]
|
||||
|
||||
@@ -35,8 +58,8 @@ function DownloadsForExtensionType(extensionType) {
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: `wordpress/${extensionType}/dt`,
|
||||
pattern: ':slug',
|
||||
base: `wordpress/${extensionType}`,
|
||||
pattern: ':interval(dd|dw|dm|dy|dt)/:slug',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +67,8 @@ function DownloadsForExtensionType(extensionType) {
|
||||
return [
|
||||
{
|
||||
title: `WordPress ${capt} Downloads`,
|
||||
namedParams: { slug: exampleSlug },
|
||||
staticPreview: this.render({ downloads: 200000 }),
|
||||
namedParams: { interval: 'dm', slug: exampleSlug },
|
||||
staticPreview: this.render({ interval: 'dm', downloads: 200000 }),
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -54,19 +77,50 @@ function DownloadsForExtensionType(extensionType) {
|
||||
return { label: 'downloads' }
|
||||
}
|
||||
|
||||
static render({ downloads }) {
|
||||
static render({ interval, downloads }) {
|
||||
const { messageSuffix } = intervalMap[interval]
|
||||
|
||||
return {
|
||||
message: metric(downloads),
|
||||
message: `${metric(downloads)}${messageSuffix}`,
|
||||
color: downloadCount(downloads),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ slug }) {
|
||||
const { downloaded: downloads } = await this.fetch({
|
||||
extensionType,
|
||||
slug,
|
||||
})
|
||||
return this.constructor.render({ downloads })
|
||||
async handle({ interval, slug }) {
|
||||
const { limit } = intervalMap[interval]
|
||||
let downloads
|
||||
if (limit === null) {
|
||||
const { downloaded: _downloads } = await this.fetch({
|
||||
extensionType,
|
||||
slug,
|
||||
})
|
||||
downloads = _downloads
|
||||
} else {
|
||||
const ext_type = extensionType === 'plugin' ? 'plugin' : 'themes'
|
||||
const json = await this._requestJson({
|
||||
schema: dateSchema,
|
||||
url: `https://api.wordpress.org/stats/${ext_type}/1.0/downloads.php`,
|
||||
options: {
|
||||
qs: {
|
||||
slug,
|
||||
limit,
|
||||
},
|
||||
},
|
||||
})
|
||||
const size = Object.keys(json).length
|
||||
downloads = Object.values(json).reduce(
|
||||
(a, b) => parseInt(a) + parseInt(b)
|
||||
)
|
||||
// This check is for non-existent and brand-new plugins both having new stats.
|
||||
// Non-Existent plugins results are the same as a brandspanking new plugin with no downloads.
|
||||
if (downloads <= 0 && size <= 1) {
|
||||
throw new NotFound({
|
||||
prettyMessage: `${extensionType} not found or too new`,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return this.constructor.render({ interval, downloads })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,100 +175,7 @@ function InstallsForExtensionType(extensionType) {
|
||||
}
|
||||
}
|
||||
|
||||
function DownloadsForInterval(interval) {
|
||||
const { base, messageSuffix = '', query, name } = {
|
||||
day: {
|
||||
base: 'wordpress/plugin/dd',
|
||||
messageSuffix: '/day',
|
||||
query: 1,
|
||||
name: 'WordpressDownloadsDay',
|
||||
},
|
||||
week: {
|
||||
base: 'wordpress/plugin/dw',
|
||||
messageSuffix: '/week',
|
||||
query: 7,
|
||||
name: 'WordpressDownloadsWeek',
|
||||
},
|
||||
month: {
|
||||
base: 'wordpress/plugin/dm',
|
||||
messageSuffix: '/month',
|
||||
query: 30,
|
||||
name: 'WordpressDownloadsMonth',
|
||||
},
|
||||
year: {
|
||||
base: 'wordpress/plugin/dy',
|
||||
messageSuffix: '/year',
|
||||
query: 365,
|
||||
name: 'WordpressDownloadsYear',
|
||||
},
|
||||
}[interval]
|
||||
|
||||
return class WordpressDownloads extends BaseJsonService {
|
||||
static get name() {
|
||||
return name
|
||||
}
|
||||
|
||||
static get category() {
|
||||
return 'downloads'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base,
|
||||
pattern: ':slug',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'WordPress Plugin Downloads',
|
||||
namedParams: { slug: 'bbpress' },
|
||||
staticPreview: this.render({ downloads: 30000 }),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static get defaultBadgeData() {
|
||||
return { label: 'downloads' }
|
||||
}
|
||||
|
||||
static render({ downloads }) {
|
||||
return {
|
||||
message: `${metric(downloads)}${messageSuffix}`,
|
||||
color: downloadCount(downloads),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ slug }) {
|
||||
const json = await this._requestJson({
|
||||
schema: dateSchema,
|
||||
url: `https://api.wordpress.org/stats/plugin/1.0/downloads.php`,
|
||||
options: {
|
||||
qs: {
|
||||
slug,
|
||||
limit: query,
|
||||
},
|
||||
},
|
||||
})
|
||||
const size = Object.keys(json).length
|
||||
const downloads = Object.values(json).reduce(
|
||||
(a, b) => parseInt(a) + parseInt(b)
|
||||
)
|
||||
// This check is for non-existent and brand-new plugins both having new stats.
|
||||
// Non-Existent plugins results are the same as a brandspanking new plugin with no downloads.
|
||||
if (downloads <= 0 && size <= 1) {
|
||||
throw new NotFound({ prettyMessage: 'plugin not found or too new' })
|
||||
}
|
||||
return this.constructor.render({ downloads })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const intervalServices = ['day', 'week', 'month', 'year'].map(
|
||||
DownloadsForInterval
|
||||
)
|
||||
const downloadServices = ['plugin', 'theme'].map(DownloadsForExtensionType)
|
||||
const installServices = ['plugin', 'theme'].map(InstallsForExtensionType)
|
||||
const modules = [...intervalServices, ...downloadServices, ...installServices]
|
||||
const modules = [...downloadServices, ...installServices]
|
||||
module.exports = modules
|
||||
|
||||
@@ -15,6 +15,7 @@ t.create('Plugin Downloads - Total')
|
||||
label: 'downloads',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Plugin Downloads - Active')
|
||||
.get('/plugin/installs/akismet.json')
|
||||
.expectBadge({
|
||||
@@ -43,12 +44,20 @@ t.create('Plugin Downloads - Month')
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Plugin Downloads - Year')
|
||||
.get('/plugin/dy/akismet.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Total')
|
||||
.get('/theme/dt/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Active')
|
||||
.get('/theme/installs/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
@@ -56,12 +65,41 @@ t.create('Theme Downloads - Active')
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Day')
|
||||
.get('/theme/dd/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Week')
|
||||
.get('/theme/dw/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Month')
|
||||
.get('/theme/dm/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Year')
|
||||
.get('/theme/dy/twentyseventeen.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetricOverTimePeriod,
|
||||
})
|
||||
|
||||
t.create('Plugin Downloads - Total | Not Found')
|
||||
.get('/plugin/dt/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'not found',
|
||||
})
|
||||
|
||||
t.create('Plugin Downloads - Active | Not Found')
|
||||
.get('/plugin/installs/100.json')
|
||||
.expectBadge({
|
||||
@@ -90,15 +128,51 @@ t.create('Plugin Downloads - Month | Not Found')
|
||||
message: 'plugin not found or too new',
|
||||
})
|
||||
|
||||
t.create('Plugin Downloads - Year | Not Found')
|
||||
.get('/plugin/dy/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'plugin not found or too new',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Total | Not Found')
|
||||
.get('/theme/dt/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'not found',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Active | Not Found')
|
||||
.get('/theme/installs/100.json')
|
||||
.expectBadge({
|
||||
label: 'active installs',
|
||||
message: 'not found',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Day | Not Found')
|
||||
.get('/theme/dd/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'theme not found or too new',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Week | Not Found')
|
||||
.get('/theme/dw/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'theme not found or too new',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Month | Not Found')
|
||||
.get('/theme/dm/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'theme not found or too new',
|
||||
})
|
||||
|
||||
t.create('Theme Downloads - Year | Not Found')
|
||||
.get('/theme/dy/100.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'theme not found or too new',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user