PageSourceSearch

https://docstarclub.ru/chtm/app/filebrainpro/static/interface.js

js docstarclub.ru collected 2026-09-29 18:00:02 UTC 21,219 bytes, 566 lines download raw bytes

1(function(){
2const escapeHTML = function(str) { return str.replace(/[&<>'"]/g, function(tag) { return ({'&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;'}[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>&nbsp;<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>&nbsp;<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">Вставить&nbsp;<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.