// ==UserScript== // @id 4pda.ru-QMS-RTC@scriptish // @name 4pdaQmsRtc // @version 1.2 // @namespace https://greasyfork.org/users/23 // @author kilowatt36@4pda.ru // @description Добавляет возможность передачи файлов напрямую между пользователями на сайте 4pda.ru // @require https://cdn.firebase.com/js/client/1.0.6/firebase.js // @require https://greasyfork.org/scripts/348/code.user.js // @include http://4pda.ru/forum/index.php?act=qms* // @run-at document-end // @downloadURL none // ==/UserScript== var $ = unsafeWindow.$; // нужен jQuery именно из библиотеки QMS, потому что потребуется управлять событиями, связанными с ajax window.Firebase = Firebase; // в библиотеке RTCMultiConnection автор обращается не к Firebase, а к window.Firebase. Так что вот так. var connection; var iwanttosendfile = false; var sessions = { }; var progressHelper = { }; function printToChat(title, text) {// добавление ложного "нового сообщения" в чат var new_row = $( '
'+ ''+ '
'+(new Date())+'
'+ ''+title+'
'+ '
'+ (typeof text === 'string' ? text : '')+ '
'+ '
' ); if (typeof text !== 'string') new_row.find('.msg-content').append(text); $('#scroll-thread .scrollframe-body .list-group-item').last().after(new_row); var pieces = $('#scroll-thread .scrollframe-body').css('transform').split(' '); // нужно pieces[5]=(pieces[5].split(')')[0] - 50)+')'; // для $('#scroll-thread .scrollframe-body').css('transform',pieces.join(' ')); // прокрутки } function HangHandlers_dialog() { // Создать UI и повесить все необходимые обработчики на экране диалога var inputFile = $(''); var button = $(''); $('#btn-bb-codes').before('Отправить файл: ').before(inputFile).before(button); button.click(function() { // Нажатие на кнопку "отправить" if (Object.getOwnPropertyNames(connection.peers).length === 1) { // Если еще ни одной сессии не было создано, создание сессии, после которой автоматом пойдет отправка файла var sessionName = '4pdaSession'; connection.extra = { 'session-name': sessionName || 'Anonymous' }; connection.sessionid = sessionName || 'Anonymous'; connection.maxParticipantsAllowed = 1; printToChat('Отправка файла', 'Ожидание соединения с собеседником...'); connection.open(connection.channel); iwanttosendfile = true; } else {// если сессия уже есть, просто отправить connection.send($('#4pdaQmsRTC')[0].files[0]); } }); $('.icon-back-up').click(HangHandlers_topicchoise); // При щелчке на возврат надо опять расставлять обработчики } function HangHandlers_topicchoise() { // Повесить все необходимые обработчики на экране выбора темы $(document).ajaxComplete(function() { // Чтобы повесить событие на НОВЫЙ список тем, который загрузится через ajax $('#threads-form .list-group-item.text-overflow').each(function(){ $(this).click(function() { // щелчок по теме $(document).ajaxComplete(function() { // После загрузки окна диалога HangHandlers_dialog(); $(document).off('ajaxComplete'); }); }); }); $(document).off('ajaxComplete'); // чтобы функция выше больше не срабатывала при каждом ajax запросе }); } function createConnection(peer) { // создание нового connection в соответствии с id собеседника connection = new RTCMultiConnection([peer, $('.i-code').attr('href').split('=')[1]].sort().join('_')); connection.session = { data: true }; connection.autoSaveToDisk = false; sessions = { }; progressHelper = { }; iwanttosendfile = false; connection.onNewSession = function(session) { if (sessions[session.sessionid]) return; sessions[session.sessionid] = session; console.log('new session: '+session.extra['session-name']); connection.join(session); // при каждом создании сессии присоединяемся к ней, не спрашивая разрешения (это же удобно!) }; connection.onmessage = function(e) { console.debug(e.userid, 'posted', e.data); console.log('latency:', e.latency, 'ms'); }; connection.onclose = function(e) { console.log('Data connection is closed between you and ' + e.userid); }; connection.onleave = function(e) { console.log(e.userid + ' left the session.'); }; // когда собеседник подтверждает наш запрос на присоединение к сесси (а это делается автоматически) connection.onopen = function() { if (iwanttosendfile) { connection.send($('#4pdaQmsRTC')[0].files[0]); $('#4pdaQmsRTC').val(''); } iwanttosendfile = false; //console.log('connection.onopen'); }; function updateLabel(progress, label) { if (progress.position == -1) return; var position = +progress.position.toFixed(2).split('.')[1] || 100; label.innerHTML = position + '%'; } connection.onFileProgress = function(chunk) { var helper = progressHelper[chunk.uuid]; helper.progress.value = chunk.currentPosition || chunk.maxChunks || helper.progress.max; updateLabel(helper.progress, helper.label); }; connection.onFileStart = function(file) { var div = document.createElement('div'); div.title = file.name; div.innerHTML = ' '; printToChat('Передача файла',div); progressHelper[file.uuid] = { div: div, progress: div.querySelector('progress'), label: div.querySelector('#RTCLabel') }; progressHelper[file.uuid].progress.max = file.maxChunks; }; connection.onFileEnd = function(file) { progressHelper[file.uuid].div.innerHTML = '' + file.name + ''; }; connection.connect(connection.channel); } /////////////////////////////// MAIN //////////////////////////////////////////// /* у firebase такая замечательна клиентская библиотека. Создает в документе скрытый iframe и грузит туда скрипт, вызывающий parent.window["somefunc"] Просто офигеть. Так что надо сделать перенаправлялочку для этих функций. (требуется только для работоспособности в юзерскрипте) */ function inject_FbFunctions(funcnum) { if (typeof(window["pLPCommand"+funcnum]) == 'function' && typeof(window["pRTLPCB"+funcnum]) == 'function') { unsafeWindow.window["pLPCommand"+funcnum] = window["pLPCommand"+funcnum]; unsafeWindow.window["pRTLPCB"+funcnum] = window["pRTLPCB"+funcnum]; //console.log(funcnum+" ready"); } else setTimeout(function(){inject_FbFunctions(funcnum);},50); } for (var i=1; i<8; i++) { inject_FbFunctions(i); } // Если пользователь зашел сразу на страницу диалога или выбора темы, то сразу создаем соединение. if (location.href.indexOf("&mid=") != -1) { createConnection(location.href.split("&mid=")[1].split("&")[0]); if (location.href.indexOf("&t=") != -1) { HangHandlers_dialog(); } else { HangHandlers_topicchoise(); } } else { createConnection('4pda-temp'); } // При щелчке на пользователя слева пусть создается соединение с этим пользователем. $('#contacts .list-group-item.text-overflow').each(function(){ $(this).click(function() { // Щелчок по имени пользователя var peer = $(this).attr('data-member-id'); createConnection(peer); if (peer > 0) { HangHandlers_topicchoise(); } }); });