From 93d07daf8d180d29a4fa9b959a379c59ae056cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Bl=C3=A4ul?= Date: Sun, 23 Oct 2022 14:03:33 +0200 Subject: [PATCH] feat(comments): allow notification emails --- server/db/migrations-sqlite/2.5.292.js | 8 + server/db/migrations/2.5.292.js | 8 + server/jobs/README.md | 7 + .../jobs/send-comment-notification-emails.js | 47 +++ server/models/comments.js | 3 +- .../modules/comments/default/definition.yml | 8 +- server/templates/comment-notification.html | 283 ++++++++++++++++++ 7 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 server/db/migrations-sqlite/2.5.292.js create mode 100644 server/db/migrations/2.5.292.js create mode 100644 server/jobs/README.md create mode 100644 server/jobs/send-comment-notification-emails.js create mode 100644 server/templates/comment-notification.html diff --git a/server/db/migrations-sqlite/2.5.292.js b/server/db/migrations-sqlite/2.5.292.js new file mode 100644 index 00000000..410bdda1 --- /dev/null +++ b/server/db/migrations-sqlite/2.5.292.js @@ -0,0 +1,8 @@ +exports.up = async knex => { + await knex.schema.alterTable('comments', table => { + table.boolean('notificationSent').notNullable().defaultTo(false) + }) +} + +exports.down = knex => { +} diff --git a/server/db/migrations/2.5.292.js b/server/db/migrations/2.5.292.js new file mode 100644 index 00000000..410bdda1 --- /dev/null +++ b/server/db/migrations/2.5.292.js @@ -0,0 +1,8 @@ +exports.up = async knex => { + await knex.schema.alterTable('comments', table => { + table.boolean('notificationSent').notNullable().defaultTo(false) + }) +} + +exports.down = knex => { +} diff --git a/server/jobs/README.md b/server/jobs/README.md new file mode 100644 index 00000000..6ec22ef6 --- /dev/null +++ b/server/jobs/README.md @@ -0,0 +1,7 @@ +# About jobs + +The files in this directory can be executed from the terminal like this: + +````bash +node server/core/worker.js --job=send-comment-notification-emails +```` diff --git a/server/jobs/send-comment-notification-emails.js b/server/jobs/send-comment-notification-emails.js new file mode 100644 index 00000000..adab36a5 --- /dev/null +++ b/server/jobs/send-comment-notification-emails.js @@ -0,0 +1,47 @@ +/* global WIKI */ + +module.exports = async () => { + WIKI.models = require('../core/db').init() + await WIKI.configSvc.loadFromDb() + WIKI.mail = require('../core/mail').init() + WIKI.lang = require('../core/localization').init() + const providers = await WIKI.models.commentProviders.query().where('key', 'default') + const emailAddresses = providers[0].config.notificationEmailAddresses + if (!providers[0].isEnabled || !emailAddresses) return + const unsentComments = await WIKI.models.comments.query().select('id', 'pageId', 'name', 'email', 'content').where('notificationSent', false) + WIKI.logger.info('Number of comments that need to be sent: ' + unsentComments.length) + if (!unsentComments.length) return + let listItems = '' + for (const comment of unsentComments) { + const page = await WIKI.models.pages.getPageFromDb(comment.pageId) + if (!page) { + throw new WIKI.Error.PageNotFound() + } + const interpolation = { + email: comment.email, + commentAuthorName: comment.name, + pagePath: WIKI.config.host + '/' + page.path, + pageTitle: page.title + } + listItems += '
  • ' + WIKI.lang.engine.t('emails:notification-email:item', interpolation) + ':
    ' + + comment.content + + await WIKI.models.comments.query().findById(comment.id).patch({ + notificationSent: true + }) + } + const subject = WIKI.lang.engine.t('emails:notification-email:subject') + for (const to of emailAddresses.split(/, */)) { + await WIKI.mail.send({ + template: 'comment-notification', + to, + subject, + data: { + preheadertext: WIKI.lang.engine.t('emails:notification-email:preheadertext'), + title: subject, + content: '' + } + }) + WIKI.logger.info('Sent notification email to ' + to + '.') + } +} diff --git a/server/models/comments.js b/server/models/comments.js index 0ec5f5c9..b27fc7a5 100644 --- a/server/models/comments.js +++ b/server/models/comments.js @@ -23,7 +23,8 @@ module.exports = class Comment extends Model { email: {type: 'string'}, ip: {type: 'string'}, createdAt: {type: 'string'}, - updatedAt: {type: 'string'} + updatedAt: {type: 'string'}, + notificationSent: {type: 'boolean'} } } } diff --git a/server/modules/comments/default/definition.yml b/server/modules/comments/default/definition.yml index 4eceee52..8f9bcbed 100644 --- a/server/modules/comments/default/definition.yml +++ b/server/modules/comments/default/definition.yml @@ -10,7 +10,6 @@ props: akismet: type: String title: Akismet API Key - default: '' hint: 'Prevent spam by using the Akismet service. Enter your API key here to enable. Leave empty to disable.' maxWidth: 650 order: 1 @@ -21,3 +20,10 @@ props: hint: 'Minimum delay (in seconds) between comments per account. Note that all guests are considered as a single account.' maxWidth: 400 order: 2 + notificationEmailAddresses: + type: String + title: Email addresses to notify on new comment + hint: You can separate multiple addresses with a comma. + multiline: true + maxWidth: 650 + order: 3 diff --git a/server/templates/comment-notification.html b/server/templates/comment-notification.html new file mode 100644 index 00000000..3b6274f9 --- /dev/null +++ b/server/templates/comment-notification.html @@ -0,0 +1,283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    + <%= preheadertext %> +
    + + + + +
    + ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌  +
    + + + + + + +
    + +