From 2d2d9ec54eb75866274b496398aa6deba3d2bca4 Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Sat, 28 Aug 2021 01:26:21 +0200 Subject: [PATCH] feat: add freecodecamp badge --- .../freecodecamp-points.service.js | 70 +++++++++++++++++++ .../freecodecamp-points.tester.js | 15 ++++ 2 files changed, 85 insertions(+) create mode 100644 services/freecodecamp/freecodecamp-points.service.js create mode 100644 services/freecodecamp/freecodecamp-points.tester.js diff --git a/services/freecodecamp/freecodecamp-points.service.js b/services/freecodecamp/freecodecamp-points.service.js new file mode 100644 index 0000000000000..8ec55b5aa4fa8 --- /dev/null +++ b/services/freecodecamp/freecodecamp-points.service.js @@ -0,0 +1,70 @@ +import Joi from 'joi' +import { metric } from '../text-formatters.js' +import { BaseJsonService, InvalidResponse, NotFound } from '../index.js' + +const schema = Joi.object({ + entities: Joi.object({ + user: Joi.object() + .required() + .pattern(/^\w+$/, { + points: Joi.number().allow(null).required(), + }), + }).optional(), +}).required() + +/** + * This badge displays the total number of points a student has accumulated + * from completing challenges on freeCodeCamp. + */ +export default class FreeCodeCampPoints extends BaseJsonService { + static category = 'other' + static route = { + base: 'freecodecamp/points', + pattern: ':username', + } + + static examples = [ + { + title: 'freeCodeCamp points', + namedParams: { username: 'sethi' }, + staticPreview: this.render({ points: 934 }), + }, + ] + + static defaultBadgeData = { label: 'points', color: 'info' } + + static render({ points }) { + return { message: metric(points) } + } + + async fetch({ username }) { + return this._requestJson({ + schema, + url: `https://api.freecodecamp.org/api/users/get-public-profile`, + options: { + qs: { + username, + }, + }, + }) + } + + static transform(response, username) { + const { entities } = response + + if (entities === undefined) + throw new NotFound({ prettyMessage: 'profile not found' }) + + const { points } = entities.user[username] + + if (points === null) throw new InvalidResponse({ prettyMessage: 'private' }) + + return points + } + + async handle({ username }) { + const response = await this.fetch({ username }) + const points = this.constructor.transform(response, username) + return this.constructor.render({ points }) + } +} diff --git a/services/freecodecamp/freecodecamp-points.tester.js b/services/freecodecamp/freecodecamp-points.tester.js new file mode 100644 index 0000000000000..e228f13752ca3 --- /dev/null +++ b/services/freecodecamp/freecodecamp-points.tester.js @@ -0,0 +1,15 @@ +import { createServiceTester } from '../tester.js' +import { isMetric } from '../test-validators.js' +export const t = await createServiceTester() + +t.create('Total Points Valid') + .get('/sethi.json') + .expectBadge({ label: 'points', message: isMetric }) + +t.create('Total Points Private') + .get('/set.json') + .expectBadge({ label: 'points', message: 'private' }) + +t.create('Total Points Invalid') + .get('/invalid@username.json') + .expectBadge({ label: 'points', message: 'profile not found' })