|
@@ -14,9 +14,9 @@ local expired_status = "expired";
|
14
|
14
|
-- Options
|
15
|
15
|
local poltergeist_component
|
16
|
16
|
= module:get_option_string("poltergeist_component", module.host);
|
|
17
|
+-- defaults to 30 seconds
|
17
|
18
|
local poltergeist_timeout
|
18
|
|
- = module:get_option_string("poltergeist_leave_timeout", 180);
|
|
19
|
+ = module:get_option_string("poltergeist_leave_timeout", 30);
|
19
|
20
|
-- this basically strips the domain from the conference.domain address
|
20
|
21
|
local parentHostName = string.gmatch(tostring(module.host), "%w+.(%w.+)")();
|
21
|
22
|
if parentHostName == nil then
|
|
@@ -108,27 +108,6 @@ function remove_username(room, nick)
|
108
|
108
|
end
|
109
|
109
|
end
|
110
|
110
|
|
111
|
|
-function generate_poltergeist_presence(room, nick, status)
|
112
|
|
- local presence_stanza = st.presence({
|
113
|
|
- to = room.jid.."/"..nick,
|
114
|
|
- from = poltergeist_component.."/"..nick,
|
115
|
|
- }):tag("x", { xmlns = MUC_NS }):up();
|
116
|
|
-
|
117
|
|
- presence_stanza:tag("call_cancel"):text(nil):up();
|
118
|
|
- presence_stanza:tag("call_id"):text(nil):up();
|
119
|
|
-
|
120
|
|
- if status then
|
121
|
|
- presence_stanza:tag("status"):text(status):up();
|
122
|
|
- else
|
123
|
|
- presence_stanza:tag("status"):text(nil):up();
|
124
|
|
- end
|
125
|
|
-
|
126
|
|
- return presence_stanza;
|
127
|
|
-end
|
128
|
|
-
|
129
|
111
|
--- Verifies room name, domain name with the values in the token
|
130
|
112
|
-- @param token the token we received
|
131
|
113
|
-- @param room_name the room name
|
|
@@ -213,89 +192,31 @@ prosody.events.add_handler("pre-jitsi-authentication", function(session)
|
213
|
192
|
return nil;
|
214
|
193
|
end);
|
215
|
194
|
|
216
|
|
-function create_poltergeist_occupant(room, nick, name, avatar, status, context)
|
217
|
|
- log("debug", "create_poltergeist_occupant %s", nick);
|
218
|
|
- -- Join poltergeist occupant to room, with the invited JID as their nick
|
219
|
|
- local join_presence = generate_poltergeist_presence(room, nick, status)
|
220
|
|
-
|
221
|
|
- if (name) then
|
222
|
|
- join_presence:tag(
|
223
|
|
- "nick",
|
224
|
|
- { xmlns = "http://jabber.org/protocol/nick" }):text(name):up();
|
225
|
|
- end
|
226
|
|
- if (avatar) then
|
227
|
|
- join_presence:tag("avatar-url"):text(avatar):up();
|
228
|
|
- end
|
229
|
|
-
|
230
|
|
- -- If the room has a password set, let the poltergeist enter using it
|
231
|
|
- local room_password = room:get_password();
|
232
|
|
- if room_password then
|
233
|
|
- local join = join_presence:get_child("x", MUC_NS);
|
234
|
|
- join:tag("password", { xmlns = MUC_NS }):text(room_password);
|
235
|
|
- end
|
236
|
|
-
|
237
|
|
- -- Update the nil call id to the initial call id for call flows.
|
238
|
|
- local call_id = get_username(room, context.user.id);
|
239
|
|
- join_presence:maptags(function (tag)
|
240
|
|
- if tag.name == "call_id" then
|
241
|
|
- return st.stanza("call_id"):text(call_id);
|
242
|
|
- end
|
243
|
|
- return tag;
|
244
|
|
- end);
|
245
|
|
-
|
246
|
|
- update_presence_identity(
|
247
|
|
- join_presence,
|
248
|
|
- context.user,
|
249
|
|
- context.group,
|
250
|
|
- context.creator_user,
|
251
|
|
- context.creator_group
|
252
|
|
- );
|
253
|
|
-
|
254
|
|
- room:handle_first_presence(
|
255
|
|
- prosody.hosts[poltergeist_component], join_presence);
|
256
|
|
-
|
257
|
|
- -- the timeout before removing so participants can see the status update
|
258
|
|
- local removeTimeout = 5;
|
259
|
|
- local timeout = poltergeist_timeout - removeTimeout;
|
260
|
|
-
|
261
|
|
- timer.add_task(timeout,
|
262
|
|
- function ()
|
263
|
|
- update_poltergeist_occupant_status(
|
264
|
|
- room, nick, expired_status);
|
265
|
|
- -- and remove it after some time so participant can see
|
266
|
|
- -- the update
|
267
|
|
- timer.add_task(removeTimeout,
|
268
|
|
- function ()
|
269
|
|
- if (have_poltergeist_occupant(room, nick)) then
|
270
|
|
- remove_poltergeist_occupant(room, nick, false);
|
271
|
|
- end
|
272
|
|
- end);
|
273
|
|
- end);
|
274
|
|
-end
|
275
|
|
-
|
276
|
195
|
-- Removes poltergeist occupant
|
277
|
196
|
-- @param room the room instance where to remove the occupant
|
278
|
197
|
-- @param nick the nick of the occupant to remove
|
279
|
198
|
-- @param ignore to mark the poltergeist unavailble presence to be ignored
|
280
|
199
|
function remove_poltergeist_occupant(room, nick, ignore)
|
281
|
|
- log("debug", "remove_poltergeist_occupant %s", nick);
|
282
|
|
- local leave_presence = st.presence({
|
283
|
|
- to = room.jid.."/"..nick,
|
284
|
|
- from = poltergeist_component.."/"..nick,
|
285
|
|
- type = "unavailable" });
|
286
|
|
- if (ignore) then
|
287
|
|
- poltergeists_pr_ignore[room.jid.."/"..nick] = true;
|
288
|
|
- end
|
289
|
|
- room:handle_normal_presence(
|
290
|
|
- prosody.hosts[poltergeist_component], leave_presence);
|
291
|
|
- remove_username(room, nick);
|
|
200
|
+ log("debug", "remove_poltergeist_occupant %s", nick);
|
|
201
|
+
|
|
202
|
+ local current_presence = get_presence(room, nick);
|
|
203
|
+ if (not current_presence) then
|
|
204
|
+ module:log("info", "attempted to remove a poltergeist with no presence")
|
|
205
|
+ return;
|
|
206
|
+ end
|
|
207
|
+
|
|
208
|
+ local leave_presence = st.clone(current_presence)
|
|
209
|
+ leave_presence.attr.to = room.jid.."/"..nick;
|
|
210
|
+ leave_presence.attr.from = poltergeist_component.."/"..nick;
|
|
211
|
+ leave_presence.attr.type = "unavailable";
|
|
212
|
+
|
|
213
|
+ if (ignore) then
|
|
214
|
+ poltergeists_pr_ignore[room.jid.."/"..nick] = true;
|
|
215
|
+ end
|
|
216
|
+
|
|
217
|
+ room:handle_normal_presence(
|
|
218
|
+ prosody.hosts[poltergeist_component], leave_presence);
|
|
219
|
+ remove_username(room, nick);
|
292
|
220
|
end
|
293
|
221
|
|
294
|
222
|
-- Updates poltergeist occupant status
|
|
@@ -307,16 +228,18 @@ function update_poltergeist_occupant_status(room, nick, status, call_details)
|
307
|
228
|
local update_presence = get_presence(room, nick);
|
308
|
229
|
|
309
|
230
|
if (not update_presence) then
|
310
|
|
- -- no presence found for occupant, create one
|
311
|
|
- update_presence = generate_poltergeist_presence(room, nick)
|
312
|
|
- else
|
313
|
|
- -- update occupant presence with appropriate to and from
|
314
|
|
- -- so we can send it again
|
315
|
|
- update_presence = st.clone(update_presence);
|
316
|
|
- update_presence.attr.to = room.jid.."/"..nick;
|
317
|
|
- update_presence.attr.from = poltergeist_component.."/"..nick;
|
|
231
|
+ -- TODO: determine if we should provide an error and how that would be
|
|
232
|
+ -- handled for bosh and http api.
|
|
233
|
+ module:log("info", "update issued for a non-existing poltergeist")
|
|
234
|
+ return;
|
318
|
235
|
end
|
319
|
236
|
|
|
237
|
+ -- update occupant presence with appropriate to and from
|
|
238
|
+ -- so we can send it again
|
|
239
|
+ update_presence = st.clone(update_presence);
|
|
240
|
+ update_presence.attr.to = room.jid.."/"..nick;
|
|
241
|
+ update_presence.attr.from = poltergeist_component.."/"..nick;
|
|
242
|
+
|
320
|
243
|
update_presence = update_presence_tags(update_presence, status, call_details)
|
321
|
244
|
|
322
|
245
|
room:handle_normal_presence(
|
|
@@ -442,33 +365,122 @@ function handle_create_poltergeist (event)
|
442
|
365
|
return 403;
|
443
|
366
|
end
|
444
|
367
|
|
|
368
|
+ -- If the provided room conference doesn't exist then we
|
|
369
|
+ -- can't add a poltergeist to it.
|
445
|
370
|
local room = get_room(room_name, group);
|
446
|
371
|
if (not room) then
|
447
|
372
|
log("error", "no room found %s", room_name);
|
448
|
373
|
return 404;
|
449
|
374
|
end
|
450
|
375
|
|
|
376
|
+ -- If the poltergiest is already in the conference then it will
|
|
377
|
+ -- be in our username store and another can't be added.
|
451
|
378
|
local username = get_username(room, user_id);
|
452
|
379
|
if (username ~= nil
|
453
|
380
|
and have_poltergeist_occupant(room, string.sub(username, 0, 8))) then
|
454
|
381
|
log("warn", "poltergeist for username:%s already in the room:%s",
|
455
|
382
|
username, room_name);
|
456
|
383
|
return 202;
|
457
|
|
- else
|
458
|
|
- username = generate_uuid();
|
459
|
|
- store_username(room, user_id, username);
|
460
|
|
- local context = {
|
461
|
|
- user = {
|
462
|
|
- id = user_id;
|
463
|
|
- };
|
464
|
|
- group = group;
|
465
|
|
- creator_user = session.jitsi_meet_context_user;
|
466
|
|
- creator_group = session.jitsi_meet_context_group;
|
467
|
|
- };
|
468
|
|
- create_poltergeist_occupant(
|
469
|
|
- room, string.sub(username, 0, 8), name, avatar, status, context);
|
470
|
|
- return 200;
|
471
|
384
|
end
|
|
385
|
+ username = generate_uuid();
|
|
386
|
+ local context = {
|
|
387
|
+ user = {
|
|
388
|
+ id = user_id;
|
|
389
|
+ };
|
|
390
|
+ group = group;
|
|
391
|
+ creator_user = session.jitsi_meet_context_user;
|
|
392
|
+ creator_group = session.jitsi_meet_context_group;
|
|
393
|
+ };
|
|
394
|
+
|
|
395
|
+ local nick = string.sub(username, 0, 8)
|
|
396
|
+ local presence_stanza = original_presence(
|
|
397
|
+ poltergeist_component,
|
|
398
|
+ room,
|
|
399
|
+ nick,
|
|
400
|
+ name,
|
|
401
|
+ avatar,
|
|
402
|
+ username,
|
|
403
|
+ context,
|
|
404
|
+ status
|
|
405
|
+ )
|
|
406
|
+ store_username(room, user_id, username);
|
|
407
|
+
|
|
408
|
+ room:handle_first_presence(
|
|
409
|
+ prosody.hosts[poltergeist_component],
|
|
410
|
+ presence_stanza
|
|
411
|
+ );
|
|
412
|
+
|
|
413
|
+ -- the timeout before removing so participants can see the status update
|
|
414
|
+ local removeTimeout = 5;
|
|
415
|
+ local timeout = poltergeist_timeout - removeTimeout;
|
|
416
|
+
|
|
417
|
+ timer.add_task(timeout,
|
|
418
|
+ function ()
|
|
419
|
+ update_poltergeist_occupant_status(
|
|
420
|
+ room, nick, expired_status);
|
|
421
|
+ -- and remove it after some time so participant can see
|
|
422
|
+ -- the update
|
|
423
|
+ timer.add_task(removeTimeout,
|
|
424
|
+ function ()
|
|
425
|
+ if (have_poltergeist_occupant(room, nick)) then
|
|
426
|
+ remove_poltergeist_occupant(room, nick, false);
|
|
427
|
+ end
|
|
428
|
+ end);
|
|
429
|
+ end);
|
|
430
|
+
|
|
431
|
+ return 200;
|
|
432
|
+end
|
|
433
|
+
|
|
434
|
+-- Generate the original presence for a poltergeist when it is added to a room.
|
|
435
|
+-- @param component is the configured component name for poltergeist.
|
|
436
|
+-- @param room is the room the poltergeist is being added to.
|
|
437
|
+-- @param nick is the nick the poltergeist will use for xmpp.
|
|
438
|
+-- @param avatar is the url of the display avatar for the poltergeist.
|
|
439
|
+-- @param username is the poltergeist unique username.
|
|
440
|
+-- @param context is the context information from the valid auth token.
|
|
441
|
+-- @param status is the status string for the presence.
|
|
442
|
+-- @return a presence stanza
|
|
443
|
+function original_presence(
|
|
444
|
+ component, room, nick, name, avatar, username, context, status)
|
|
445
|
+ local p = st.presence({
|
|
446
|
+ to = room.jid.."/"..nick,
|
|
447
|
+ from = component.."/"..nick,
|
|
448
|
+ }):tag("x", { xmlns = MUC_NS }):up();
|
|
449
|
+
|
|
450
|
+ p:tag("call_cancel"):text(nil):up();
|
|
451
|
+ p:tag("call_id"):text(username):up();
|
|
452
|
+
|
|
453
|
+ if status then
|
|
454
|
+ p:tag("status"):text(status):up();
|
|
455
|
+ else
|
|
456
|
+ p:tag("status"):text(nil):up();
|
|
457
|
+ end
|
|
458
|
+
|
|
459
|
+ if (name) then
|
|
460
|
+ p:tag(
|
|
461
|
+ "nick",
|
|
462
|
+ { xmlns = "http://jabber.org/protocol/nick" }):text(name):up();
|
|
463
|
+ end
|
|
464
|
+
|
|
465
|
+ if (avatar) then
|
|
466
|
+ p:tag("avatar-url"):text(avatar):up();
|
|
467
|
+ end
|
|
468
|
+
|
|
469
|
+ -- If the room has a password set, let the poltergeist enter using it
|
|
470
|
+ local room_password = room:get_password();
|
|
471
|
+ if room_password then
|
|
472
|
+ local join = p:get_child("x", MUC_NS);
|
|
473
|
+ join:tag("password", { xmlns = MUC_NS }):text(room_password);
|
|
474
|
+ end
|
|
475
|
+
|
|
476
|
+ update_presence_identity(
|
|
477
|
+ p,
|
|
478
|
+ context.user,
|
|
479
|
+ context.group,
|
|
480
|
+ context.creator_user,
|
|
481
|
+ context.creator_group
|
|
482
|
+ );
|
|
483
|
+ return p
|
472
|
484
|
end
|
473
|
485
|
|
474
|
486
|
--- Handles request for updating poltergeists status
|
|
@@ -484,12 +496,12 @@ function handle_update_poltergeist (event)
|
484
|
496
|
local room_name = params["room"];
|
485
|
497
|
local group = params["group"];
|
486
|
498
|
local status = params["status"];
|
487
|
|
- local call_id = params["callid"];
|
|
499
|
+ local call_id = params["callid"];
|
488
|
500
|
|
489
|
|
- local call_cancel = false
|
490
|
|
- if params["callcancel"] == "true" then
|
491
|
|
- call_cancel = true;
|
492
|
|
- end
|
|
501
|
+ local call_cancel = false
|
|
502
|
+ if params["callcancel"] == "true" then
|
|
503
|
+ call_cancel = true;
|
|
504
|
+ end
|
493
|
505
|
|
494
|
506
|
if not verify_token(params["token"], room_name, group, {}) then
|
495
|
507
|
return 403;
|
|
@@ -512,12 +524,12 @@ function handle_update_poltergeist (event)
|
512
|
524
|
};
|
513
|
525
|
|
514
|
526
|
local nick = string.sub(username, 0, 8);
|
515
|
|
- if (have_poltergeist_occupant(room, nick)) then
|
516
|
|
- update_poltergeist_occupant_status(room, nick, status, call_details);
|
517
|
|
- return 200;
|
518
|
|
- else
|
519
|
|
- return 404;
|
|
527
|
+ if (not have_poltergeist_occupant(room, nick)) then
|
|
528
|
+ return 404;
|
520
|
529
|
end
|
|
530
|
+
|
|
531
|
+ update_poltergeist_occupant_status(room, nick, status, call_details);
|
|
532
|
+ return 200;
|
521
|
533
|
end
|
522
|
534
|
|
523
|
535
|
--- Handles remove poltergeists
|
|
@@ -549,12 +561,12 @@ function handle_remove_poltergeist (event)
|
549
|
561
|
end
|
550
|
562
|
|
551
|
563
|
local nick = string.sub(username, 0, 8);
|
552
|
|
- if (have_poltergeist_occupant(room, nick)) then
|
553
|
|
- remove_poltergeist_occupant(room, nick, false);
|
554
|
|
- return 200;
|
555
|
|
- else
|
556
|
|
- return 404;
|
|
564
|
+ if (not have_poltergeist_occupant(room, nick)) then
|
|
565
|
+ return 404;
|
557
|
566
|
end
|
|
567
|
+
|
|
568
|
+ remove_poltergeist_occupant(room, nick, false);
|
|
569
|
+ return 200;
|
558
|
570
|
end
|
559
|
571
|
|
560
|
572
|
log("info", "Loading poltergeist service");
|