diff --git a/services/greasyfork/greasyfork-base.js b/services/greasyfork/greasyfork-base.js new file mode 100644 index 0000000000000..a9c474647c4a2 --- /dev/null +++ b/services/greasyfork/greasyfork-base.js @@ -0,0 +1,24 @@ +import Joi from 'joi' +import { nonNegativeInteger } from '../validators.js' +import { BaseJsonService } from '../index.js' + +const schema = Joi.object({ + daily_installs: nonNegativeInteger, + total_installs: nonNegativeInteger, + good_ratings: nonNegativeInteger, + ok_ratings: nonNegativeInteger, + bad_ratings: nonNegativeInteger, + version: Joi.string().required(), + license: Joi.string().allow(null).required(), +}).required() + +export default class BaseGreasyForkService extends BaseJsonService { + static defaultBadgeData = { label: 'greasy fork' } + + async fetch({ scriptId }) { + return this._requestJson({ + schema, + url: `https://greasyfork.org/scripts/${scriptId}.json`, + }) + } +} diff --git a/services/greasyfork/greasyfork-downloads.service.js b/services/greasyfork/greasyfork-downloads.service.js new file mode 100644 index 0000000000000..cc6f6ce3adf25 --- /dev/null +++ b/services/greasyfork/greasyfork-downloads.service.js @@ -0,0 +1,35 @@ +import { renderDownloadsBadge } from '../downloads.js' +import BaseGreasyForkService from './greasyfork-base.js' + +export default class GreasyForkInstalls extends BaseGreasyForkService { + static category = 'downloads' + static route = { base: 'greasyfork', pattern: ':variant(dt|dd)/:scriptId' } + + static examples = [ + { + title: 'Greasy Fork', + pattern: 'dd/:scriptId', + namedParams: { scriptId: '407466' }, + staticPreview: renderDownloadsBadge({ downloads: 17 }), + }, + { + title: 'Greasy Fork', + pattern: 'dt/:scriptId', + namedParams: { scriptId: '407466' }, + staticPreview: renderDownloadsBadge({ downloads: 3420 }), + }, + ] + + static defaultBadgeData = { label: 'installs' } + + async handle({ variant, scriptId }) { + const data = await this.fetch({ scriptId }) + if (variant === 'dd') { + const downloads = data.daily_installs + const interval = 'day' + return renderDownloadsBadge({ downloads, interval }) + } + const downloads = data.total_installs + return renderDownloadsBadge({ downloads }) + } +} diff --git a/services/greasyfork/greasyfork-downloads.tester.js b/services/greasyfork/greasyfork-downloads.tester.js new file mode 100644 index 0000000000000..dc69e7c1cbaf3 --- /dev/null +++ b/services/greasyfork/greasyfork-downloads.tester.js @@ -0,0 +1,19 @@ +import { createServiceTester } from '../tester.js' +import { isMetric, isMetricOverTimePeriod } from '../test-validators.js' +export const t = await createServiceTester() + +t.create('Daily Installs') + .get('/dd/407466.json') + .expectBadge({ label: 'installs', message: isMetricOverTimePeriod }) + +t.create('Daily Installs (not found)') + .get('/dd/000000.json') + .expectBadge({ label: 'installs', message: 'not found' }) + +t.create('Total Installs') + .get('/dt/407466.json') + .expectBadge({ label: 'installs', message: isMetric }) + +t.create('Total Installs (not found)') + .get('/dt/000000.json') + .expectBadge({ label: 'installs', message: 'not found' }) diff --git a/services/greasyfork/greasyfork-license.service.js b/services/greasyfork/greasyfork-license.service.js new file mode 100644 index 0000000000000..895b3a97a6c77 --- /dev/null +++ b/services/greasyfork/greasyfork-license.service.js @@ -0,0 +1,34 @@ +import { renderLicenseBadge } from '../licenses.js' +import { InvalidResponse } from '../index.js' +import BaseGreasyForkService from './greasyfork-base.js' + +export default class GreasyForkLicense extends BaseGreasyForkService { + static category = 'license' + static route = { base: 'greasyfork', pattern: 'l/:scriptId' } + + static examples = [ + { + title: 'Greasy Fork', + namedParams: { scriptId: '407466' }, + staticPreview: renderLicenseBadge({ licenses: ['MIT'] }), + }, + ] + + static defaultBadgeData = { label: 'license' } + + transform({ data }) { + if (data.license === null) { + throw new InvalidResponse({ + prettyMessage: 'license not found', + }) + } + // remove suffix " License" from data.license + return { license: data.license.replace(/ License$/, '') } + } + + async handle({ scriptId }) { + const data = await this.fetch({ scriptId }) + const { license } = this.transform({ data }) + return renderLicenseBadge({ licenses: [license] }) + } +} diff --git a/services/greasyfork/greasyfork-license.tester.js b/services/greasyfork/greasyfork-license.tester.js new file mode 100644 index 0000000000000..bf410b73e18c1 --- /dev/null +++ b/services/greasyfork/greasyfork-license.tester.js @@ -0,0 +1,11 @@ +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() + +t.create('License (valid)').get('/l/407466.json').expectBadge({ + label: 'license', + message: 'MIT', +}) + +t.create('License (not found)') + .get('/l/000000.json') + .expectBadge({ label: 'license', message: 'not found' }) diff --git a/services/greasyfork/greasyfork-version.service.js b/services/greasyfork/greasyfork-version.service.js new file mode 100644 index 0000000000000..9759703d6a357 --- /dev/null +++ b/services/greasyfork/greasyfork-version.service.js @@ -0,0 +1,20 @@ +import { renderVersionBadge } from '../version.js' +import BaseGreasyForkService from './greasyfork-base.js' + +export default class GreasyForkVersion extends BaseGreasyForkService { + static category = 'version' + static route = { base: 'greasyfork', pattern: 'v/:scriptId' } + + static examples = [ + { + title: 'Greasy Fork', + namedParams: { scriptId: '407466' }, + staticPreview: renderVersionBadge({ version: '3.9.3' }), + }, + ] + + async handle({ scriptId }) { + const data = await this.fetch({ scriptId }) + return renderVersionBadge({ version: data.version }) + } +} diff --git a/services/greasyfork/greasyfork-version.tester.js b/services/greasyfork/greasyfork-version.tester.js new file mode 100644 index 0000000000000..d4c2877dd4736 --- /dev/null +++ b/services/greasyfork/greasyfork-version.tester.js @@ -0,0 +1,12 @@ +import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js' +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() + +t.create('Version').get('/v/407466.json').expectBadge({ + label: 'greasy fork', + message: isVPlusDottedVersionAtLeastOne, +}) + +t.create('Version (not found)') + .get('/v/000000.json') + .expectBadge({ label: 'greasy fork', message: 'not found' })