analytics.mjs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { Model } from 'objection'
  2. import fs from 'node:fs/promises'
  3. import path from 'node:path'
  4. import { defaultTo, forOwn, isBoolean, replace, sortBy } from 'lodash-es'
  5. import yaml from 'js-yaml'
  6. import { parseModuleProps } from '../helpers/common.mjs'
  7. /**
  8. * Analytics model
  9. */
  10. export class Analytics extends Model {
  11. static get tableName() { return 'analytics' }
  12. static get jsonSchema () {
  13. return {
  14. type: 'object',
  15. required: ['module', 'isEnabled'],
  16. properties: {
  17. id: { type: 'string' },
  18. module: { type: 'string' },
  19. isEnabled: { type: 'boolean', default: false }
  20. }
  21. }
  22. }
  23. static get jsonAttributes() {
  24. return ['config']
  25. }
  26. static async getProviders(isEnabled) {
  27. const providers = await WIKI.db.analytics.query().where(isBoolean(isEnabled) ? { isEnabled } : {})
  28. return sortBy(providers, ['module'])
  29. }
  30. static async refreshProvidersFromDisk() {
  31. try {
  32. // -> Fetch definitions from disk
  33. const analyticsDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/analytics'))
  34. WIKI.data.analytics = []
  35. for (const dir of analyticsDirs) {
  36. const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/analytics', dir, 'definition.yml'), 'utf8')
  37. const defParsed = yaml.load(def)
  38. defParsed.key = dir
  39. defParsed.props = parseModuleProps(defParsed.props)
  40. WIKI.data.analytics.push(defParsed)
  41. WIKI.logger.debug(`Loaded analytics module definition ${dir}: [ OK ]`)
  42. }
  43. WIKI.logger.info(`Loaded ${WIKI.data.analytics.length} analytics module definitions: [ OK ]`)
  44. } catch (err) {
  45. WIKI.logger.error(`Failed to scan or load analytics providers: [ FAILED ]`)
  46. WIKI.logger.error(err)
  47. }
  48. }
  49. static async getCode ({ cache = false } = {}) {
  50. if (cache) {
  51. const analyticsCached = await WIKI.cache.get('analytics')
  52. if (analyticsCached) {
  53. return analyticsCached
  54. }
  55. }
  56. try {
  57. const analyticsCode = {
  58. head: '',
  59. bodyStart: '',
  60. bodyEnd: ''
  61. }
  62. const providers = await WIKI.db.analytics.getProviders(true)
  63. for (let provider of providers) {
  64. const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/analytics', provider.key, 'code.yml'), 'utf8')
  65. let code = yaml.safeLoad(def)
  66. code.head = defaultTo(code.head, '')
  67. code.bodyStart = defaultTo(code.bodyStart, '')
  68. code.bodyEnd = defaultTo(code.bodyEnd, '')
  69. forOwn(provider.config, (value, key) => {
  70. code.head = replace(code.head, new RegExp(`{{${key}}}`, 'g'), value)
  71. code.bodyStart = replace(code.bodyStart, `{{${key}}}`, value)
  72. code.bodyEnd = replace(code.bodyEnd, `{{${key}}}`, value)
  73. })
  74. analyticsCode.head += code.head
  75. analyticsCode.bodyStart += code.bodyStart
  76. analyticsCode.bodyEnd += code.bodyEnd
  77. }
  78. await WIKI.cache.set('analytics', analyticsCode, 300)
  79. return analyticsCode
  80. } catch (err) {
  81. WIKI.logger.warn('Error while getting analytics code: ', err)
  82. return {
  83. head: '',
  84. bodyStart: '',
  85. bodyEnd: ''
  86. }
  87. }
  88. }
  89. }