d-bot
Version:
A quirky Discord bot made for single, small, private servers
108 lines (101 loc) • 3.43 kB
JavaScript
// Storage interface to keep files organized
var path = require('path');
var fse = require('fs-extra');
var Nedb = require('nedb-promise');
var callsite = require('callsite'); // For getting filename of calling module
const PATH = 'storage/';
function JSONFile(filename, initData, space) {
this.filename = filename;
this.space = space;
initData = objToMap(initData || {});
try {
let data = fse.readJsonSync(filename);
this.data = new Map([...initData, ...objToMap(data)]);
} catch(err) {
this.data = initData;
} finally {
this.save();
}
}
JSONFile.prototype.get = function(key) {
return this.data.get(key);
};
JSONFile.prototype.set = function(key, value) {
this.data.set(key, value);
this.save();
return this.data;
};
JSONFile.prototype.trans = function(key, fn) {
this.data.set(key, fn(this.data.get(key)));
this.save();
return this.data;
};
JSONFile.prototype.save = function() {
if(this.saving) return;
this.saving = true;
setTimeout(() => { // Multiple saves called at once will collapse into a single save
fse.writeJson(this.filename + '.tmp', mapToObj(this.data), { spaces: this.space })
.then(() => {
fse.move(this.filename + '.tmp', this.filename, { overwrite: true })
.then(() => this.saving = false)
.catch(err => {
console.error('Error writing to file', this.filename, err);
this.saving = false;
});
})
.catch(err => console.error('Error saving temporary file', this.filename + '.tmp', err));
}, 0);
};
JSONFile.prototype.delete = function(key) {
this.data.delete(key);
this.save();
};
JSONFile.prototype.setData = function(data) {
this.data = objToMap(data);
this.save();
return this.data;
};
JSONFile.prototype.reset = function() {
this.data.clear();
this.save();
};
module.exports = {
nedb: async function(name, index) {
try {
let dir = getDirectory(PATH + path.basename(callsite()[1].getFileName(),'.js'));
let db = new Nedb({
filename: dir + '/' + name + '.db',
autoload: true
});
if(index) {
index = Array.isArray(index) ? index : [index];
await index.forEach(i => db.ensureIndex(i));
}
return db;
} catch(e) {
console.log(`Error creating "${name}" nedb`, e);
}
},
json: function(name, initData, space) {
let dir = getDirectory(PATH + path.basename(callsite()[1].getFileName(),'.js'));
return new JSONFile(dir + '/' + name + '.json', initData, space);
},
getStoragePath: function(name) {
let dir = getDirectory(PATH + path.basename(callsite()[1].getFileName(),'.js'));
return dir + '/' + name;
}
};
function getDirectory(dir) {
fse.ensureDirSync(dir);
return dir;
}
function objToMap(obj) { // https://stackoverflow.com/a/36644532/2612679
let map = new Map();
Object.keys(obj).forEach(key => map.set(key, obj[key]));
return map;
}
function mapToObj(map) {
let obj = Object.create(null);
for (let [k,v] of map) obj[k] = v;
return obj;
}