IP.Chat Logs

Keep and manage IRC-like logs for IP.Chat clients.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name	IP.Chat Logs
// @namespace	Makaze
// @include	*
// @grant	none
// @version	1.3.2
// @description Keep and manage IRC-like logs for IP.Chat clients.
// ==/UserScript==

var IPChatMenuItems,
menuButton,
logs,
CAPACITY = 5242880,
filled = 0,
occupied = 0,
i = 0;

// Classes constructor

function ClassHandler() {
	var self = this;

	this.classList = function(elem) {
		return elem.className.trim().split(/[\b\s]/);
	};

	this.hasClass = function(elem, className) {
		var classes = self.classList(elem),
		has = false,
		i = 0;

		for (i = 0; i < classes.length; i++) {
			if (classes[i] === className) {
				has = true;
				break;
			}
		}

		return (has);
	};

	this.addClass = function(elem, className) {
		var classes;

		if (!self.hasClass(elem, className)) {
			classes = self.classList(elem);
			classes.push(className);
			elem.className = classes.join(' ').trim();
		}

		return self;
	};

	this.removeClass = function(elem, className) {
		var classes = self.classList(elem),
		i = 0;

		for (i = 0; i < classes.length; i++) {
			if (classes[i] === className) {
				classes.splice(i, 1);
			}
		}

		elem.className = classes.join(' ').trim();

		return self;
	};

	this.toggleClass = function(elem, className) {
		var classes;

		if (self.hasClass(elem, className)) {
			self.removeClass(elem, className);
		} else {
			classes = self.classList(elem);
			classes.push(className);
			elem.className = classes.join(' ').trim();
		}

		return self;
	};
}

// Initialize

var Classes = new ClassHandler();

// End Classes constructor

function dateAndTime(which) {
	var currentdate = new Date(),
	output;

	which = which || 'default';
	
	switch (which) {
		case 'time':
			output = ((currentdate.getHours() < 10) ? '0' + currentdate.getHours() : currentdate.getHours()) + ":"
				+ ((currentdate.getMinutes() < 10) ? '0' + currentdate.getMinutes() : currentdate.getMinutes()) + ":"
				+ ((currentdate.getSeconds() < 10) ? '0' + currentdate.getSeconds() : currentdate.getSeconds());
		break;
		case 'date':
			output = (((currentdate.getMonth() + 1) < 10) ? '0' + (currentdate.getMonth() + 1)  : (currentdate.getMonth() + 1)) + "/"
				+ ((currentdate.getDate() < 10) ? '0' + currentdate.getDate() : currentdate.getDate()) + "/"
				+ currentdate.getFullYear();
		break;
		default:
			output = ((currentdate.getHours() < 10) ? '0' + currentdate.getHours() : currentdate.getHours()) + ":"
				+ ((currentdate.getMinutes() < 10) ? '0' + currentdate.getMinutes() : currentdate.getMinutes()) + ":"
				+ ((currentdate.getSeconds() < 10) ? '0' + currentdate.getSeconds() : currentdate.getSeconds())
				+ ' on '
				+ (((currentdate.getMonth() + 1) < 10) ? '0' + (currentdate.getMonth() + 1)  : (currentdate.getMonth() + 1)) + "/"
				+ ((currentdate.getDate() < 10) ? '0' + currentdate.getDate() : currentdate.getDate()) + "/"
				+ currentdate.getFullYear();
	}
	return output;
}

function empty(elem) {
	while (elem.hasChildNodes()) {
		elem.removeChild(elem.lastChild);
	}
}

function createElement(type, callback) {
	var element = document.createElement(type);

	callback(element);

	return element;
}

function roundToNthDecimal(d, n) {
	return Math.round(d * Math.pow(10, n)) / Math.pow(10, n);
}

