From 4a55c3eaa42d0e56970b825b41728aa3daa4245f Mon Sep 17 00:00:00 2001 From: Sepehr Safari Date: Thu, 11 Jan 2024 23:05:03 +0330 Subject: [PATCH] Add Support for [Nostr] Followers (#9870) * add nostr followers with tests * fix broken test * fix http error handler * rename route from nostr to nostr-band * remove unnecessary test cases * edit test expectation * validate data schema ensuring exact one key * remove unavailable named logo * migrate examples to openApi * Update services/nostr-band/nostr-band-followers.tester.js * remove unused import --------- Co-authored-by: chris48s Co-authored-by: chris48s --- .../nostr-band-followers.service.js | 67 +++++++++++++++++++ .../nostr-band/nostr-band-followers.tester.js | 15 +++++ 2 files changed, 82 insertions(+) create mode 100644 services/nostr-band/nostr-band-followers.service.js create mode 100644 services/nostr-band/nostr-band-followers.tester.js diff --git a/services/nostr-band/nostr-band-followers.service.js b/services/nostr-band/nostr-band-followers.service.js new file mode 100644 index 0000000000000..f9133e928e909 --- /dev/null +++ b/services/nostr-band/nostr-band-followers.service.js @@ -0,0 +1,67 @@ +import Joi from 'joi' +import { metric } from '../text-formatters.js' +import { BaseJsonService, pathParams } from '../index.js' + +const npubSchema = Joi.object({ + followers_pubkey_count: Joi.number().required(), +}).required() + +const mainSchema = Joi.object({ + stats: Joi.object() + .pattern(Joi.string(), npubSchema) + .min(1) + .max(1) + .required(), +}).required() + +export default class NostrBandFollowers extends BaseJsonService { + static category = 'social' + + static route = { + base: 'nostr-band/followers', + pattern: ':npub', + } + + static openApi = { + '/nostr-band/followers/{npub}': { + get: { + summary: 'Nostr.band Followers', + description: + 'Returns the number of followers for a Nostr pubkey using the Nostr.band API.', + parameters: pathParams({ + name: 'npub', + description: 'Nostr pubkey in (npub1...) format or hex.', + example: + 'npub18c556t7n8xa3df2q82rwxejfglw5przds7sqvefylzjh8tjne28qld0we7', + }), + }, + }, + } + + static defaultBadgeData = { label: 'followers' } + + static render({ followers }) { + return { + message: metric(followers), + style: 'social', + } + } + + async fetch({ npub }) { + const data = await this._requestJson({ + url: `https://api.nostr.band/v0/stats/profile/${npub}`, + schema: mainSchema, + httpErrors: { + 400: 'invalid pubkey', + }, + }) + const stats = data.stats + const firstKey = Object.keys(stats)[0] + return stats[firstKey].followers_pubkey_count + } + + async handle({ npub }) { + const followers = await this.fetch({ npub }) + return this.constructor.render({ followers }) + } +} diff --git a/services/nostr-band/nostr-band-followers.tester.js b/services/nostr-band/nostr-band-followers.tester.js new file mode 100644 index 0000000000000..1a85f8c337337 --- /dev/null +++ b/services/nostr-band/nostr-band-followers.tester.js @@ -0,0 +1,15 @@ +import { isMetric } from '../test-validators.js' +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() + +t.create('fetch: valid npub') + .get('/npub18c556t7n8xa3df2q82rwxejfglw5przds7sqvefylzjh8tjne28qld0we7.json') + .expectBadge({ + label: 'followers', + message: isMetric, + }) + +t.create('fetch: invalid npub').get('/invalidnpub.json').expectBadge({ + label: 'followers', + message: 'invalid pubkey', +})