4pdaQmsRtc

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

Ajankohdalta 1.4.2014. Katso uusin versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @id             4pda.ru-QMS-RTC@scriptish
// @name           4pdaQmsRtc
// @version        1.0
// @namespace      https://greasyfork.org/users/23
// @author         [email protected]
// @description    Добавляет возможность передачи файлов напрямую между пользователями на сайте 4pda.ru по технологии WebRTC
// @require        http://raw.githubusercontent.com/Pmmlabs/4pdaQmsRtc/master/firebase.js
// @require        http://raw.githubusercontent.com/Pmmlabs/4pdaQmsRtc/master/RTCMultiConnection-v1.7.js
// @include        http://4pda.ru/forum/index.php?act=qms*
// @run-at         document-end
// ==/UserScript==

$ = unsafeWindow.$;			// нужен jQuery именно из библиотеки QMS, потому что потребуется управлять событиями, связанными с ajax
window.Firebase = Firebase; // в библиотеке RTCMultiConnection автор обращается не к Firebase, а к window.Firebase. Так что вот так.
var connection;
var iwanttosendfile = false;
var sessions = { };
var progressHelper = { };

function HangHandlers_dialog() {						// Создать UI и повесить все необходимые обработчики на экране диалога
	inputFile = $('<input id="4pdaQmsRTC" type=file />');
	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');
	};
	
	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>';
	};

	function updateLabel(progress, label) {
		if (progress.position == -1) return;
		var position = +progress.position.toFixed(2).split('.')[1] || 100;
		label.innerHTML = position + '%';
	}

	connection.connect(connection.channel); 
}

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(' '));		// прокрутки
}

///////////////////////////////		MAIN	////////////////////////////////////////////

/* у firebase такая замечательна клиентская библиотека.
   Создает в документе скрытый iframe и грузит туда скрипт, вызывающий parent.window["somefunc"]
   Просто офигеть. Так что надо сделать перенаправлялочку для этих функций. (требуется только для работоспособности в юзерскрипте)
*/
function inject_FbFunctions(funcname) {	
	if (typeof(window[funcname]) == 'function') {
		unsafeWindow.window[funcname] = window[funcname];
		//console.log(funcname+" ready");
	}
	else
		setTimeout(function(){inject_FbFunctions(funcname);},50);
}

firebase_functions = ["pLPCommand1","pRTLPCB1","pLPCommand2","pRTLPCB2","pLPCommand3","pRTLPCB3","pLPCommand4","pRTLPCB4","pLPCommand5","pRTLPCB5","pLPCommand6","pRTLPCB6","pLPCommand7","pRTLPCB7"];
for (i in firebase_functions) 
	inject_FbFunctions(firebase_functions[i]);

// Если пользователь зашел сразу на страницу с диалогом, то сразу создаем соединение.	
if (location.href.indexOf("&t=") != -1) {
	createConnection(location.href.split("&t=")[1].split("&")[0]);
	HangHandlers_dialog();
} 

// При щелчке на пользователя слева пусть создается соединение с этим пользователем.
  $('#contacts .list-group-item.text-overflow').each(function(){
	$(this).click(function() { // Щелчок по имени пользователя
		peer = $(this).attr('data-member-id');
		createConnection(peer);
		if (peer > 0) HangHandlers_topicchoise();
	});
});