| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | const md = require('markdown-it')const mdEmoji = require('markdown-it-emoji')const { JSDOM } = require('jsdom')const createDOMPurify = require('dompurify')const _ = require('lodash')const { AkismetClient } = require('akismet-api')const moment = require('moment')/* global WIKI */const window = new JSDOM('').windowconst DOMPurify = createDOMPurify(window)let akismetClient = nullconst mkdown = md({  html: false,  breaks: true,  linkify: true,  highlight(str, lang) {    return `<pre><code class="language-${lang}">${_.escape(str)}</code></pre>`  }})mkdown.use(mdEmoji)// ------------------------------------// Default Comment Provider// ------------------------------------module.exports = {  /**   * Init   */  async init (config) {    WIKI.logger.info('(COMMENTS/DEFAULT) Initializing...')    if (WIKI.data.commentProvider.config.akismet && WIKI.data.commentProvider.config.akismet.length > 2) {      akismetClient = new AkismetClient({        key: WIKI.data.commentProvider.config.akismet,        blog: WIKI.config.host,        lang: WIKI.config.lang.namespacing ? WIKI.config.lang.namespaces.join(', ') : WIKI.config.lang.code,        charset: 'UTF-8'      })      try {        const isValid = await akismetClient.verifyKey()        if (!isValid) {          akismetClient = null          WIKI.logger.warn('(COMMENTS/DEFAULT) Akismet Key is invalid! [ DISABLED ]')        } else {          WIKI.logger.info('(COMMENTS/DEFAULT) Akismet key is valid. [ OK ]')        }      } catch (err) {        akismetClient = null        WIKI.logger.warn('(COMMENTS/DEFAULT) Unable to verify Akismet Key: ' + err.message)      }    } else {      akismetClient = null    }    WIKI.logger.info('(COMMENTS/DEFAULT) Initialization completed.')  },  /**   * Create New Comment   */  async create ({ page, replyTo, content, user }) {    // -> Build New Comment    const newComment = {      content,      render: DOMPurify.sanitize(mkdown.render(content)),      replyTo,      pageId: page.id,      authorId: user.id,      name: user.name,      email: user.email,      ip: user.ip    }    // -> Check for Spam with Akismet    if (akismetClient) {      let userRole = 'user'      if (user.groups.indexOf(1) >= 0) {        userRole = 'administrator'      } else if (user.groups.indexOf(2) >= 0) {        userRole = 'guest'      }      let isSpam = false      try {        isSpam = await akismetClient.checkSpam({          ip: user.ip,          useragent: user.agentagent,          content,          name: user.name,          email: user.email,          permalink: `${WIKI.config.host}/${page.localeCode}/${page.path}`,          permalinkDate: page.updatedAt,          type: (replyTo > 0) ? 'reply' : 'comment',          role: userRole        })      } catch (err) {        WIKI.logger.warn('Akismet Comment Validation: [ FAILED ]')        WIKI.logger.warn(err)      }      if (isSpam) {        throw new Error('Comment was rejected because it is marked as spam.')      }    }    // -> Check for minimum delay between posts    if (WIKI.data.commentProvider.config.minDelay > 0) {      const lastComment = await WIKI.models.comments.query().select('updatedAt').findOne('authorId', user.id).orderBy('updatedAt', 'desc')      if (lastComment && moment().subtract(WIKI.data.commentProvider.config.minDelay, 'seconds').isBefore(lastComment.updatedAt)) {        throw new Error('Your administrator has set a time limit before you can post another comment. Try again later.')      }    }    // -> Save Comment to DB    const cm = await WIKI.models.comments.query().insert(newComment)    // -> Return Comment ID    return cm.id  },  /**   * Update an existing comment   */  async update ({ id, content, user }) {    const renderedContent = DOMPurify.sanitize(mkdown.render(content))    await WIKI.models.comments.query().findById(id).patch({      content,      render: renderedContent    })    return renderedContent  },  /**   * Delete an existing comment by ID   */  async remove ({ id, user }) {    return WIKI.models.comments.query().findById(id).delete()  },  /**   * Get the page ID from a comment ID   */  async getPageIdFromCommentId (id) {    const result = await WIKI.models.comments.query().select('pageId').findById(id)    return (result) ? result.pageId : false  },  /**   * Get a comment by ID   */  async getCommentById (id) {    return WIKI.models.comments.query().findById(id)  },  /**   * Get the total comments count for a page ID   */  async count (pageId) {    const result = await WIKI.models.comments.query().count('* as total').where('pageId', pageId).first()    return _.toSafeInteger(result.total)  }}
 |