IP.Chat Logs

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

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==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));
	}
}