function fade(elem, type, speed) {
	var defaultOpacity,
	currentDisplay = elem.style.display || window.getComputedStyle(elem).display;

	elem.style.opacity = '';
	defaultOpacity = window.getComputedStyle(elem).opacity;
	elem.style.opacity = 0;

	// Default values:

	switch (arguments.length) {
		case 1:
			type = 'toggle';
		case 2:
			speed = 300;
		break;
	}

	switch (type) {
		case 'in':
			elem.style.display = '';
			setTimeout(function() {
				elem.style.transition = 'all ' + speed + 'ms ease-in-out';
				elem.style.opacity = defaultOpacity;
				setTimeout(function() {
					elem.style.transition = '';
					elem.style.opacity = '';
				}, speed + 10);
			}, 1);
		break;
		case 'out':
			elem.style.transition = '';
			elem.style.opacity = defaultOpacity;
			elem.style.transition = 'all ' + speed + 'ms ease-in-out';
			elem.style.opacity = 0;
			setTimeout(function() {
				elem.style.display = 'none';
				elem.style.transition = '';
				elem.style.opacity = '';
			}, speed + 10);
		break;
		case 'toggle':
		default:
			if (currentDisplay === 'none') {
				elem.style.display = '';
				setTimeout(function() {
					elem.style.transition = 'all ' + speed + 'ms ease-in-out';
					elem.style.opacity = defaultOpacity;
					setTimeout(function() {
						elem.style.transition = '';
						elem.style.opacity = '';
					}, speed + 10);
				}, 1);
			} else {
				elem.style.transition = '';
				elem.style.opacity = defaultOpacity;
				elem.style.transition = 'all ' + speed + 'ms ease-in-out';
				elem.style.opacity = 0;
				setTimeout(function() {
					elem.style.display = 'none';
					elem.style.transition = '';
					elem.style.opacity = '';
				}, speed + 10);
			}
	}
}

function createLog(logs, i) {
	return createElement('div', function(el) {
		el.className = 'log';

		el.appendChild(createElement('div', function(del) {
			del.className = 'delete';
			del.appendChild(document.createTextNode('Delete'));
			del.onclick = function() {
				deleteLog(this.parentNode, logs[i].initiated);
			};
		}));

		el.appendChild(document.createTextNode('-----\nLog started at [' + logs[i].initiated + ']\n-----\n'));

		el.appendChild(createElement('span', function(content) {
			content.innerHTML = logs[i].log;
		}));
	});
}

function deleteLog(logElement, date) {
	var logs = JSON.parse(localStorage.getItem('IP.Chat Logs')),
	CAPACITY = 5242880,
	filled = 0;

	var confirmContent = createElement('span', function(cont) {
		cont.appendChild(document.createTextNode('Are you sure? '));

		cont.appendChild(createElement('a', function(yes) {
			yes.id = 'yes';
			yes.href = 'javascript:void(0)';
			yes.appendChild(document.createTextNode('[Yes]'));
			yes.onclick = function() {
				var i = 0;

				document.getElementById('confirm').style.opacity = 0;
				document.getElementById('screen').style.opacity = 0;
				setTimeout(function() {
					document.getElementById('confirm').style.display = 'none';
					document.getElementById('screen').style.display = 'none';
				}, 300);

				for (i = 0; i < logs.length; i++) {
					if (logs[i].initiated === date) {
						logs.splice(i, 1);
						localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));
						break;
					}
				}

				for (i = 0; i < localStorage.length; i++) {
					filled += localStorage.getItem(localStorage.key(i)).length;
				}
				occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
				document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';

				logElement.className = logElement.className + ' deleted';
				if (logElement.nextSibling) {
					logElement.nextSibling.remove();
				} else {
					logElement.previousSibling.remove();
				}
				setTimeout(function() {
					logElement.remove();
				}, 500);
			};
		}));

		cont.appendChild(document.createTextNode(' '));

		cont.appendChild(createElement('a', function(no) {
			no.id = 'no';
			no.href = 'javascript:void(0)';
			no.appendChild(document.createTextNode('[Cancel]'));
			no.onclick = function() {
				document.getElementById('confirm').style.opacity = 0;
				document.getElementById('screen').style.opacity = 0;
				setTimeout(function() {
					document.getElementById('confirm').style.display = 'none';
					document.getElementById('screen').style.display = 'none';
				}, 300);
			};
		}));
	});

	empty(document.getElementById('confirm'));

	document.getElementById('confirm').appendChild(confirmContent);

	document.getElementById('screen').style.display = 'block';
	document.getElementById('confirm').style.display = 'block';
	setTimeout(function() {
		document.getElementById('screen').style.opacity = 1;
		document.getElementById('confirm').style.opacity = 1;
	}, 1);
}

