1(function(){ 2const escapeHTML = function(str) { return str.replace(/[&<>'"]/g, function(tag) { return ({'&': '&', '<': '<', '>': '>', "'": ''', '"': '"'}[tag] || tag) }) }; 3function resizeWindow() { setTimeout(()=>{ $(window).resize() }, 100) } 4$(document).on("ajaxSuccess", function(event, xhr, settings) { 5 if (settings && settings.url && settings.url.indexOf("/pl/user/user/model?id=") > -1 && $('.gc-right-active-block .filebrainpro').length == 0) { 6 const userId = xhr.responseJSON.model.id; 7 $.get('/chtm/app/filebrainpro/~filebrain-bot-status?userId='+userId, '', function (data){ 8 if (data.success) { 9 setTimeout(()=>{ 10 $('.gc-right-active-block .user-avatar').append($('<div class="filebrainpro '+(data.active?'active':'stopped')+'" data-userId="'+userId+'"><button title="'+(data.active?'ÐÑÑановиÑÑ':'ÐклÑÑиÑÑ')+'"><i class="fa-solid fa-robot"></i> <span class="title">'+(data.active?'ÐкÑивен':'ÐÑÑановлен')+'</span></button></div>')); 11 }); 12 } 13 }); 14 } else if (settings && settings.url && settings.url.indexOf("/pl/tasks/resp/model-view?id=") > -1 && (new URLSearchParams(settings.url)).has('withHistory') && xhr.responseJSON.success && xhr.responseJSON.data.title === "app\\modules\\talks\\models\\Conversation") { 15 setTimeout(()=>{ 16 const startIndex = xhr.responseJSON.data.html.indexOf("id=\"gc-conversation-widget-") + 4; 17 const endIndex = xhr.responseJSON.data.html.indexOf("\"", startIndex); 18 const conversationWidgetId = xhr.responseJSON.data.html.substring(startIndex, endIndex); 19 const conversationId = $(`#${conversationWidgetId} .comments-tree`).data('tree-id').split('-')[2]; 20 $.get('/chtm/app/filebrainpro/~filebrain-get-bot-messages?conversationId='+conversationId, '', function (data){ 21 if (data.success && Array.isArray(data.messages) && data.messages.length > 0) { 22 const $mainContainer = $(`<div class="filebrainpro new-messages" data-conversationId="${conversationId}"><span class="title">ÐодеÑаÑÐ¸Ñ FileBrain</span><div class="paging" style="display: none;"><button class="move-left"><i class="fa-solid fa-angle-left"></i></button><div class="state"></div><button class="move-right"><i class="fa-solid fa-angle-right"></i></button></div><button class="toggler"><i class="fa-solid fa-robot"></i> <span class="title">ÐÑÑÑ ÑообÑÐµÐ½Ð¸Ñ Ð¾Ñ ÐÐ</span></button></div>`); 23 for (let i = 0; i < data.messages.length; ++i) { 24 $mainContainer.append($(`<div class="m" style="display: none;" data-id="${escapeHTML(data.messages[i].id)}" data-transports="${escapeHTML(JSON.stringify(data.messages[i].transportsIds))}" data-forceEmails="${escapeHTML(JSON.stringify(data.messages[i].forceEmails))}"><div class="txt"><span class="dt">${(new Date(data.messages[i].createdAt)).toLocaleString(window.language)}</span><p>${escapeHTML(data.messages[i].text)}</p></div><div class="ctrls"><button class="accept">ÐÑинÑÑÑ</button><button class="insert">ÐÑÑавиÑÑ <i class="fa-solid fa-angle-down"></i></button><button class="decline">ÐÑклониÑÑ</button></div></div>`)); 25 } 26 $(`#${conversationWidgetId} .new-comment`).prepend($mainContainer); 27 resizeWindow(); 28 } 29 }); 30 }); 31 } 32}); 33$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.toggler', function(){ 34 const $paging = $(this).siblings('.paging'); 35 if ($paging.is(":hidden")) { 36 $paging.show(); 37 $(this).next('.m').show(); 38 $paging.find('.state').text(`1 / ${$(this).siblings('.m').length}`); 39 } else { 40 $paging.hide(); 41 $(this).siblings('.m').hide(); 42 } 43 resizeWindow(); 44}); 45$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.move-left', function(){ 46 const $paging = $(this).parent('.paging'); 47 const $current = $paging.siblings('.m:visible'); 48 const $prev = $current.prev('.m'); 49 if ($prev.length) { 50 $current.hide(); 51 $prev.show(); 52 $paging.find('.state').text(`${$current.prevAll('.m').length} / ${$paging.siblings('.m').length}`); 53 } 54 resizeWindow(); 55}); 56$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.move-right', function(){ 57 const $paging = $(this).parent('.paging'); 58 const $current = $paging.siblings('.m:visible'); 59 const $next = $current.next('.m'); 60 if ($next.length) { 61 $current.hide(); 62 $next.show(); 63 $paging.find('.state').text(`${$next.prevAll('.m').length + 1} / ${$paging.siblings('.m').length}`); 64 } 65 resizeWindow(); 66}); 67$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.insert', function(){ 68 const $container = $(this).parents('.new-comment');
69 const $m = $(this).parents('.m'); 70 $container.find('.new-comment-textarea').val($m.find('.txt p').text()).trigger('input').focus()[0].setSelectionRange(0, 0); 71 72 const transports = $m.data('transports'); 73 $container.find('input[name="message_type[]"]').each(function(idx, el){ 74 $(el).prop('checked', transports.indexOf(parseInt($(el).val(), 10)) > -1); 75 }); 76 77 resizeWindow(); 78}); 79function removeModerationMessage($m) { 80 const $paging = $m.siblings('.paging'); 81 if ($m.next('.m').length) { 82 $m.next('.m').show(); 83 } else if ($m.prev('.m').length) { 84 $m.prev('.m').show(); 85 } 86 $m.remove(); 87 88 const $current = $paging.siblings('.m:visible'); 89 if ($current.length) { 90 $paging.find('.state').text(`${$current.prevAll('.m').length + 1} / ${$paging.siblings('.m').length}`); 91 } else { 92 $paging.parents('.filebrainpro').remove(); 93 } 94 resizeWindow(); 95} 96$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.accept', function(){ 97 const $m = $(this).parents('.m'); 98 $.get('/chtm/app/filebrainpro/~filebrain-accept-bot-message?id='+$m.data('id'), '', function (data){ 99 if (data.success) { 100 removeModerationMessage($m); 101 } 102 }); 103}); 104$(document).on('click', '.resp-content-body .filebrainpro.new-messages button.decline', function(){ 105 const $m = $(this).parents('.m'); 106 $.get('/chtm/app/filebrainpro/~filebrain-decline-bot-message?id='+$m.data('id'), '', function (data){ 107 if (data.success) { 108 removeModerationMessage($m); 109 } 110 }); 111}); 112$(document).on('click', '.gc-right-active-block .user-avatar .filebrainpro button', function(){ 113 const $self = $(this); 114 const $fbpStatus = $self.parents('.filebrainpro'); 115 const userId = $fbpStatus.attr('data-userId'); 116 const newStatus = $fbpStatus.hasClass('stopped'); 117 $.get('/chtm/app/filebrainpro/~filebrain-update-bot-status?userId='+userId+'&active='+newStatus, '', function (data){ 118 if (data.success) { 119 $fbpStatus.toggleClass('active', data.active).toggleClass('stopped', !data.active); 120 $fbpStatus.find('.title').text(data.active?'ÐкÑивен':'ÐÑÑановлен'); 121 $self.attr('title', data.active?'ÐÑÑановиÑÑ':'ÐклÑÑиÑÑ'); 122 } 123 }); 124}); 125})(); 126$(function(){ 127 if (window.gcSessionId > 0 && window.webinar && typeof isAdmin === 'boolean' && isAdmin === false) { 128 var webinarStartDate = null; 129 $.get('/pl/webinar/show/teaser', {id: window.webinar.id}, function (data, status){ 130 if (status == 'success') { 131 var finishDate = data.match(/finishDate[\s]*=[\s]*"([^"]+)"/); 132 if (finishDate) { 133 var a = finishDate[1].split(/[^0-9]/); 134 if (a[2] > 2000) { 135 webinarStartDate = new Date(Date.UTC(a[2],a[1]-1,a[0],a[3] - (typeof window.dateOffset === 'number'?window.dateOffset:3),a[4], a[5] ? a[5] : 0 )); 136 } else { 137 webinarStartDate = new Date(Date.UTC(a[0],a[1]-1,a[2],a[3] - (typeof window.dateOffset === 'number'?window.dateOffset:3),a[4], a[5] ? a[5] : 0 )); 138 } 139 } 140 } 141 }); 142 const messagesCache = {}; 143 // Ðовим оÑпÑавлÑемÑе ÑообÑÐµÐ½Ð¸Ñ Ð¸ кладÑм в кÑÑ, ÑÑÐ¾Ð±Ñ Ð² поÑледÑÑвии иÑклÑÑиÑÑ Ð´Ñбли 144 const catchComment = function (event) { 145 const keycode = event.keyCode ? event.keyCode : event.which; 146 const comment = document.querySelector('#comment_form input').value.trim(); 147 148 if (comment !== "" && (event.type === 'mousedown' || (event.type === 'keydown' && (keycode === 13 || event.key === 'Enter')))) { 149 messagesCache[Date.now()] = comment; 150 } 151 }; 152 document.querySelector('#comment_form a.webinar-btn-send').addEventListener('mousedown', catchComment); 153 document.querySelector('#comment_form input').addEventListener('keydown', catchComment); 154 155 const isCachedMessage = function(txt){ 156 for (const tm in messagesCache) { 157 if (tm + 60000 > Date.now() && txt === messagesCache[tm]) { 158 delete messagesCache[tm]; 159 return true; 160 } 161 } 162 return false; 163 } 164 // ÐÑпÑавлÑем на обÑабоÑÐºÑ Ñе ÑообÑениÑ, коÑоÑÑе подÑвеÑÐ¶Ð´ÐµÐ½Ñ Ð² WebSocket 165 var wsio = window.webinarSocketIo; 166 wsio.addCallback(wsio.getActions().ADD_MESSAGE, function (json) { 167 if ('actionType' in json && json.actionType == 'addMessage' && 168 json.sessionId && json.sessionId == window.gcSessionId && isCachedMessage(json.text.trim())) { 169 if (!json.realUserId && window.accountUserId) { 170 json.realUserId = window.accountUserId; 171 } 172 $.ajax(`/chtm/app/filebrainpro/hooks~addedWebinarMessage`, { 173 data: JSON.stringify({webinarId: window.webinar.id, webinarStatus: window.webinar.status, gcUniqId:
173window.gcUniqId, sign: window.webinar.sign, webinarStartDate: webinarStartDate, event: json}), 174 contentType : 'application/json', 175 type : 'POST' 176 }); 177 } 178 }); 179 window.fbpWebinarIntention = function(intention){ 180 const webinarStatus = window.webinar.status ?? 'connecting'; 181 $.ajax(`/chtm/app/filebrainpro/hooks~addedWebinarIntention`, { 182 data: JSON.stringify({intention: intention, webinarId: window.webinar.id, webinarStatus: webinarStatus, gcUniqId: window.gcUniqId, sign: window.webinar.sign, webinarStartDate: webinarStartDate, 183 event: {...window.webinarComments.getParams(), launchNumber: window.webinar.launchId, sessionId: window.gcSessionId}}), 184 contentType : 'application/json', 185 type : 'POST' 186 }); 187 }; 188 (function () { 189 var fbpSocket = function (ch, managerSocket) { 190 var connectionTimeout = 5000; 191 192 var channel = ch; 193 var managerSocket = managerSocket; 194 var callbacks = {}; 195 var _this = this; 196 197 var unloading = false; 198 199 var params = { 200 'randomId': window.gcUniqId, 201 }; 202 203 var host = "app.chatium.io"; 204 var socket = io.connect(host, { 205 transports: ['websocket'], 206 query: $.param(params), 207 timeout: connectionTimeout, 208 }); 209 210 window.addEventListener('beforeunload', function(event) { 211 unloading = true; 212 setTimeout(function() { unloading = false; }, 10000); 213 }); 214 215 this.restoreSocketCallbacks = function (newSocket, oldSocket) { 216 let skip = ['connect', 'connecting']; 217 for (let key in oldSocket._callbacks) { 218 let keyString = key.substring(1); 219 220 if (skip.includes(keyString)) { 221 continue; 222 } 223 224 for (let innerKey in oldSocket._callbacks[key]) { 225 let handler = oldSocket._callbacks[key][innerKey]; 226 newSocket.on(keyString, handler); 227 } 228 } 229 230 return newSocket; 231 }; 232 233 this.getActions = function () { 234 return { 235 SUBSCRIBE: 'dataSocket/subscribe', 236 WRITE: 'dataSocket/write', 237 DATA: 'dataSocket/data/' + channel, 238 }; 239 }; 240 241 this.addCallback = function (type, cb) { 242 if (!callbacks[type]) { 243 callbacks[type] = []; 244 } 245 246 callbacks[type].push(cb); 247 }; 248 249 this.callCallback = function (action, data) { 250 if (callbacks[action]) { 251 var len = callbacks[action].length; 252 253 for (var i = 0; i < len; i++) { 254 callbacks[action][i](data); 255 } 256 } 257 }; 258
259 this.getSocket = function () { 260 return socket; 261 }; 262 263 this.getManagerSocket = function () { 264 return managerSocket; 265 }; 266 267 this.subscribe = function () { 268 if (channel) { 269 socket.emit(_this.getActions().SUBSCRIBE, { 270 id: channel, 271 }); 272 } 273 }; 274 275 socket.on(_this.getActions().WRITE, function (data) { 276 _this.callCallback(_this.getActions().WRITE, data); 277 }); 278 279 socket.on(_this.getActions().DATA, function (data) { 280 _this.callCallback(_this.getActions().DATA, data); 281 }); 282 283 this.addMessage = function(params) { 284 var data = { 285 id: ch, 286 action: 'addMessage', 287 text: params.text, 288 }; 289 290 for (var p in params) { 291 data[p] = params[p]; 292 } 293 294 socket.emit(_this.getActions().WRITE, data); 295 }; 296 297 socket.on('connect', function () { 298 _this.subscribe(); 299 window.dispatchEvent(new Event('fbpWebinarBridgeSocket')); 300 }); 301 302 socket.on('reconnect', function () { 303 _this.subscribe(); 304 }); 305 306 let errorCallback = function () { 307 if (unloading) { 308 console.log('reconnect to ws canceled with unloading'); 309 return; 310 } 311 312 let newSocket = io.connect(host, { 313 transports: ['websocket'], 314 query: $.param(params), 315 timeout: connectionTimeout, 316 }); 317 318 newSocket = _this.restoreSocketCallbacks(newSocket, socket); 319 320 socket.off('connect_error', errorCallback); 321 socket.off('disconnect', errorCallback); 322 socket.disconnect(); 323 324 newSocket.on('connect', function () { 325 _this.subscribe(); 326 }); 327 328 socket = newSocket; 329 }; 330 331 socket.on('connect_error', errorCallback); 332 socket.on('disconnect', errorCallback); 333 }; 334 335 var managerSocket = function () { 336 var connectionTimeout = 5000; 337 var lastWsHost = ''; 338 var hosts = window.webinarWebsocketHosts; 339 var webinarWsPath = window.webinarWebsocketPath; 340 341 var channels = {}; 342 var packets = []; 343 var sendCounter = 0; 344 var _this = this; 345 var socket = null; 346 347 var params = null; 348 349 function getServerToConnect() { 350 var host = hosts[0]; 351 if (hosts.indexOf(lastWsHost) !== -1) { 352 host = hosts[hosts.indexOf(lastWsHost) + 1] 353 ? hosts[hosts.indexOf(lastWsHost) + 1] 354 : hosts[0]; 355 } 356 357 lastWsHost = host; 358 console.log('selected ws server: ' + host); 359 return host; 360 }; 361 362 var host = getServerToConnect(); 363 364 var connectCallback = function () { 365 for (var i in channels) { 366 socket.emit(_this.getActions().JOIN, { 367 channel: i, 368 sign: params.sign, 369 }); 370 } 371 while (packets.length > 0) { 372 const packet = packets.shift(); 373 if (packet.action == _this.getActions().ADD_MESSAGE) { 374 ++sendCounter; 375 _this.addMessage(packet.data); 376 } else if (packet.action == _this.getActions().BAN) { 377 ++sendCounter; 378 _this.ban(packet.data); 379 } else if (packet.action == _this.getActions().UN_BAN) { 380 ++sendCounter; 381 _this.unBan(packet.data); 382 } else if (packet.action == _this.getActions().UPDATE) { 383 ++sendCounter; 384 _this.update(packet.data); 385 } 386 } 387 }; 388 389 var disconnectCallback = function (data) { 390 if (packets.length > 0) { 391 _this.run(params); 392 } 393 }; 394 395 var disconnectOnLastPacket = function(data){ 396 if (data.ackSign === 'messageSent' || data.userId == params.userId && data.sessionId == params.sessionId) { 397 --sendCounter; 398 console.log('dec sendCounter:', sendCounter); 399 if (packets.length == 0 && sendCounter <= 0) { 400 socket.disconnect(); 401 } 402 } 403 }; 404 405 var errorCallback = function (data) { 406 console.log('websocket error:', data); 407 socket.disconnect(); 408 socket = null; 409 host = getServerToConnect(); 410 _this.run(params); 411 }; 412 413 this.addPacket = function (packet) { 414 if (Array.isArray(packet)) { 415 packets = packets.concat(packet); 416 } else if (packet) { 417 packets.push(packet); 418 } 419 }; 420 421 this.run = function (p) { 422 params = p; 423 if (socket === null || !socket.connected) { 424 socket = io.connect(host, { 425 transports: ['websocket'], 426 path: webinarWsPath, 427 query: $.param(params), 428 timeout: connectionTimeout, 429 }); 430 socket.on('connect', connectCallback); 431 socket.on('disconnect', disconnectCallback); 432 socket.on('connect_error', errorCallback); 433 socket.on(_this.getActions().ADD_MESSAGE, disconnectOnLastPacket); 434 socket.on(_this.getActions().UPDATE, disconnectOnLastPacket); 435 socket.on(_this.getActions().UN_BAN, disconnectOnLastPacket); 436 socket.on(_this.getActions().BAN, disconnectOnLastPacket); 437 } else { 438 connectCallback(); 439 } 440 }; 441 442 this.getActions = function () { 443 return { 444 JOIN: 'join', 445 UPDATE: 'update', 446 ADD_MESSAGE: 'addMessage', 447 UN_BAN: 'unBan', 448 BAN: 'Ban', 449 }; 450 }; 451
452 this.getSocket = function () { 453 return socket; 454 }; 455 456 this.addChannel = function (channel) { 457 if (!channels[channel]) { 458 channels[channel] = channel; 459 } 460 }; 461 462 this.update = function(d) { 463 var data = { 464 channel: _this.getPublicChannel(), 465 sign: params.sign, 466 ackSign: 'messageSent' 467 }; 468 469 for (var p in d) { 470 data[p] = d[p]; 471 } 472 473 socket.emit(_this.getActions().UPDATE, data); 474 }; 475 476 this.addMessage = function(d) { 477 var data = { 478 channel: _this.getPublicChannel(), 479 text: d.text, 480 sign: params.sign, 481 launchId: params.launchId, 482 isIsolatedCommentsFixFeatureEnabled: true, 483 ackSign: 'messageSent' 484 }; 485 486 for (var p in d) { 487 data[p] = d[p]; 488 } 489 490 socket.emit(_this.getActions().ADD_MESSAGE, data); 491 }; 492 493 this.unBan = function(d) { 494 var data = { 495 channel: _this.getModerationChannel(), 496 sign: params.sign, 497 ackSign: 'messageSent' 498 }; 499 500 for (var p in d) { 501 data[p] = d[p]; 502 } 503 504 socket.emit(_this.getActions().UN_BAN, data); 505 }; 506 507 this.ban = function(d) { 508 var data = { 509 channel: _this.getModerationChannel(), 510 sign: params.sign, 511 ackSign: 'messageSent' 512 }; 513 514 for (var p in d) { 515 data[p] = d[p]; 516 } 517 518 socket.emit(_this.getActions().BAN, data); 519 }; 520 521 this.getPublicCommonChannel = function() { 522 return 'public_' + window.webinar.id; 523 } 524 525 this.getPublicChannel = function() { 526 return 'public_' + window.webinar.id + '_' + window.webinar.launchId; 527 }; 528 529 this.getPublicAutoChannel = function() { 530 return 'public_auto_' + window.webinar.id + '_' + window.webinar.launchId; 531 }; 532 533 this.getModerationChannel = function() { 534 return 'moderation_' + window.webinar.id + '_' + window.webinar.launchId; 535 }; 536 537 this.getPrivateSessionChannel = function () { 538 return 'private_session_' + params.gcSessionId; 539 } 540 541 this.getPrivateUserChannel = function () { 542 if (params.userId > 0) { 543 return 'private_user_' + params.userId; 544 } 545 546 return null; 547 }; 548 }; 549 550 (async function() { 551 await fetch(`/chtm/app/filebrainpro/hooks~webinar-manager-socket?gcUniqId=${window.gcUniqId}`).then(res => res.json()).then((data) => { 552 if (data.channel) { 553 window.fbpWebinarBridge = new fbpSocket(data.channel, new managerSocket()); 554 window.fbpWebinarBridge.addCallback(window.fbpWebinarBridge.getActions().DATA, function(dt){ 555 const ms = window.fbpWebinarBridge.getManagerSocket(); 556 ms.addChannel(ms.getPublicChannel()); 557 ms.addChannel(ms.getModerationChannel()); 558 ms.addPacket(dt.packet); 559 ms.run(dt.params); 560 }); 561 } 562 }); 563 })(); 564 })(); 565 } 566});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.