NotificationLatch/lib/repository.js

130 lines
2.9 KiB
JavaScript

const fs = require('fs').promises;
const fshelpers = require('./fshelpers');
const crypto = require('crypto');
const { DateTime } = require('luxon');
function checkInitialized()
{
if (!global.repositoryData)
throw new Error('Repository not initialized, call init() first');
}
async function init(filename, salt)
{
if (global.repositoryData)
throw new Error('Repository is already initialized');
global.repositoryData = {
filename: filename,
salt: salt,
notifications: {}
};
if (!(await fshelpers.exists(filename)))
return;
const contents = await fs.readFile(filename, 'utf8');
global.repositoryData.notifications = JSON.parse(contents.toString());
}
async function flush()
{
const contents = JSON.stringify(global.repositoryData.notifications, null, 2);
await fs.writeFile(global.repositoryData.filename, contents, 'utf8');
}
function getNotificationToken(id)
{
const hasher = crypto.createHmac("sha256", global.repositoryData.salt);
return hasher.update(id).digest("hex");
}
function getUnixTimestamp()
{
return Math.floor(DateTime.now().toSeconds());
}
// Returns the notification token if it should be sent out or null if the notification is latched
async function storeNotification(id, title)
{
checkInitialized();
const now = getUnixTimestamp();
const token = getNotificationToken(id);
if (!global.repositoryData.notifications.hasOwnProperty(token))
{
console.info(`New notification with id '${id}' and token '${token}', send permitted`);
global.repositoryData.notifications[token] = {
id: id,
title: title,
latched: true,
latchTime: now,
resetTime: null,
reminders: true,
remindTime: null
};
await flush();
return token;
}
const notification = global.repositoryData.notifications[token];
if (notification.latched)
{
console.info(`Notification with id ${id} and token '${token}' is already latched, send blocked`);
return null;
}
console.info(`Latching notification with id ${id} and token '${token}', send permitted`);
notification.latched = true;
notification.latchTime = now;
await flush();
return token;
}
async function resetNotification(token)
{
checkInitialized();
const now = getUnixTimestamp();
if (!global.repositoryData.notifications.hasOwnProperty(token))
{
console.info(`Notification token '${token}' does not exist, reset unneccesary`);
return;
}
const notification = global.repositoryData.notifications[token];
if (!notification.latched)
{
console.info(`Notification with id '${notification.id}' and token '${token}' is not latched, reset unneccesary`);
return;
}
console.info(`Resetting notification with id '${notification.id}' and token '${token}'`);
notification.latched = false;
notification.resetTime = now;
notification.reminders = true;
notification.remindTime = null;
await flush();
}
module.exports = {
init,
storeNotification,
resetNotification
}