function deleteAllLogs() {
	var CAPACITY = 5242880,
	filled = 0,
	logElement;

	var confirmContent = createElement('span', function(cont) {
		cont.appendChild(document.createTextNode('Are you sure? '));

		cont.appendChild(createElement('a', function(yes) {
			yes.id = 'yes';
			yes.href = 'javascript:void(0)';
			yes.appendChild(document.createTextNode('[Yes]'));
			yes.onclick = function() {
				var i = 0;
				document.getElementById('confirm').style.opacity = 0;
				document.getElementById('screen').style.opacity = 0;
				setTimeout(function() {
					document.getElementById('confirm').style.display = 'none';
					document.getElementById('screen').style.display = 'none';
				}, 300);

				localStorage.removeItem('IP.Chat Logs');

				for (i = 0; i < localStorage.length; i++) {
					filled += localStorage.getItem(localStorage.key(i)).length;
				}
				occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
				document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';

				var waitHandler = function() {
					logElement.remove();
				};

				for (i = 0; i < document.getElementsByClassName('log').length; i++) {
					logElement = document.getElementsByClassName('log')[i];
					logElement.className = logElement.className + ' deleted';
					if (logElement.nextSibling) {
						logElement.nextSibling.remove();
					} else {
						logElement.previousSibling.remove();
					}
					setTimeout(waitHandler, 500);
				}
			};
		}));

		cont.appendChild(document.createTextNode(' '));

		cont.appendChild(createElement('a', function(no) {
			no.id = 'no';
			no.href = 'javascript:void(0)';
			no.appendChild(document.createTextNode('[Cancel]'));
			no.onclick = function() {
				document.getElementById('confirm').style.opacity = 0;
				document.getElementById('screen').style.opacity = 0;
				setTimeout(function() {
					document.getElementById('confirm').style.display = 'none';
					document.getElementById('screen').style.display = 'none';
				}, 300);
			};
		}));
	});

	empty(document.getElementById('confirm'));

	document.getElementById('confirm').appendChild(confirmContent);

	document.getElementById('screen').style.display = 'block';
	document.getElementById('confirm').style.display = 'block';
	setTimeout(function() {
		document.getElementById('screen').style.opacity = 1;
		document.getElementById('confirm').style.opacity = 1;
	}, 1);
}

