"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.notify = exports.initNotifierDaemon = void 0;

var _util = require("util");

var _responses = require("./responses");

var _event = require("./event");

var _privileges = require("./privileges");

var _repetition = _interopRequireDefault(require("./repetition"));

var _templates = _interopRequireDefault(require("./templates"));

var _settings = require("./settings");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const {
  create: createNotif,
  push: pushNotif
} = require.main.require('./src/notifications');

const {
  getPostFields
} = require.main.require('./src/posts');

const meta = require.main.require('./src/meta');

const {
  getUidsFromSet,
  getUserFields,
  getSettings: getUserSettings
} = require.main.require('./src/user');

const {
  send: sendEmail
} = require.main.require('./src/emailer');

const nconf = require.main.require('nconf');

const winston = require.main.require('winston');

const emailNotification = async ({
  uid,
  event,
  message
}) => {
  if (parseInt(meta.config.disableEmailSubscriptions, 10) === 1) {
    return;
  }

  const [userData, userSettings, response] = await Promise.all([getUserFields(uid, ['username', 'userslug']), getUserSettings(uid), (0, _responses.getUserResponse)({
    pid: event.pid,
    uid,
    day: event.day
  })]);

  if (userSettings.sendPostNotifications) {
    const parsed = await (0, _event.escapeEvent)(event);
    parsed.responses = {
      [uid]: response
    };
    const content = await (0, _templates.default)({
      event: parsed,
      uid,
      isEmail: true
    });
    await sendEmail('notif_plugin_calendar_event_reminder', uid, {
      pid: event.pid,
      subject: `[${meta.config.title || 'NodeBB'}] ` + `[[calendar:event_starting, ${message}, ${event.name}]]`,
      content: content.replace(/"\/\//g, '"https://'),
      site_title: meta.config.title || 'NodeBB',
      username: userData.username,
      userslug: userData.userslug,
      url: `${nconf.get('url')}/post/${event.pid}`,
      base_url: nconf.get('url')
    });
  }
};

const notify = async ({
  event,
  reminder,
  message
}) => {
  let uids; // if event is mandatory, notify all the users who can view it

  if (event.mandatory) {
    const all = await getUidsFromSet('users:joindate', 0, -1);
    uids = await (0, _privileges.filterUidsByPid)(all, event.pid);
  } else {
    let users; // if reminder is for the event start
    // notify 'maybe' and 'yes' responders
    // otherwise, notify only 'yes' responders

    if (reminder === 0) {
      const responses = await (0, _responses.getAll)({
        pid: event.pid,
        selection: ['yes', 'maybe']
      });
      users = [...responses.yes, ...responses.maybe];
    } else {
      const responses = await (0, _responses.getAll)({
        pid: event.pid,
        selection: ['yes']
      });
      users = responses.yes;
    }

    uids = users.map(u => u.uid);
  }

  const postData = await getPostFields(event.pid, ['tid', 'content', 'title']);
  const notif = await createNotif({
    bodyShort: `[[calendar:event_starting, ${message}, ${event.name}]]`,
    bodyLong: postData.content,
    nid: `plugin-calendar:events:pid:${event.pid}:event_starting`,
    pid: event.pid,
    tid: postData.tid,
    from: event.uid,
    path: `/post/${event.pid}`
  });
  await pushNotif(notif, uids);
  await Promise.all(uids.map(uid => emailNotification({
    uid,
    event,
    message,
    postData
  })));
};

exports.notify = notify;

const initNotifierDaemon = async () => {
  // ms between checking for reminders
  // pulled from settings
  let checkingInterval = await (0, _settings.getSetting)('checkingInterval');
  winston.verbose(`[plugins/calendar] Notifier Daemon initialized with
    interval of ${Math.floor(checkingInterval / 1000)} seconds`);
  let lastEnd = Date.now() + checkingInterval;
  const checkReminders = (0, _util.callbackify)(async () => {
    checkingInterval = await (0, _settings.getSetting)('checkingInterval'); // timespan we check is a checkingInterval in the future
    // so as to avoid sending notifications too late

    const start = lastEnd;
    const end = Date.now() + checkingInterval;
    lastEnd = end;
    const events = await (0, _event.getEventsEndingAfter)(start);
    const occurences = events.reduce((prev, event) => {
      const max = Math.max(0, ...event.reminders);

      if (event.repeats) {
        return [...prev, ...(0, _repetition.default)(event, start, end + max)];
      }

      return [...prev, event];
    }, []);
    const filtered = occurences.map(event => {
      const reminder = [0, ...event.reminders].find(r => {
        const remDate = event.startDate - r;
        return remDate > start && remDate <= end;
      });

      if (!Number.isFinite(reminder)) {
        return null;
      }

      const message = `[[moment:time-in, ${event.startDate - start}]]`;
      return {
        event,
        reminder,
        message
      };
    }).filter(Boolean);
    await Promise.all(filtered.map(notify));
  });

  const daemon = () => {
    checkReminders(err => {
      if (err) {
        winston.error(err);
      }

      setTimeout(daemon, checkingInterval);
    });
  };

  daemon();
};

exports.initNotifierDaemon = initNotifierDaemon;
//# sourceMappingURL=reminders.js.map