From 440947c9a8d10edaec69bc7afb9b362b323d2370 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 17 Sep 2023 14:41:40 +0800 Subject: [PATCH] feat: add basic telemetry api --- package.json | 1 + pnpm-lock.yaml | 25 +++++++++++++++++++++++ src/server/main.ts | 2 ++ src/server/router/telemetry.ts | 37 ++++++++++++++++++++++++++++++++++ src/server/utils/common.ts | 32 +++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 src/server/router/telemetry.ts diff --git a/package.json b/package.json index d2a7ca8..b7bc352 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "maxmind": "^4.3.11", "morgan": "^1.10.0", "nanoid": "^3.3.6", + "openbadge": "^1.0.4", "passport": "^0.6.0", "passport-jwt": "^4.0.1", "react": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0048f69..a330e93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -73,6 +73,9 @@ dependencies: nanoid: specifier: ^3.3.6 version: 3.3.6 + openbadge: + specifier: ^1.0.4 + version: 1.0.4 passport: specifier: ^0.6.0 version: 0.6.0 @@ -3827,6 +3830,10 @@ packages: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} dev: false + /lodash@3.10.1: + resolution: {integrity: sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==} + dev: false + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false @@ -4199,6 +4206,20 @@ packages: dependencies: wrappy: 1.0.2 + /openbadge@1.0.4: + resolution: {integrity: sha512-A/yslJpnCgQPPo8sYYDTymAiDfuZI9AzpwuOQdbc0ZIbTcL4BsuVQm2BV63jEiDVatlz4kcFX8Y36hloEuFhGA==} + dependencies: + lodash: 3.10.1 + opentype.js: 0.6.9 + dev: false + + /opentype.js@0.6.9: + resolution: {integrity: sha512-H8TkPyysd95WFQcgBpOoyZA0y6rf5b7iC5Y4ABwHi7ZMc0dqdgwOIeKMh7+rU2SG492Y+6eqJ4uOxLTBVkixjw==} + hasBin: true + dependencies: + tiny-inflate: 1.0.3 + dev: false + /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -5716,6 +5737,10 @@ packages: resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} dev: false + /tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + dev: false + /tiny-lru@11.0.1: resolution: {integrity: sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==} engines: {node: '>=12'} diff --git a/src/server/main.ts b/src/server/main.ts index 8a9d049..ccce869 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -9,6 +9,7 @@ import morgan from 'morgan'; import { userRouter } from './router/user'; import { websiteRouter } from './router/website'; import { workspaceRouter } from './router/workspace'; +import { telemetryRouter } from './router/telemetry'; const port = Number(process.env.PORT || 12345); @@ -25,6 +26,7 @@ app.disable('x-powered-by'); app.use('/api/user', userRouter); app.use('/api/website', websiteRouter); app.use('/api/workspace', workspaceRouter); +app.use('/api/telemetry', telemetryRouter); app.use((err: any, req: any, res: any, next: any) => { console.error(err); diff --git a/src/server/router/telemetry.ts b/src/server/router/telemetry.ts new file mode 100644 index 0000000..14261e1 --- /dev/null +++ b/src/server/router/telemetry.ts @@ -0,0 +1,37 @@ +import { Router } from 'express'; +import { numify } from '../utils/common'; +const openBadge = require('openbadge'); + +export const telemetryRouter = Router(); + +telemetryRouter.get('/blank.gif', async (req, res) => { + const buffer = Buffer.from( + 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', + 'base64' + ); + + res.header('Content-Type', 'image/gif').send(buffer); +}); + +telemetryRouter.get('/badge.svg', async (req, res) => { + const title = req.query.title || 'visitor'; + + const num = numify(11123243); + + const svg = await new Promise((resolve, reject) => { + openBadge( + { + text: [title, num], + }, + (err: any, badgeSvg: string) => { + if (err) { + reject(err); + } else { + resolve(badgeSvg); + } + } + ); + }); + + res.header('Content-Type', 'image/svg+xml').send(svg); +}); diff --git a/src/server/utils/common.ts b/src/server/utils/common.ts index 6e231e3..f93a274 100644 --- a/src/server/utils/common.ts +++ b/src/server/utils/common.ts @@ -218,3 +218,35 @@ export function getMinimumUnit(startDate: Date, endDate: Date) { return 'year'; } + +/** + * fork from https://github.com/mcnaveen/numify/blob/main/src/index.ts + */ +export function numify(num: number): string { + num = Number(num.toString().replace(/[^0-9.]/g, '')); + if (num < 1000) { + return String(num); + } + + let si = [ + { v: 1e3, s: 'k' }, + { v: 1e6, s: 'M' }, + { v: 1e9, s: 'B' }, + { v: 1e12, s: 'T' }, + { v: 1e15, s: 'P' }, + { v: 1e18, s: 'E' }, + ]; + + let index; + for (index = si.length - 1; index > 0; index--) { + if (num >= si[index].v) { + break; + } + } + const result: string = ( + (num / si[index].v).toFixed(2).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + + si[index].s + ).toString(); + + return result; +}