if (document.body.id === 'ipboard_body' && document.getElementById('chat-form') != null) {
	var nick,
	curr,
	append = '';

	logs = (localStorage.getItem('IP.Chat Logs')) ? JSON.parse(localStorage.getItem('IP.Chat Logs')) : [];

	for (i = 0; i < localStorage.length; i++) {
		filled += localStorage.getItem(localStorage.key(i)).length;
	}

	if (filled + JSON.stringify({'initiated': dateAndTime(), 'log': ''}).length >= CAPACITY) {
		logs.splice(0, 1);
	}

	logs.push({'initiated': dateAndTime(), 'log': ''});

	localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));

	document.addEventListener('DOMNodeInserted', function(event) {
		if (event.target.nodeType !== 1 || event.target.id !== 'storage_chatroom') {
			return false;
		}

		var latestMessage,
		latestMessageText,
		logs = JSON.parse(localStorage.getItem('IP.Chat Logs')),
		CAPACITY = 5242880,
		filled = 0,
		i = 0;

		latestMessage = event.target.parentNode.getElementsByTagName('div')[event.target.parentNode.getElementsByTagName('div').length - 1];

		if (!Classes.hasClass(latestMessage.parentNode, 'post')) {
			return false;
		}

		latestMessageText = latestMessage.innerHTML.replace(/<br>/gi, '<br>\t');

		if (!latestMessageText.length) {
			return false;
		}

		nick = null;

		if (Classes.hasClass(latestMessage.parentNode, 'chat-moderator')) {
			if (latestMessage.parentNode.getElementsByTagName('label')[0] != null) {
				nick = latestMessage.parentNode.getElementsByTagName('label')[0].innerHTML;
			} else {
				nick = '';
			}
		}

		curr = latestMessage.parentNode;

		while (nick === null) {
			if (curr.getElementsByTagName('label').length) {
				nick = curr.getElementsByTagName('label')[0].innerHTML;
			} else {
				curr = curr.previousSibling;
			}
		}

		for (i = 0; i < localStorage.length; i++) {
			filled += localStorage.getItem(localStorage.key(i)).length;
		}

		if (Classes.hasClass(latestMessage.parentNode, 'chat-me')) {
			append = '\n[' + dateAndTime('time') + '] **' + nick + ' ' + latestMessageText.substr(2, latestMessageText.length - 4) + '**';
		} else if (Classes.hasClass(latestMessage.parentNode, 'chat-notice')) {
			append = '\n[' + dateAndTime('time') + '] ' + nick + ' ' + latestMessageText.substr(2, latestMessageText.length - 2);
		} else if (Classes.hasClass(latestMessage.parentNode, 'chat-message')) {
			append = '\n[' + dateAndTime('time') + '] ' + nick + ': ' + latestMessageText;
		} else {
			if (nick.length) {
				append = '\n[' + dateAndTime('time') + '] ' + nick + ' ' + latestMessageText;
			} else {
				append = '\n[' + dateAndTime('time') + '] ' + latestMessageText;
			}
		}

		logs[logs.length - 1].log += append;

		if (filled + append.length >= CAPACITY) {
			logs.splice(0, 1);
		}
		localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));
	});

	if (document.getElementById('IPChatMenuItems') == null) {
		IPChatMenuItems = createElement('div', function(menu) {
			menu.id = 'IPChatMenuItems';
			menu.style.textAlign = 'right';
		});
		document.getElementById('chatters-online-wrap').nextSibling.nextSibling.getElementsByTagName('ul')[0].appendChild(IPChatMenuItems);
	}

	if (document.getElementById('IPChatMenuItems').hasChildNodes()) {
		document.getElementById('IPChatMenuItems').appendChild(document.createElement('br'));
	}

	menuButton = createElement('a', function(button) {
		button.id = 'viewIPChatLogs';
		button.className = 'ipsButton_secondary';
		button.href = window.location.origin + '/IP.Chat_Logs';
		button.target = '_blank';
		button.style.marginTop = '10px';
		button.appendChild(document.createTextNode('View Logs'));
	});

	document.getElementById('IPChatMenuItems').appendChild(menuButton);
}

