879 lines
22 KiB
JavaScript
879 lines
22 KiB
JavaScript
const http = require('http')
|
|
const express = require('express')
|
|
const compression = require('compression')
|
|
const sanitizer = require('sanitizer')
|
|
const socketIO = require('socket.io')
|
|
const reload = require('reload')
|
|
const conf = require('./config.js').server
|
|
const { headerBarUrl, logoUrl } = require('./config.js')
|
|
|
|
const app = express()
|
|
const router = express.Router()
|
|
|
|
app.use(compression())
|
|
app.use(conf.baseurl, router)
|
|
router.use(express.static(`${__dirname}/node_modules`))
|
|
router.use(express.static(`${__dirname}/client`))
|
|
|
|
const server = http.createServer(app)
|
|
const io = socketIO(server, { // Use the renamed socketIO require
|
|
path: conf.baseurl === '/' ? '' : `${conf.baseurl}/socket.io`,
|
|
cookie: false
|
|
})
|
|
|
|
/** ************
|
|
LOCAL INCLUDES
|
|
************* */
|
|
const rooms = require('./lib/rooms.js')
|
|
let data = require('./lib/data.js').db
|
|
|
|
/** ************
|
|
GLOBALS
|
|
************* */
|
|
// Map of sids to user_names
|
|
const sids_to_user_names = []
|
|
|
|
// Reload code here
|
|
reload(app)
|
|
.then((reloadReturned) => {
|
|
// reloadReturned is documented in the returns API in the README
|
|
|
|
// Reload started, start web server
|
|
server.listen(conf.port, () => {
|
|
console.log(`Web server available on http://127.0.0.1:${conf.port}`)
|
|
})
|
|
})
|
|
.catch((err) => {
|
|
console.error(
|
|
'Reload could not start, could not start server/sample app',
|
|
err
|
|
)
|
|
})
|
|
|
|
/** ************
|
|
SETUP Socket.IO
|
|
************* */
|
|
|
|
/** ************
|
|
ROUTES
|
|
************* */
|
|
router.get('/', (req, res) => {
|
|
// console.log(req.header('host'));
|
|
url = req.header('host') + req.baseUrl
|
|
const { connected } = io.sockets
|
|
clientsCount = Object.keys(connected).length
|
|
res.render('home.jade', {
|
|
url,
|
|
headerBarUrl,
|
|
logoUrl,
|
|
connected: clientsCount,
|
|
home: true
|
|
})
|
|
})
|
|
|
|
router.get('/demo', (req, res) => {
|
|
url = req.header('host') + req.baseUrl
|
|
res.render('index.jade', {
|
|
pageTitle: 'Memo - demo',
|
|
headerBarUrl,
|
|
logoUrl,
|
|
url,
|
|
demo: true
|
|
})
|
|
})
|
|
|
|
router.get('/:id', (req, res) => {
|
|
url = req.header('host') + req.baseUrl
|
|
res.render('index.jade', {
|
|
pageTitle: `Memo - ${req.params.id}`,
|
|
headerBarUrl,
|
|
logoUrl,
|
|
url
|
|
})
|
|
})
|
|
|
|
router.get('/stats', (req, res) => {
|
|
console.log('TODO: stats')
|
|
})
|
|
|
|
/** ************
|
|
SOCKET.I0
|
|
************* */
|
|
// sanitizes text
|
|
function scrub(text) {
|
|
if (typeof text != 'undefined' && text !== null) {
|
|
// clip the string if it is too long
|
|
if (text.length > 65535) {
|
|
text = text.substr(0, 65535)
|
|
}
|
|
|
|
return sanitizer.sanitize(text)
|
|
}
|
|
return null
|
|
}
|
|
|
|
io.sockets.on('connection', (client) => {
|
|
client.on('message', (message) => {
|
|
// console.log(message.action + " -- " + sys.inspect(message.data) );
|
|
|
|
let clean_data = {}
|
|
let clean_message = {}
|
|
let message_out = {}
|
|
|
|
if (!message.action) return
|
|
|
|
switch (message.action) {
|
|
case 'initializeMe':
|
|
initClient(client)
|
|
break
|
|
|
|
case 'joinRoom':
|
|
joinRoom(client, message.data, (clients) => {
|
|
client.json.send({ action: 'roomAccept', data: '' })
|
|
})
|
|
|
|
break
|
|
|
|
case 'editBoardMetas':
|
|
clean_data = {}
|
|
// TODO: test if prop is in ['title', opacity, 'imageUrl']
|
|
clean_data.id = message.data.id
|
|
clean_data.prop = message.data.prop
|
|
clean_data.value = scrub(message.data.value)
|
|
|
|
// send update to database
|
|
getRoom(client, (room) => {
|
|
db.editBoardMetas(room, clean_data.id, clean_data.prop, clean_data.value)
|
|
})
|
|
|
|
message_out = {
|
|
action: 'editBoardMetas',
|
|
data: clean_data
|
|
}
|
|
|
|
broadcastToRoom(client, message_out)
|
|
|
|
break
|
|
|
|
case 'moveCard':
|
|
// report to all other browsers
|
|
message_out = {
|
|
action: message.action,
|
|
data: {
|
|
id: scrub(message.data.id),
|
|
position: {
|
|
left: scrub(message.data.position.left),
|
|
top: scrub(message.data.position.top)
|
|
}
|
|
}
|
|
}
|
|
|
|
broadcastToRoom(client, message_out)
|
|
|
|
// console.log("-----" + message.data.id);
|
|
// console.log(JSON.stringify(message.data));
|
|
|
|
getRoom(client, (room) => {
|
|
db.cardSetXY(
|
|
room,
|
|
message.data.id,
|
|
message.data.position.left,
|
|
message.data.position.top
|
|
)
|
|
})
|
|
|
|
break
|
|
|
|
case 'createCard':
|
|
data = message.data
|
|
clean_data = {}
|
|
clean_data.text = scrub(data.text)
|
|
clean_data.id = scrub(data.id)
|
|
clean_data.x = scrub(data.x)
|
|
clean_data.y = scrub(data.y)
|
|
clean_data.rot = scrub(data.rot)
|
|
clean_data.colour = scrub(data.colour)
|
|
|
|
getRoom(client, (room) => {
|
|
createCard(
|
|
room,
|
|
clean_data.id,
|
|
clean_data.text,
|
|
clean_data.x,
|
|
clean_data.y,
|
|
clean_data.rot,
|
|
clean_data.colour
|
|
)
|
|
})
|
|
|
|
message_out = {
|
|
action: 'createCard',
|
|
data: clean_data
|
|
}
|
|
|
|
// report to all other browsers
|
|
broadcastToRoom(client, message_out)
|
|
break
|
|
|
|
case 'editCard':
|
|
clean_data = {}
|
|
clean_data.value = scrub(message.data.value)
|
|
clean_data.id = scrub(message.data.id)
|
|
|
|
// send update to database
|
|
getRoom(client, (room) => {
|
|
db.cardEdit(room, clean_data.id, clean_data.value)
|
|
})
|
|
|
|
message_out = {
|
|
action: 'editCard',
|
|
data: clean_data
|
|
}
|
|
|
|
broadcastToRoom(client, message_out)
|
|
|
|
break
|
|
|
|
case 'deleteCard':
|
|
clean_message = {
|
|
action: 'deleteCard',
|
|
data: { id: scrub(message.data.id) }
|
|
}
|
|
|
|
getRoom(client, (room) => {
|
|
db.deleteCard(room, clean_message.data.id)
|
|
})
|
|
|
|
// report to all other browsers
|
|
broadcastToRoom(client, clean_message)
|
|
|
|
break
|
|
|
|
case 'createColumn':
|
|
clean_message = { data: scrub(message.data) }
|
|
|
|
getRoom(client, (room) => {
|
|
db.createColumn(room, clean_message.data, () => {})
|
|
})
|
|
|
|
broadcastToRoom(client, clean_message)
|
|
|
|
break
|
|
|
|
case 'deleteColumn':
|
|
getRoom(client, (room) => {
|
|
db.deleteColumn(room)
|
|
})
|
|
broadcastToRoom(client, { action: 'deleteColumn' })
|
|
|
|
break
|
|
|
|
case 'updateColumns':
|
|
var columns = message.data
|
|
|
|
if (!(columns instanceof Array)) break
|
|
|
|
var clean_columns = []
|
|
|
|
for (const i in columns) {
|
|
clean_columns[i] = scrub(columns[i])
|
|
}
|
|
getRoom(client, (room) => {
|
|
db.setColumns(room, clean_columns)
|
|
})
|
|
|
|
broadcastToRoom(client, {
|
|
action: 'updateColumns',
|
|
data: clean_columns
|
|
})
|
|
|
|
break
|
|
|
|
case 'changeTheme':
|
|
clean_message = {}
|
|
clean_message.data = scrub(message.data)
|
|
|
|
getRoom(client, (room) => {
|
|
db.setTheme(room, clean_message.data)
|
|
})
|
|
|
|
clean_message.action = 'changeTheme'
|
|
|
|
broadcastToRoom(client, clean_message)
|
|
break
|
|
|
|
case 'setUserName':
|
|
clean_message = {}
|
|
|
|
clean_message.data = scrub(message.data)
|
|
|
|
setUserName(client, clean_message.data)
|
|
|
|
var msg = {}
|
|
msg.action = 'nameChangeAnnounce'
|
|
msg.data = { sid: client.id, user_name: clean_message.data }
|
|
broadcastToRoom(client, msg)
|
|
break
|
|
|
|
case 'addSticker':
|
|
var cardId = scrub(message.data.cardId)
|
|
var stickerId = scrub(message.data.stickerId)
|
|
|
|
getRoom(client, (room) => {
|
|
db.addSticker(room, cardId, stickerId)
|
|
})
|
|
|
|
broadcastToRoom(client, {
|
|
action: 'addSticker',
|
|
data: { cardId, stickerId }
|
|
})
|
|
break
|
|
|
|
case 'setBoardSize':
|
|
var size = {}
|
|
size.width = scrub(message.data.width)
|
|
size.height = scrub(message.data.height)
|
|
|
|
getRoom(client, (room) => {
|
|
db.setBoardSize(room, size)
|
|
})
|
|
|
|
broadcastToRoom(client, { action: 'setBoardSize', data: size })
|
|
break
|
|
|
|
case 'exportTxt':
|
|
exportBoard('txt', client, message.data)
|
|
break
|
|
|
|
case 'exportCsv':
|
|
exportBoard('csv', client, message.data)
|
|
break
|
|
|
|
case 'exportJson':
|
|
exportJson(client, message.data)
|
|
break
|
|
|
|
case 'importJson':
|
|
importJson(client, message.data)
|
|
break
|
|
|
|
case 'createRevision':
|
|
createRevision(client, message.data)
|
|
break
|
|
|
|
case 'deleteRevision':
|
|
deleteRevision(client, message.data)
|
|
break
|
|
|
|
case 'exportRevision':
|
|
exportRevision(client, message.data)
|
|
break
|
|
|
|
default:
|
|
// console.log('unknown action');
|
|
break
|
|
}
|
|
})
|
|
|
|
client.on('disconnect', () => {
|
|
leaveRoom(client)
|
|
})
|
|
|
|
// tell all others that someone has connected
|
|
// client.broadcast('someone has connected');
|
|
})
|
|
|
|
/** ************
|
|
FUNCTIONS
|
|
************* */
|
|
function initClient(client) {
|
|
// console.log ('initClient Started');
|
|
getRoom(client, (room) => {
|
|
db.getAllCards(room, (cards) => {
|
|
client.json.send({
|
|
action: 'initCards',
|
|
data: cards
|
|
})
|
|
})
|
|
|
|
db.getAllColumns(room, (columns) => {
|
|
client.json.send({
|
|
action: 'initColumns',
|
|
data: columns
|
|
})
|
|
})
|
|
|
|
db.getRevisions(room, (revisions) => {
|
|
client.json.send({
|
|
action: 'initRevisions',
|
|
data: revisions !== null ? Object.keys(revisions) : []
|
|
})
|
|
})
|
|
|
|
db.getTheme(room, (theme) => {
|
|
if (theme === null) theme = 'bigcards'
|
|
|
|
client.json.send({
|
|
action: 'changeTheme',
|
|
data: theme
|
|
})
|
|
})
|
|
|
|
db.getBoardSize(room, (size) => {
|
|
if (size !== null) {
|
|
client.json.send({
|
|
action: 'setBoardSize',
|
|
data: size
|
|
})
|
|
}
|
|
})
|
|
|
|
roommates_clients = rooms.room_clients(room)
|
|
roommates = []
|
|
|
|
let j = 0
|
|
for (const i in roommates_clients) {
|
|
if (roommates_clients[i].id != client.id) {
|
|
roommates[j] = {
|
|
sid: roommates_clients[i].id,
|
|
user_name: sids_to_user_names[roommates_clients[i].id]
|
|
}
|
|
j++
|
|
}
|
|
}
|
|
|
|
// console.log('initialusers: ' + roommates);
|
|
client.json.send({
|
|
action: 'initialUsers',
|
|
data: roommates
|
|
})
|
|
})
|
|
}
|
|
|
|
function joinRoom(client, room, successFunction) {
|
|
const msg = {}
|
|
msg.action = 'join-announce'
|
|
msg.data = { sid: client.id, user_name: client.user_name }
|
|
|
|
rooms.add_to_room_and_announce(client, room, msg)
|
|
successFunction()
|
|
}
|
|
|
|
function leaveRoom(client) {
|
|
// console.log (client.id + ' just left');
|
|
const msg = {}
|
|
msg.action = 'leave-announce'
|
|
msg.data = { sid: client.id }
|
|
rooms.remove_from_all_rooms_and_announce(client, msg)
|
|
|
|
delete sids_to_user_names[client.id]
|
|
}
|
|
|
|
function broadcastToRoom(client, message) {
|
|
rooms.broadcast_to_roommates(client, message)
|
|
}
|
|
|
|
// ----------------CARD FUNCTIONS
|
|
function createCard(room, id, text, x, y, rot, colour) {
|
|
const card = {
|
|
id,
|
|
colour,
|
|
rot,
|
|
x,
|
|
y,
|
|
text,
|
|
sticker: null
|
|
}
|
|
|
|
db.createCard(room, id, card)
|
|
}
|
|
|
|
function roundRand(max) {
|
|
return Math.floor(Math.random() * max)
|
|
}
|
|
|
|
// ------------ROOM STUFF
|
|
// Get Room name for the given Session ID
|
|
function getRoom(client, callback) {
|
|
room = rooms.get_room(client)
|
|
// console.log( 'client: ' + client.id + " is in " + room);
|
|
callback(room)
|
|
}
|
|
|
|
function setUserName(client, name) {
|
|
client.user_name = name
|
|
sids_to_user_names[client.id] = name
|
|
// console.log('sids to user names: ');
|
|
console.dir(sids_to_user_names)
|
|
}
|
|
|
|
function cleanAndInitializeDemoRoom() {
|
|
// DUMMY DATA
|
|
db.clearRoom('/demo', () => {
|
|
db.createColumn('/demo', 'Pas commencé')
|
|
db.createColumn('/demo', 'Commencé')
|
|
db.createColumn('/demo', 'En test')
|
|
db.createColumn('/demo', 'Validation')
|
|
db.createColumn('/demo', 'Terminé')
|
|
|
|
createCard(
|
|
'/demo',
|
|
'card1',
|
|
"Salut, c'est fun",
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'yellow'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card2',
|
|
"Salut, c'est une nouvelle histoire.",
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'white'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card3',
|
|
'.',
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'blue'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card4',
|
|
'.',
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'green'
|
|
)
|
|
|
|
createCard(
|
|
'/demo',
|
|
'card5',
|
|
"Salut, c'est fun",
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'yellow'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card6',
|
|
"Salut, c'est un nouveau mémo.",
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'yellow'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card7',
|
|
'.',
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'blue'
|
|
)
|
|
createCard(
|
|
'/demo',
|
|
'card8',
|
|
'.',
|
|
roundRand(600),
|
|
roundRand(300),
|
|
Math.random() * 10 - 5,
|
|
'green'
|
|
)
|
|
})
|
|
}
|
|
|
|
// Export board in txt or csv
|
|
function exportBoard(format, client, data) {
|
|
const result = []
|
|
getRoom(client, (room) => {
|
|
db.getAllCards(room, (cards) => {
|
|
db.getAllColumns(room, (columns) => {
|
|
const text = []
|
|
const cols = {}
|
|
if (columns.length > 0) {
|
|
for (var i = 0; i < columns.length; i++) {
|
|
cols[columns[i]] = []
|
|
for (var j = 0; j < cards.length; j++) {
|
|
if (i === 0) {
|
|
if (cards[j].x < (i + 1) * data) {
|
|
cols[columns[i]].push(cards[j])
|
|
}
|
|
} else if (i + 1 === columns.length) {
|
|
if (cards[j].x >= i * data) {
|
|
cols[columns[i]].push(cards[j])
|
|
}
|
|
} else if (
|
|
cards[j].x >= i * data
|
|
&& cards[j].x < (i + 1) * data
|
|
) {
|
|
cols[columns[i]].push(cards[j])
|
|
}
|
|
}
|
|
cols[columns[i]].sort((a, b) => {
|
|
if (a.y === b.y) {
|
|
return a.x - b.x
|
|
}
|
|
return a.y - b.y
|
|
})
|
|
}
|
|
if (format === 'txt') {
|
|
for (var i = 0; i < columns.length; i++) {
|
|
if (i === 0) {
|
|
text.push(`# ${columns[i]}`)
|
|
} else {
|
|
text.push(`\n# ${columns[i]}`)
|
|
}
|
|
for (var j = 0; j < cols[columns[i]].length; j++) {
|
|
text.push(`- ${cols[columns[i]][j].text}`)
|
|
}
|
|
}
|
|
} else if (format === 'csv') {
|
|
let max = 0
|
|
let line = []
|
|
const patt_vuln = new RegExp('^[=+-@]')
|
|
for (var i = 0; i < columns.length; i++) {
|
|
if (cols[columns[i]].length > max) {
|
|
max = cols[columns[i]].length
|
|
}
|
|
var val = columns[i].replace(/"/g, '""')
|
|
if (patt_vuln.test(val)) {
|
|
// prevent CSV Formula Injection
|
|
var val = `'${val}`
|
|
}
|
|
line.push(`"${val}"`)
|
|
}
|
|
text.push(line.join(','))
|
|
for (var j = 0; j < max; j++) {
|
|
line = []
|
|
for (var i = 0; i < columns.length; i++) {
|
|
var val = cols[columns[i]][j] !== undefined
|
|
? cols[columns[i]][j].text.replace(/"/g, '""')
|
|
: ''
|
|
if (patt_vuln.test(val)) {
|
|
// prevent CSV Formula Injection
|
|
var val = `'${val}`
|
|
}
|
|
line.push(`"${val}"`)
|
|
}
|
|
text.push(line.join(','))
|
|
}
|
|
}
|
|
} else {
|
|
for (var j = 0; j < cards.length; j++) {
|
|
if (format === 'txt') {
|
|
text.push(`- ${cards[j].text}`)
|
|
} else if (format === 'csv') {
|
|
text.push(`"${cards[j].text.replace(/"/g, '""')}"\n`)
|
|
}
|
|
}
|
|
}
|
|
let result
|
|
if (format === 'txt' || format === 'csv') {
|
|
result = text.join('\n')
|
|
} else if (format === 'json') {
|
|
result = JSON.stringify(cols)
|
|
}
|
|
client.json.send({
|
|
action: 'export',
|
|
data: {
|
|
filename: `${room.replace('/', '')}.${format}`,
|
|
text: result
|
|
}
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
// Export board in json, suitable for import
|
|
function exportJson(client, data) {
|
|
let result = []
|
|
getRoom(client, (room) => {
|
|
db.getAllCards(room, (cards) => {
|
|
db.getAllColumns(room, (columns) => {
|
|
db.getTheme(room, (theme) => {
|
|
db.getBoardSize(room, (size) => {
|
|
if (theme === null) theme = 'bigcards'
|
|
if (size === null) { size = { width: data.width, height: data.height } }
|
|
result = JSON.stringify({
|
|
cards,
|
|
columns,
|
|
theme,
|
|
size
|
|
})
|
|
client.json.send({
|
|
action: 'export',
|
|
data: {
|
|
filename: `${room.replace('/', '')}.json`,
|
|
text: result
|
|
}
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
// Import board from json
|
|
function importJson(client, data) {
|
|
getRoom(client, (room) => {
|
|
db.clearRoom(room, () => {
|
|
db.getAllCards(room, (cards) => {
|
|
for (var i = 0; i < cards.length; i++) {
|
|
db.deleteCard(room, cards[i].id)
|
|
}
|
|
|
|
cards = data.cards
|
|
const cards2 = []
|
|
for (var i = 0; i < cards.length; i++) {
|
|
const card = cards[i]
|
|
if (
|
|
card.id !== undefined
|
|
&& card.colour !== undefined
|
|
&& card.rot !== undefined
|
|
&& card.x !== undefined
|
|
&& card.y !== undefined
|
|
&& card.text !== undefined
|
|
&& card.sticker !== undefined
|
|
) {
|
|
const c = {
|
|
id: card.id,
|
|
colour: card.colour,
|
|
rot: card.rot,
|
|
x: card.x,
|
|
y: card.y,
|
|
text: scrub(card.text),
|
|
sticker: card.sticker
|
|
}
|
|
db.createCard(room, c.id, c)
|
|
cards2.push(c)
|
|
}
|
|
}
|
|
const msg = { action: 'initCards', data: cards2 }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
})
|
|
|
|
db.getAllColumns(room, (columns) => {
|
|
for (var i = 0; i < columns.length; i++) {
|
|
db.deleteColumn(room)
|
|
}
|
|
|
|
columns = data.columns
|
|
const columns2 = []
|
|
for (var i = 0; i < columns.length; i++) {
|
|
const column = scrub(columns[i])
|
|
if (typeof column === 'string') {
|
|
db.createColumn(room, column)
|
|
columns2.push(column)
|
|
}
|
|
}
|
|
msg = { action: 'initColumns', data: columns2 }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
})
|
|
|
|
let { size } = data
|
|
if (size.width !== undefined && size.height !== undefined) {
|
|
size = { width: scrub(size.width), height: scrub(size.height) }
|
|
db.setBoardSize(room, size)
|
|
msg = { action: 'setBoardSize', data: size }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
}
|
|
|
|
data.theme = scrub(data.theme)
|
|
if (data.theme === 'smallcards' || data.theme === 'bigcards') {
|
|
db.setTheme(room, data.theme)
|
|
msg = { action: 'changeTheme', data: data.theme }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
//
|
|
|
|
function createRevision(client, data) {
|
|
let result = []
|
|
getRoom(client, (room) => {
|
|
db.getAllCards(room, (cards) => {
|
|
db.getAllColumns(room, (columns) => {
|
|
db.getTheme(room, (theme) => {
|
|
db.getBoardSize(room, (size) => {
|
|
if (theme === null) theme = 'bigcards'
|
|
if (size === null) { size = { width: data.width, height: data.height } }
|
|
result = {
|
|
cards,
|
|
columns,
|
|
theme,
|
|
size
|
|
}
|
|
const timestamp = Date.now()
|
|
db.getRevisions(room, (revisions) => {
|
|
if (revisions === null) revisions = {}
|
|
revisions[`${timestamp}`] = result
|
|
db.setRevisions(room, revisions)
|
|
msg = { action: 'addRevision', data: timestamp }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function deleteRevision(client, timestamp) {
|
|
getRoom(client, (room) => {
|
|
db.getRevisions(room, (revisions) => {
|
|
if (revisions !== null && revisions[`${timestamp}`] !== undefined) {
|
|
delete revisions[`${timestamp}`]
|
|
db.setRevisions(room, revisions)
|
|
}
|
|
msg = { action: 'deleteRevision', data: timestamp }
|
|
broadcastToRoom(client, msg)
|
|
client.json.send(msg)
|
|
})
|
|
})
|
|
}
|
|
|
|
function exportRevision(client, timestamp) {
|
|
getRoom(client, (room) => {
|
|
db.getRevisions(room, (revisions) => {
|
|
if (revisions !== null && revisions[`${timestamp}`] !== undefined) {
|
|
client.json.send({
|
|
action: 'export',
|
|
data: {
|
|
filename: `${room.replace('/', '')}-${timestamp}.json`,
|
|
text: JSON.stringify(revisions[`${timestamp}`])
|
|
}
|
|
})
|
|
} else {
|
|
client.json.send({
|
|
action: 'message',
|
|
data: `Unable to find revision ${timestamp}.`
|
|
})
|
|
}
|
|
})
|
|
})
|
|
}
|
|
/** ************
|
|
SETUP DATABASE ON FIRST RUN
|
|
************* */
|
|
// (runs only once on startup)
|
|
var db = new data(() => {
|
|
cleanAndInitializeDemoRoom()
|
|
})
|