diff --git a/services/revolt/revolt.service.js b/services/revolt/revolt.service.js new file mode 100644 index 0000000000000..e43763e5b722f --- /dev/null +++ b/services/revolt/revolt.service.js @@ -0,0 +1,79 @@ +import Joi from 'joi' +import { BaseJsonService, pathParam, queryParam } from '../index.js' +import { nonNegativeInteger, optionalUrl } from '../validators.js' + +const schema = Joi.object({ + member_count: nonNegativeInteger, +}).required() + +const description = ` +The Revolt badge requires an INVITE CODE to access the Revolt API, +which can be located at the end of the invitation url. + +For example, both +https://app.revolt.chat/invite/01F7ZSBSFHQ8TA81725KQCSDDP and +https://rvlt.gg/01F7ZSBSFHQ8TA81725KQCSDDP contains an invite code +of 01F7ZSBSFHQ8TA81725KQCSDDP. +` + +const queryParamSchema = Joi.object({ + revolt_api_url: optionalUrl, +}).required() + +export default class RevoltServerInvite extends BaseJsonService { + static category = 'chat' + + static route = { + base: 'revolt/invite', + pattern: ':inviteId', + queryParamSchema, + } + + static openApi = { + '/revolt/invite/{inviteId}': { + get: { + summary: 'Revolt', + description, + parameters: [ + pathParam({ + name: 'inviteId', + example: '01F7ZSBSFHQ8TA81725KQCSDDP', + }), + queryParam({ + name: 'revolt_api_url', + example: 'https://api.revolt.chat', + }), + ], + }, + }, + } + + static defaultBadgeData = { label: 'chat' } + + static render({ memberCount }) { + return { + message: `${memberCount} members`, + color: 'brightgreen', + } + } + + async fetch({ inviteId, baseUrl }) { + return this._requestJson({ + schema, + url: `${baseUrl}/invites/${inviteId}`, + }) + } + + async handle( + { inviteId }, + { revolt_api_url: baseUrl = 'https://api.revolt.chat' }, + ) { + const { member_count: memberCount } = await this.fetch({ + inviteId, + baseUrl, + }) + return this.constructor.render({ + memberCount, + }) + } +} diff --git a/services/revolt/revolt.tester.js b/services/revolt/revolt.tester.js new file mode 100644 index 0000000000000..aa7a046e957c2 --- /dev/null +++ b/services/revolt/revolt.tester.js @@ -0,0 +1,26 @@ +import Joi from 'joi' +import { createServiceTester } from '../tester.js' + +export const t = await createServiceTester() + +t.create('get status of #revolt') + .get('/01F7ZSBSFHQ8TA81725KQCSDDP.json') + .expectBadge({ + label: 'chat', + message: Joi.string().regex(/^[0-9]+ members$/), + color: 'brightgreen', + }) + +t.create('custom api url') + .get( + '/01F7ZSBSFHQ8TA81725KQCSDDP.json?revolt_api_url=https://api.revolt.chat', + ) + .expectBadge({ + label: 'chat', + message: Joi.string().regex(/^[0-9]+ members$/), + color: 'brightgreen', + }) + +t.create('invalid invite code') + .get('/12345.json') + .expectBadge({ label: 'chat', message: 'not found' })