kopia lustrzana https://github.com/badgen/badgen.net
feat(matrix): introduce Gitter and Matrix member count badges (#500)
* feat: add Gitter members badge * feat: add Matrix members badge with Gitter fallback * docs(matrix): update examples * perf(matrix): fail fast if room does NOT exist * style(gitter): tweak scrapping patternpull/506/head
rodzic
44a9a2f1df
commit
df1e40cb1e
|
@ -0,0 +1,39 @@
|
||||||
|
import got from '../libs/got'
|
||||||
|
import { millify } from '../libs/utils'
|
||||||
|
import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler'
|
||||||
|
|
||||||
|
const BRAND_COLOR = 'ED1965'
|
||||||
|
|
||||||
|
export default createBadgenHandler({
|
||||||
|
title: 'Gitter',
|
||||||
|
examples: {
|
||||||
|
'/gitter/members/redom/lobby': 'members',
|
||||||
|
'/gitter/members/redom/redom': 'members'
|
||||||
|
},
|
||||||
|
handlers: {
|
||||||
|
'/gitter/members/:org/:room': handler
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handler ({ org, room }: PathArgs) {
|
||||||
|
const membersCount = await fetchMembersCount(org, room)
|
||||||
|
if (Number.isNaN(membersCount)) {
|
||||||
|
return {
|
||||||
|
subject: 'gitter',
|
||||||
|
status: 'unknown',
|
||||||
|
color: 'grey'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const suffix = membersCount === 1 ? 'member' : 'members'
|
||||||
|
return {
|
||||||
|
subject: 'gitter',
|
||||||
|
status: `${millify(membersCount)} ${suffix}`,
|
||||||
|
color: BRAND_COLOR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchMembersCount(org: string, room: string) {
|
||||||
|
const html = await got(`https://gitter.im/${org}/${room}`).text()
|
||||||
|
return Number(html.match(/"userCount"\s*:\s*(\d+)/)?.[1])
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { Got } from 'got'
|
||||||
|
import got from '../libs/got'
|
||||||
|
import { millify } from '../libs/utils'
|
||||||
|
import { fetchMembersCount as fetchGitterMembersCount } from './gitter'
|
||||||
|
import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler'
|
||||||
|
|
||||||
|
const BRAND_COLOR = 'black'
|
||||||
|
|
||||||
|
export default createBadgenHandler({
|
||||||
|
title: 'Matrix',
|
||||||
|
examples: {
|
||||||
|
'/matrix/members/rust/matrix.org': 'members',
|
||||||
|
'/matrix/members/thisweekinmatrix': 'members',
|
||||||
|
'/matrix/members/archlinux/archlinux.org': 'members',
|
||||||
|
'/matrix/members/redom_redom/gitter.im': 'members'
|
||||||
|
},
|
||||||
|
handlers: {
|
||||||
|
'/matrix/members/:room/:server?': handler
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handler ({ room, server = 'matrix.org' }: PathArgs) {
|
||||||
|
const roomName = room.replace(/^#/, '')
|
||||||
|
const membersCount = await fetchMembersCount(roomName, server)
|
||||||
|
if (Number.isNaN(membersCount)) {
|
||||||
|
return {
|
||||||
|
subject: 'matrix',
|
||||||
|
status: 'unknown',
|
||||||
|
color: 'grey'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = [
|
||||||
|
millify(membersCount),
|
||||||
|
server === 'gitter.im' ? 'gitter' : '',
|
||||||
|
membersCount === 1 ? 'member' : 'members'
|
||||||
|
].join(' ')
|
||||||
|
|
||||||
|
return {
|
||||||
|
subject: `#${roomName}:${server}`,
|
||||||
|
status,
|
||||||
|
color: BRAND_COLOR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchMembersCount(roomName: string, server: string) {
|
||||||
|
if (server === 'gitter.im') {
|
||||||
|
const [gitterOrg, gitterRoom] = roomName.split('_')
|
||||||
|
return fetchGitterMembersCount(gitterOrg, gitterRoom)
|
||||||
|
}
|
||||||
|
const homeserver = await getHomeserver(server)
|
||||||
|
const client = got.extend({ prefixUrl: `${homeserver}/_matrix/client/r0` })
|
||||||
|
const roomAlias = `#${roomName}:${server}`
|
||||||
|
const room = await findPublicRoom(client, roomAlias)
|
||||||
|
return room?.num_joined_members
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://matrix.org/docs/spec/client_server/latest#get-well-known-matrix-client
|
||||||
|
async function getHomeserver(server: string) {
|
||||||
|
const endpoint = `https://${server}/.well-known/matrix/client`
|
||||||
|
const { 'm.homeserver': homeserver } = await got(endpoint).json<any>()
|
||||||
|
return homeserver?.base_url
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms
|
||||||
|
async function findPublicRoom(client: Got, roomAlias: string) {
|
||||||
|
const roomId = await getRoomId(client, roomAlias)
|
||||||
|
const searchParams = new URLSearchParams({ limit: '500' })
|
||||||
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
|
const { chunk, next_batch } = await client.get('publicRooms', { searchParams }).json<any>()
|
||||||
|
const room = chunk.find(it => it.room_id === roomId)
|
||||||
|
if (room) return room
|
||||||
|
if (!next_batch) return
|
||||||
|
searchParams.set('since', next_batch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-directory-room-roomalias
|
||||||
|
async function getRoomId(client: Got, roomAlias: string) {
|
||||||
|
const endpoint = `directory/room/${encodeURIComponent(roomAlias)}`
|
||||||
|
const { room_id } = await client.get(endpoint).json<any>()
|
||||||
|
return room_id
|
||||||
|
}
|
|
@ -61,6 +61,9 @@ export const liveBadgeList = [
|
||||||
// social
|
// social
|
||||||
'devrant',
|
'devrant',
|
||||||
'peertube',
|
'peertube',
|
||||||
|
// chat
|
||||||
|
'gitter',
|
||||||
|
'matrix',
|
||||||
// utilities
|
// utilities
|
||||||
'opencollective',
|
'opencollective',
|
||||||
'keybase',
|
'keybase',
|
||||||
|
|
Ładowanie…
Reference in New Issue