bbb.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { Request, ParamsDictionary, server } from "./deps.ts";
  2. import { createHash } from "https://deno.land/std@0.87.0/hash/mod.ts";
  3. export class BBB {
  4. call: string
  5. checksum_incoming: string
  6. query: string
  7. params: string
  8. meeting_id: string
  9. url: string
  10. constructor (req: Request<ParamsDictionary, any, any>) {
  11. this.call = req.params.call
  12. this.checksum_incoming = req.query.checksum
  13. this.query = req._parsedUrl?.query || ""
  14. this.params = this.query.replace(/[?|&]checksum.*$/, '')
  15. this.meeting_id = req.query.meetingID
  16. this.url = req.originalUrl
  17. console.log(`New call to ${this.call}`)
  18. }
  19. // generate a checksum for various calls
  20. generate_checksum = (secret: string, call: string = this.call, params: string = this.params) => {
  21. const hash = createHash("sha1");
  22. hash.update(`${call}${params}${secret}`)
  23. return hash.toString()
  24. }
  25. // generate a url to check if meeting is available
  26. check_for_meeting_query = (server: server) => {
  27. const checksum = this.generate_checksum(server.secret, 'getMeetingInfo', `meetingID=${this.meeting_id}`)
  28. return `${server.host}/bigbluebutton/api/getMeetingInfo?meetingID=${this.meeting_id}&checksum=${checksum}`
  29. }
  30. // write new query for target bbb server
  31. rewritten_query = (server: server) => {
  32. const checksum_outgoing = this.generate_checksum(server.secret)
  33. return `${server.host}/${this.url.replace(this.checksum_incoming, checksum_outgoing)}`
  34. }
  35. // check if request is autheticated with correct checksum
  36. authenticated = (secret: string) => {
  37. const checksum = this.generate_checksum(secret)
  38. console.log(`Rejected incoming call to ${this.call}`)
  39. return checksum === this.checksum_incoming
  40. }
  41. find_meeting_id = (servers: server[]): Promise<server> => {
  42. if (!this.meeting_id) throw Error
  43. const promises = servers.map(async s => {
  44. const res = await fetch(this.check_for_meeting_query(s))
  45. if (!res.ok) throw Error
  46. const text = await res.text()
  47. if (text.includes(this.meeting_id)) return s
  48. else throw Error
  49. })
  50. return Promise.any(promises)
  51. }
  52. }