if (window.location.href === window.location.origin + '/IP.Chat_Logs' && localStorage.getItem('IP.Chat Logs')) {
	var style,
	funcs;

	logs = JSON.parse(localStorage.getItem('IP.Chat Logs'));

	style = createElement('style', function(el) {
		el.type = 'text/css';
		el.appendChild(document.createTextNode(
			'#screen {\n' +
				'position: fixed;\n' +
				'height: 100%;\n' +
				'width: 100%;\n' +
				'background-color: rgba(0, 0, 0, .7);\n' +
				'top: 0px;\n' +
				'left: 0px;\n' +
				'transition: all .3s ease-in-out;\n' +
				'opacity: 0;\n' +
				'display: none;\n' +
			'}\n\n' +

			'#confirm {\n' +
				'position: fixed;\n' +
				'font-size: 3em;\n' +
				'background-color: rgba(255, 255, 255, .9);\n' +
				'box-shadow: 0px 0px 3px;\n' +
				'height: 40px;\n' +
				'line-height: 40px;\n' +
				'width: 620px;\n' +
				'text-align: center;\n' +
				'top: 50%;\n' +
				'left: 50%;\n' +
				'margin-top: -32px;\n' +
				'margin-left: -350px;\n' +
				'padding: 10px 20px;\n' +
				'border-radius: 5px;\n' +
				'transition: all .3s ease-in-out;\n' +
				'opacity: 0;\n' +
				'display: none;\n' +
			'}\n\n' +

			'#space {\n' +
				'font-size: 20px;\n' +
			'}\n\n' +

			'#logs {\n' +
				'margin: 8px 0;\n' +
				'padding: 10px;\n' +
				'background-color: #fcfcfc;\n' +
			'}\n\n' +

			'#logs img.bbc {\n' +
				'vertical-align: middle;\n' +
			'}\n\n' +

			'#logs > .log {\n' +
				'transition: all .3s ease-in-out;\n' +
				'overflow: hidden;\n' +
			'}\n\n' +

			'#logs > .log:hover {\n' +
			//	'background-color: #f5f5f5;\n' +
			'}\n\n' +

			'.delete {\n' +
			//	'display: none;\n' +
				'float: right;\n' +
				'background-color: #444;\n' +
				'padding: 3px 5px;\n' +
				'color: #eee;\n' +
				'font-size: 15px;\n' +
				'letter-spacing: 2px;\n' +
				'text-transform: uppercase;\n' +
				'cursor: pointer;\n' +
			'}\n\n' +

			'.delete:hover {\n' +
				'background-color: #222;\n' +
			'}\n\n' +

			'.deleted {\n' +
				'background-color: #222 ! important;\n' +
				'color: #eee ! important;\n' +
				'font-size: 0px ! important;\n' +
			'}\n\n' +

			'.deleted > * {\n' +
				'display: none;\n' +
			'}'
		));
	});

	document.title = 'IP.Chat Logs';
	document.body.style.fontFamily = 'monospace';
	document.head.appendChild(style);

	// Body creation

	empty(document.body);

	document.body.appendChild(createElement('div', function(filter) {
		filter.id = 'screen';
	}));

	document.body.appendChild(createElement('div', function(confirm) {
		confirm.id = 'confirm';
	}));

	document.body.appendChild(createElement('div', function(space) {
		space.id = 'space';

		space.appendChild(document.createTextNode('0% full'));

		space.appendChild(createElement('span', function(delete_all) {
			delete_all.id = 'delete_all';
			delete_all.className = 'delete';
			delete_all.appendChild(document.createTextNode('Delete All'));
			delete_all.onclick = deleteAllLogs;
		}));

		space.appendChild(createElement('span', function(hide) {
			hide.id = 'hide_non-logs';
			hide.className = 'delete';
			hide.style.marginRight = '10px';
			hide.appendChild(document.createTextNode('Hide Non-Logs'));
			hide.onclick = function() {
				var i = 0,
				deletes;

				fade(document.getElementById('space'), 'out');
				for (i = 0, deletes = document.getElementsByClassName('delete'); i < deletes.length; i++) {
					fade(deletes[i], 'out');
				}
			};
		}));
	}));

	document.body.appendChild(createElement('pre', function(pre) {
		pre.id = 'logs';
	}));

	for (i = 0; i < localStorage.length; i++) {
		filled += localStorage.getItem(localStorage.key(i)).length;
	}
	occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
	document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';

	for (i = 0; i < logs.length; i++) {
		if (document.getElementById('logs').hasChildNodes()) {
			document.getElementById('logs').appendChild(document.createTextNode('\n'));
		}

		document.getElementById('logs').appendChild(createLog(logs, i));
	}
}