Skip to content

Commit 875fda7

Browse files
committed
Split out common code shared with notepad
1 parent 90b33e1 commit 875fda7

File tree

2 files changed

+267
-247
lines changed

2 files changed

+267
-247
lines changed

src/commonhandler.js

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
/* eslint-disable node/no-callback-literal */
2+
/*
3+
Fails Components (Fancy Automated Internet Lecture System - Components)
4+
Copyright (C) 2015-2017 (original FAILS),
5+
2021- (FAILS Components) Marten Richter <[email protected]>
6+
7+
This program is free software: you can redistribute it and/or modify
8+
it under the terms of the GNU Affero General Public License as
9+
published by the Free Software Foundation, either version 3 of the
10+
License, or (at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU Affero General Public License for more details.
16+
17+
You should have received a copy of the GNU Affero General Public License
18+
along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
import { commandOptions } from 'redis'
22+
23+
export class CommonConnection {
24+
async getBgpdf(notepadscreenid) {
25+
let lecturedoc = {}
26+
try {
27+
const lecturescol = this.mongo.collection('lectures')
28+
lecturedoc = await lecturescol.findOne(
29+
{ uuid: notepadscreenid.lectureuuid },
30+
{
31+
projection: { _id: 0, backgroundpdfuse: 1, backgroundpdf: 1 }
32+
}
33+
)
34+
// console.log("lecturedoc",lecturedoc);
35+
if (
36+
!lecturedoc.backgroundpdfuse ||
37+
!lecturedoc.backgroundpdf ||
38+
!lecturedoc.backgroundpdf.sha
39+
)
40+
return null
41+
return this.getFileURL(lecturedoc.backgroundpdf.sha, 'application/pdf')
42+
} catch (err) {
43+
console.log('error in getBgpdf pictures', err)
44+
}
45+
}
46+
47+
async getUsedPicts(notepadscreenid) {
48+
let lecturedoc = {}
49+
try {
50+
const lecturescol = this.mongo.collection('lectures')
51+
lecturedoc = await lecturescol.findOne(
52+
{ uuid: notepadscreenid.lectureuuid },
53+
{
54+
projection: { _id: 0, usedpictures: 1 }
55+
}
56+
)
57+
// console.log("lecturedoc",lecturedoc);
58+
if (!lecturedoc.usedpictures) return []
59+
60+
return lecturedoc.usedpictures.map((el) => {
61+
return {
62+
name: el.name,
63+
mimetype: el.mimetype,
64+
sha: el.sha.buffer.toString('hex'),
65+
url: this.getFileURL(el.sha.buffer, el.mimetype),
66+
urlthumb: this.getFileURL(el.tsha.buffer, el.mimetype)
67+
}
68+
})
69+
// ok now I have the picture, but I also have to generate the urls
70+
} catch (err) {
71+
console.log('error in getUsedPicts pictures', err)
72+
}
73+
}
74+
75+
async sendBoardsToSocket(lectureuuid, socket) {
76+
// we have to send first information about pictures
77+
78+
const usedpict = await this.getUsedPicts({ lectureuuid: lectureuuid })
79+
if (usedpict) {
80+
socket.emit('pictureinfo', usedpict)
81+
}
82+
const bgpdf = await this.getBgpdf({ lectureuuid: lectureuuid })
83+
if (bgpdf) {
84+
socket.emit('bgpdfinfo', { bgpdfurl: bgpdf })
85+
} else {
86+
socket.emit('bgpdfinfo', { none: true })
87+
}
88+
89+
try {
90+
const res = await this.redis.sMembers(
91+
'lecture:' + lectureuuid + ':boards'
92+
)
93+
94+
// console.log('boards', res, 'lecture:' + lectureuuid + ':boards')
95+
const length = res.length
96+
let countdown = length
97+
if (length === 0) socket.emit('reloadBoard', { last: true })
98+
for (const index in res) {
99+
const boardnum = res[index]
100+
// console.log('sendBoardsToSocket', boardnum, lectureuuid)
101+
try {
102+
const res2 = await this.redis.get(
103+
commandOptions({ returnBuffers: true }),
104+
'lecture:' + lectureuuid + ':board' + boardnum
105+
)
106+
107+
countdown--
108+
// console.log('send reloadboard', boardnum, res2, length)
109+
const send = {
110+
number: boardnum,
111+
data: res2,
112+
last: countdown === 0
113+
}
114+
socket.emit('reloadBoard', send)
115+
} catch (error) {
116+
console.log('error in sendboard to sockets loop', error)
117+
}
118+
}
119+
} catch (error) {
120+
console.log('error in sendboard to sockets', error)
121+
}
122+
}
123+
124+
async getLectDetail(notepadscreenid, socket) {
125+
// TODO should be feed from mongodb
126+
127+
let lecturedoc = {}
128+
try {
129+
const lecturescol = this.mongo.collection('lectures')
130+
131+
lecturedoc = await lecturescol.findOne(
132+
{ uuid: notepadscreenid.lectureuuid },
133+
{
134+
projection: {
135+
_id: 0,
136+
title: 1,
137+
coursetitle: 1,
138+
ownersdisplaynames: 1,
139+
date: 1
140+
}
141+
}
142+
)
143+
} catch (err) {
144+
console.log('error in get LectDetail', err)
145+
}
146+
147+
const lectdetail = {
148+
title: lecturedoc.title,
149+
coursetitle: lecturedoc.coursetitle,
150+
instructors: lecturedoc.ownersdisplaynames,
151+
date: lecturedoc.date
152+
}
153+
// if (notepadscreenid.notepaduuid) lectdetail.notepaduuid=notepadscreenid.notepaduuid;
154+
socket.emit('lecturedetail', lectdetail)
155+
}
156+
157+
// sync changes to notes
158+
async addUpdateCryptoIdent(args) {
159+
const identity = {
160+
signKey: args.signKey,
161+
cryptKey: args.cryptKey,
162+
displayname: args.displayname,
163+
userhash: args.userhash,
164+
/* id: args.socketid, */
165+
purpose: args.purpose,
166+
lastaccess: Date.now().toString()
167+
}
168+
// Two things store it in redis until disconnect
169+
const oldident = this.redis.hGet(
170+
'lecture:' + args.lectureuuid + ':idents',
171+
args.socketid.toString()
172+
)
173+
this.redis.hSet('lecture:' + args.lectureuuid + ':idents', [
174+
args.socketid.toString(),
175+
JSON.stringify(identity)
176+
])
177+
let oldid = await oldident
178+
if (oldid) oldid = JSON.parse(oldid)
179+
180+
// and inform about new/updated identity
181+
const roomname = this.getRoomName(args.lectureuuid)
182+
183+
if (
184+
oldid &&
185+
identity.signKey === oldid.signKey &&
186+
identity.cryptKey === oldid.cryptKey
187+
) {
188+
this.notepadio.to(roomname).emit('identValidity', {
189+
lastaccess: identity.lastaccess,
190+
id: args.socketid
191+
})
192+
} else {
193+
this.notepadio
194+
.to(roomname)
195+
.emit('identUpdate', { identity: identity, id: args.socketid })
196+
}
197+
}
198+
199+
async handleKeymasterQuery(args) {
200+
const now = Date.now() / 1000
201+
// ok, first we have to figure out if a query is already running
202+
try {
203+
await this.redis.executeIsolated(async (isoredis) => {
204+
await isoredis.watch('lecture:' + args.lectureuuid + ':keymaster')
205+
const queryInfo = await isoredis.hGet(
206+
'lecture:' + args.lectureuuid + ':keymaster',
207+
'queryTime'
208+
)
209+
/* console.log(
210+
'query Info',
211+
queryInfo,
212+
now - Number(queryInfo),
213+
now,
214+
Number(queryInfo)
215+
) */
216+
217+
if (queryInfo && now - Number(queryInfo) < 15) {
218+
// we have no key, so may be the kaymaster does not know that we exist
219+
await this.addUpdateCryptoIdent(args)
220+
return // do not spam the system with these queries 20 +10
221+
}
222+
223+
const res = await isoredis
224+
.multi()
225+
.hSet('lecture:' + args.lectureuuid + ':keymaster', [
226+
'queryTime',
227+
now.toString(),
228+
'bidding',
229+
'0',
230+
'master',
231+
'none'
232+
])
233+
.exec()
234+
if (res !== null) {
235+
const roomname = this.getRoomName(args.lectureuuid)
236+
// start the bidding
237+
this.notepadio.to(roomname).emit('keymasterQuery')
238+
}
239+
})
240+
} catch (error) {
241+
console.log('handleKeymasterQuery problem or multple attempts', error)
242+
}
243+
}
244+
245+
async emitAVOffers(socket, args) {
246+
const alloffers = await this.redis.hGetAll(
247+
'lecture:' + args.lectureuuid + ':avoffers'
248+
)
249+
const offers = []
250+
for (const label in alloffers) {
251+
const labels = label.split(':')
252+
offers.push({
253+
type: labels[0],
254+
id: labels[1],
255+
time: alloffers[label]
256+
})
257+
}
258+
socket.emit('avofferList', { offers })
259+
}
260+
261+
getRoomName(uuid) {
262+
return uuid
263+
}
264+
}

0 commit comments

Comments
 (0)