4pdaQmsRtc

Добавляет возможность передачи файлов напрямую между пользователями на сайте 4pda.ru

Versión del día 03/05/2014. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @id             4pda.ru-QMS-RTC@scriptish
// @name           4pdaQmsRtc
// @version        1.2
// @namespace      https://greasyfork.org/users/23
// @author         [email protected]
// @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
// ==/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 = $(
		'<div data-toggle="checkbox" class="list-group-item">'+
		'<label class="check-item">'+
			'<input type="checkbox" data-toggle="class" data-event="change" data-event-init="1">'+
			'<span class="checkbox">'+
				'<i class="icon-uncheck"></i>'+
				'<i class="icon-check"></i>'+
			'</span>'+
		'</label>'+
		'<div class="time"><b class="read-status read big-dot"></b> '+(new Date())+' </div> <div class="avatar-wrap"><img alt="" class="avatar" data-scroll-init-load="1"></div> '+
			'<strong><span style="color:#FF9900">'+title+'</span></strong><br>'+
			'<div class="msg-content emoticons">'+
				(typeof text === 'string' ? text : '')+
			'</div>'+
		'</div>'
	);
	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 = $('<input id="4pdaQmsRTC" type=file />');
	var button = $('<button id="4pdaQmsRTCbutton">Отправить</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, $('.icon-profile').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 = '<label id="RTCLabel">0%</label> <progress></progress>';
		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 = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
	};



	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(); }
	});
});