Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
139 lines (116 loc) · 3.5 KB
/
Copy pathindex.js
File metadata and controls
139 lines (116 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import express from 'express';
import * as http from 'http';
import * as socketio from 'socket.io';
import * as fs from 'fs';
import * as path from 'path';
import * as mqtt from 'mqtt';
const app = express();
const server = http.createServer(app);
const io = new socketio.Server(server);
const client = mqtt.connect("mqtt://mqtt.hacklab");
const connections = new Set();
let timersDatabase = null;
console.log(process.argv);
if (process.argv.length < 3) {
console.log("Must supply a filepath for timer database!")
process.exit(1);
}
timersDatabase = path.resolve(process.argv[2]);
let eventLog = null;
console.log(process.argv);
if (process.argv.length < 4) {
console.log("Must supply a filepath for delta logs!")
process.exit(1);
}
eventLog = process.argv[3];
let timers = null;
try {
timers = JSON.parse(fs.readFileSync(timersDatabase));
} catch (e) {
console.log(`Couldn't read timers from ${timersDatabase}: ${e}`)
timers = {};
}
const eventLogHandle = fs.openSync(eventLog, "a");
function logEvent(type, data) {
let entry = { type: type, time: Date.now(), data }
let raw = JSON.stringify(entry) + "\n"
fs.appendFile(eventLogHandle, raw, { flush: true }, () => {});
}
logEvent("startup", timers);
function resetTimer(name, rawTimestamp) {
let timestamp = null;
if (rawTimestamp == "now") {
timestamp = Date.now() / 1000;
} else if (rawTimestamp == "never") {
timestamp = null;
} else {
timestamp = parseFloat(rawTimestamp);
if (isNaN(timestamp)) return `Could not parse '${rawTimestamp}' as a float. Valid times are "now", "never", or a Unix timestamp.`
}
return { type: "set", "name": name, "value": timestamp };
}
function deleteTimer(name) {
return { type: "delete", "name": name };
}
// Example timers:
//timer("Death of Jesus", -62135596725);
//timer("Nerd snipe", Date.now() / 1000);
//timer("Python GIL complaint", Date.now() / 1000);
//timer("Rewrite it in rust", Date.now() / 1000);
//timer("A monad is just a monoid in the category of endofunctors", Date.now() / 1000);
function edit(dict, delta) {
if (delta.type == "delete") {
delete dict[delta.name];
} else if (delta.type == "set") {
dict[delta.name] = delta.value;
}
}
function applyDelta(res, delta) {
if (typeof delta === "string") {
res.send(`Error: ${errMsg}`, 400);
} else {
edit(timers, delta);
fs.writeFileSync(timersDatabase, JSON.stringify(timers));
logEvent("delta", delta);
for (let conn of connections) {
//conn.emit("update", timers);
conn.emit("edit", delta);
}
res.send(`Success.`);
}
}
app.get('/delete', (req, res) => {
let name = req.query.name;
if (name == null) {
res.send("Reset must have a name.", 500);
return;
}
applyDelta(res, deleteTimer(name));
});
app.get('/reset', (req, res) => {
let name = req.query.name;
if (name == null) {
res.send("Reset must have a name.", 500);
return;
}
let rawTimestamp = req.query.time || req.query.timestamp;
applyDelta(res, resetTimer(name, rawTimestamp));
client.publish("time-since-last/reset-occurred", name);
});
app.get('/history', (req, res) => {
res.sendFile(path.resolve(eventLog));
res.set('Content-Type', 'text/plain');
});
io.on("connection", socket => {
console.log(`New connection`, socket);
connections.add(socket);
socket.emit("update", timers);
socket.on("close", () => {
console.log(`Closing connection`, socket);
connections.delete(socket);
})
});
app.use(express.static("."))
server.listen(3456, () => {
console.log('listening on *:3456');
});