memo/server.js

870 lines
21 KiB
JavaScript
Raw Normal View History

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