IP.Chat Logs

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

  1. // ==UserScript==
  2. // @name IP.Chat Logs
  3. // @namespace Makaze
  4. // @include *
  5. // @grant none
  6. // @version 1.3.2
  7. // @description Keep and manage IRC-like logs for IP.Chat clients.
  8. // ==/UserScript==
  9.  
  10. var IPChatMenuItems,
  11. menuButton,
  12. logs,
  13. CAPACITY = 5242880,
  14. filled = 0,
  15. occupied = 0,
  16. i = 0;
  17.  
  18. // Classes constructor
  19.  
  20. function ClassHandler() {
  21. var self = this;
  22.  
  23. this.classList = function(elem) {
  24. return elem.className.trim().split(/[\b\s]/);
  25. };
  26.  
  27. this.hasClass = function(elem, className) {
  28. var classes = self.classList(elem),
  29. has = false,
  30. i = 0;
  31.  
  32. for (i = 0; i < classes.length; i++) {
  33. if (classes[i] === className) {
  34. has = true;
  35. break;
  36. }
  37. }
  38.  
  39. return (has);
  40. };
  41.  
  42. this.addClass = function(elem, className) {
  43. var classes;
  44.  
  45. if (!self.hasClass(elem, className)) {
  46. classes = self.classList(elem);
  47. classes.push(className);
  48. elem.className = classes.join(' ').trim();
  49. }
  50.  
  51. return self;
  52. };
  53.  
  54. this.removeClass = function(elem, className) {
  55. var classes = self.classList(elem),
  56. i = 0;
  57.  
  58. for (i = 0; i < classes.length; i++) {
  59. if (classes[i] === className) {
  60. classes.splice(i, 1);
  61. }
  62. }
  63.  
  64. elem.className = classes.join(' ').trim();
  65.  
  66. return self;
  67. };
  68.  
  69. this.toggleClass = function(elem, className) {
  70. var classes;
  71.  
  72. if (self.hasClass(elem, className)) {
  73. self.removeClass(elem, className);
  74. } else {
  75. classes = self.classList(elem);
  76. classes.push(className);
  77. elem.className = classes.join(' ').trim();
  78. }
  79.  
  80. return self;
  81. };
  82. }
  83.  
  84. // Initialize
  85.  
  86. var Classes = new ClassHandler();
  87.  
  88. // End Classes constructor
  89.  
  90. function dateAndTime(which) {
  91. var currentdate = new Date(),
  92. output;
  93.  
  94. which = which || 'default';
  95. switch (which) {
  96. case 'time':
  97. output = ((currentdate.getHours() < 10) ? '0' + currentdate.getHours() : currentdate.getHours()) + ":"
  98. + ((currentdate.getMinutes() < 10) ? '0' + currentdate.getMinutes() : currentdate.getMinutes()) + ":"
  99. + ((currentdate.getSeconds() < 10) ? '0' + currentdate.getSeconds() : currentdate.getSeconds());
  100. break;
  101. case 'date':
  102. output = (((currentdate.getMonth() + 1) < 10) ? '0' + (currentdate.getMonth() + 1) : (currentdate.getMonth() + 1)) + "/"
  103. + ((currentdate.getDate() < 10) ? '0' + currentdate.getDate() : currentdate.getDate()) + "/"
  104. + currentdate.getFullYear();
  105. break;
  106. default:
  107. output = ((currentdate.getHours() < 10) ? '0' + currentdate.getHours() : currentdate.getHours()) + ":"
  108. + ((currentdate.getMinutes() < 10) ? '0' + currentdate.getMinutes() : currentdate.getMinutes()) + ":"
  109. + ((currentdate.getSeconds() < 10) ? '0' + currentdate.getSeconds() : currentdate.getSeconds())
  110. + ' on '
  111. + (((currentdate.getMonth() + 1) < 10) ? '0' + (currentdate.getMonth() + 1) : (currentdate.getMonth() + 1)) + "/"
  112. + ((currentdate.getDate() < 10) ? '0' + currentdate.getDate() : currentdate.getDate()) + "/"
  113. + currentdate.getFullYear();
  114. }
  115. return output;
  116. }
  117.  
  118. function empty(elem) {
  119. while (elem.hasChildNodes()) {
  120. elem.removeChild(elem.lastChild);
  121. }
  122. }
  123.  
  124. function createElement(type, callback) {
  125. var element = document.createElement(type);
  126.  
  127. callback(element);
  128.  
  129. return element;
  130. }
  131.  
  132. function roundToNthDecimal(d, n) {
  133. return Math.round(d * Math.pow(10, n)) / Math.pow(10, n);
  134. }
  135.  
  136. function fade(elem, type, speed) {
  137. var defaultOpacity,
  138. currentDisplay = elem.style.display || window.getComputedStyle(elem).display;
  139.  
  140. elem.style.opacity = '';
  141. defaultOpacity = window.getComputedStyle(elem).opacity;
  142. elem.style.opacity = 0;
  143.  
  144. // Default values:
  145.  
  146. switch (arguments.length) {
  147. case 1:
  148. type = 'toggle';
  149. case 2:
  150. speed = 300;
  151. break;
  152. }
  153.  
  154. switch (type) {
  155. case 'in':
  156. elem.style.display = '';
  157. setTimeout(function() {
  158. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  159. elem.style.opacity = defaultOpacity;
  160. setTimeout(function() {
  161. elem.style.transition = '';
  162. elem.style.opacity = '';
  163. }, speed + 10);
  164. }, 1);
  165. break;
  166. case 'out':
  167. elem.style.transition = '';
  168. elem.style.opacity = defaultOpacity;
  169. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  170. elem.style.opacity = 0;
  171. setTimeout(function() {
  172. elem.style.display = 'none';
  173. elem.style.transition = '';
  174. elem.style.opacity = '';
  175. }, speed + 10);
  176. break;
  177. case 'toggle':
  178. default:
  179. if (currentDisplay === 'none') {
  180. elem.style.display = '';
  181. setTimeout(function() {
  182. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  183. elem.style.opacity = defaultOpacity;
  184. setTimeout(function() {
  185. elem.style.transition = '';
  186. elem.style.opacity = '';
  187. }, speed + 10);
  188. }, 1);
  189. } else {
  190. elem.style.transition = '';
  191. elem.style.opacity = defaultOpacity;
  192. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  193. elem.style.opacity = 0;
  194. setTimeout(function() {
  195. elem.style.display = 'none';
  196. elem.style.transition = '';
  197. elem.style.opacity = '';
  198. }, speed + 10);
  199. }
  200. }
  201. }
  202.  
  203. function createLog(logs, i) {
  204. return createElement('div', function(el) {
  205. el.className = 'log';
  206.  
  207. el.appendChild(createElement('div', function(del) {
  208. del.className = 'delete';
  209. del.appendChild(document.createTextNode('Delete'));
  210. del.onclick = function() {
  211. deleteLog(this.parentNode, logs[i].initiated);
  212. };
  213. }));
  214.  
  215. el.appendChild(document.createTextNode('-----\nLog started at [' + logs[i].initiated + ']\n-----\n'));
  216.  
  217. el.appendChild(createElement('span', function(content) {
  218. content.innerHTML = logs[i].log;
  219. }));
  220. });
  221. }
  222.  
  223. function deleteLog(logElement, date) {
  224. var logs = JSON.parse(localStorage.getItem('IP.Chat Logs')),
  225. CAPACITY = 5242880,
  226. filled = 0;
  227.  
  228. var confirmContent = createElement('span', function(cont) {
  229. cont.appendChild(document.createTextNode('Are you sure? '));
  230.  
  231. cont.appendChild(createElement('a', function(yes) {
  232. yes.id = 'yes';
  233. yes.href = 'javascript:void(0)';
  234. yes.appendChild(document.createTextNode('[Yes]'));
  235. yes.onclick = function() {
  236. var i = 0;
  237.  
  238. document.getElementById('confirm').style.opacity = 0;
  239. document.getElementById('screen').style.opacity = 0;
  240. setTimeout(function() {
  241. document.getElementById('confirm').style.display = 'none';
  242. document.getElementById('screen').style.display = 'none';
  243. }, 300);
  244.  
  245. for (i = 0; i < logs.length; i++) {
  246. if (logs[i].initiated === date) {
  247. logs.splice(i, 1);
  248. localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));
  249. break;
  250. }
  251. }
  252.  
  253. for (i = 0; i < localStorage.length; i++) {
  254. filled += localStorage.getItem(localStorage.key(i)).length;
  255. }
  256. occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
  257. document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';
  258.  
  259. logElement.className = logElement.className + ' deleted';
  260. if (logElement.nextSibling) {
  261. logElement.nextSibling.remove();
  262. } else {
  263. logElement.previousSibling.remove();
  264. }
  265. setTimeout(function() {
  266. logElement.remove();
  267. }, 500);
  268. };
  269. }));
  270.  
  271. cont.appendChild(document.createTextNode(' '));
  272.  
  273. cont.appendChild(createElement('a', function(no) {
  274. no.id = 'no';
  275. no.href = 'javascript:void(0)';
  276. no.appendChild(document.createTextNode('[Cancel]'));
  277. no.onclick = function() {
  278. document.getElementById('confirm').style.opacity = 0;
  279. document.getElementById('screen').style.opacity = 0;
  280. setTimeout(function() {
  281. document.getElementById('confirm').style.display = 'none';
  282. document.getElementById('screen').style.display = 'none';
  283. }, 300);
  284. };
  285. }));
  286. });
  287.  
  288. empty(document.getElementById('confirm'));
  289.  
  290. document.getElementById('confirm').appendChild(confirmContent);
  291.  
  292. document.getElementById('screen').style.display = 'block';
  293. document.getElementById('confirm').style.display = 'block';
  294. setTimeout(function() {
  295. document.getElementById('screen').style.opacity = 1;
  296. document.getElementById('confirm').style.opacity = 1;
  297. }, 1);
  298. }
  299.  
  300. function deleteAllLogs() {
  301. var CAPACITY = 5242880,
  302. filled = 0,
  303. logElement;
  304.  
  305. var confirmContent = createElement('span', function(cont) {
  306. cont.appendChild(document.createTextNode('Are you sure? '));
  307.  
  308. cont.appendChild(createElement('a', function(yes) {
  309. yes.id = 'yes';
  310. yes.href = 'javascript:void(0)';
  311. yes.appendChild(document.createTextNode('[Yes]'));
  312. yes.onclick = function() {
  313. var i = 0;
  314. document.getElementById('confirm').style.opacity = 0;
  315. document.getElementById('screen').style.opacity = 0;
  316. setTimeout(function() {
  317. document.getElementById('confirm').style.display = 'none';
  318. document.getElementById('screen').style.display = 'none';
  319. }, 300);
  320.  
  321. localStorage.removeItem('IP.Chat Logs');
  322.  
  323. for (i = 0; i < localStorage.length; i++) {
  324. filled += localStorage.getItem(localStorage.key(i)).length;
  325. }
  326. occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
  327. document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';
  328.  
  329. var waitHandler = function() {
  330. logElement.remove();
  331. };
  332.  
  333. for (i = 0; i < document.getElementsByClassName('log').length; i++) {
  334. logElement = document.getElementsByClassName('log')[i];
  335. logElement.className = logElement.className + ' deleted';
  336. if (logElement.nextSibling) {
  337. logElement.nextSibling.remove();
  338. } else {
  339. logElement.previousSibling.remove();
  340. }
  341. setTimeout(waitHandler, 500);
  342. }
  343. };
  344. }));
  345.  
  346. cont.appendChild(document.createTextNode(' '));
  347.  
  348. cont.appendChild(createElement('a', function(no) {
  349. no.id = 'no';
  350. no.href = 'javascript:void(0)';
  351. no.appendChild(document.createTextNode('[Cancel]'));
  352. no.onclick = function() {
  353. document.getElementById('confirm').style.opacity = 0;
  354. document.getElementById('screen').style.opacity = 0;
  355. setTimeout(function() {
  356. document.getElementById('confirm').style.display = 'none';
  357. document.getElementById('screen').style.display = 'none';
  358. }, 300);
  359. };
  360. }));
  361. });
  362.  
  363. empty(document.getElementById('confirm'));
  364.  
  365. document.getElementById('confirm').appendChild(confirmContent);
  366.  
  367. document.getElementById('screen').style.display = 'block';
  368. document.getElementById('confirm').style.display = 'block';
  369. setTimeout(function() {
  370. document.getElementById('screen').style.opacity = 1;
  371. document.getElementById('confirm').style.opacity = 1;
  372. }, 1);
  373. }
  374.  
  375. if (document.body.id === 'ipboard_body' && document.getElementById('chat-form') != null) {
  376. var nick,
  377. curr,
  378. append = '';
  379.  
  380. logs = (localStorage.getItem('IP.Chat Logs')) ? JSON.parse(localStorage.getItem('IP.Chat Logs')) : [];
  381.  
  382. for (i = 0; i < localStorage.length; i++) {
  383. filled += localStorage.getItem(localStorage.key(i)).length;
  384. }
  385.  
  386. if (filled + JSON.stringify({'initiated': dateAndTime(), 'log': ''}).length >= CAPACITY) {
  387. logs.splice(0, 1);
  388. }
  389.  
  390. logs.push({'initiated': dateAndTime(), 'log': ''});
  391.  
  392. localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));
  393.  
  394. document.addEventListener('DOMNodeInserted', function(event) {
  395. if (event.target.nodeType !== 1 || event.target.id !== 'storage_chatroom') {
  396. return false;
  397. }
  398.  
  399. var latestMessage,
  400. latestMessageText,
  401. logs = JSON.parse(localStorage.getItem('IP.Chat Logs')),
  402. CAPACITY = 5242880,
  403. filled = 0,
  404. i = 0;
  405.  
  406. latestMessage = event.target.parentNode.getElementsByTagName('div')[event.target.parentNode.getElementsByTagName('div').length - 1];
  407.  
  408. if (!Classes.hasClass(latestMessage.parentNode, 'post')) {
  409. return false;
  410. }
  411.  
  412. latestMessageText = latestMessage.innerHTML.replace(/<br>/gi, '<br>\t');
  413.  
  414. if (!latestMessageText.length) {
  415. return false;
  416. }
  417.  
  418. nick = null;
  419.  
  420. if (Classes.hasClass(latestMessage.parentNode, 'chat-moderator')) {
  421. if (latestMessage.parentNode.getElementsByTagName('label')[0] != null) {
  422. nick = latestMessage.parentNode.getElementsByTagName('label')[0].innerHTML;
  423. } else {
  424. nick = '';
  425. }
  426. }
  427.  
  428. curr = latestMessage.parentNode;
  429.  
  430. while (nick === null) {
  431. if (curr.getElementsByTagName('label').length) {
  432. nick = curr.getElementsByTagName('label')[0].innerHTML;
  433. } else {
  434. curr = curr.previousSibling;
  435. }
  436. }
  437.  
  438. for (i = 0; i < localStorage.length; i++) {
  439. filled += localStorage.getItem(localStorage.key(i)).length;
  440. }
  441.  
  442. if (Classes.hasClass(latestMessage.parentNode, 'chat-me')) {
  443. append = '\n[' + dateAndTime('time') + '] **' + nick + ' ' + latestMessageText.substr(2, latestMessageText.length - 4) + '**';
  444. } else if (Classes.hasClass(latestMessage.parentNode, 'chat-notice')) {
  445. append = '\n[' + dateAndTime('time') + '] ' + nick + ' ' + latestMessageText.substr(2, latestMessageText.length - 2);
  446. } else if (Classes.hasClass(latestMessage.parentNode, 'chat-message')) {
  447. append = '\n[' + dateAndTime('time') + '] ' + nick + ': ' + latestMessageText;
  448. } else {
  449. if (nick.length) {
  450. append = '\n[' + dateAndTime('time') + '] ' + nick + ' ' + latestMessageText;
  451. } else {
  452. append = '\n[' + dateAndTime('time') + '] ' + latestMessageText;
  453. }
  454. }
  455.  
  456. logs[logs.length - 1].log += append;
  457.  
  458. if (filled + append.length >= CAPACITY) {
  459. logs.splice(0, 1);
  460. }
  461. localStorage.setItem('IP.Chat Logs', JSON.stringify(logs));
  462. });
  463.  
  464. if (document.getElementById('IPChatMenuItems') == null) {
  465. IPChatMenuItems = createElement('div', function(menu) {
  466. menu.id = 'IPChatMenuItems';
  467. menu.style.textAlign = 'right';
  468. });
  469. document.getElementById('chatters-online-wrap').nextSibling.nextSibling.getElementsByTagName('ul')[0].appendChild(IPChatMenuItems);
  470. }
  471.  
  472. if (document.getElementById('IPChatMenuItems').hasChildNodes()) {
  473. document.getElementById('IPChatMenuItems').appendChild(document.createElement('br'));
  474. }
  475.  
  476. menuButton = createElement('a', function(button) {
  477. button.id = 'viewIPChatLogs';
  478. button.className = 'ipsButton_secondary';
  479. button.href = window.location.origin + '/IP.Chat_Logs';
  480. button.target = '_blank';
  481. button.style.marginTop = '10px';
  482. button.appendChild(document.createTextNode('View Logs'));
  483. });
  484.  
  485. document.getElementById('IPChatMenuItems').appendChild(menuButton);
  486. }
  487.  
  488. if (window.location.href === window.location.origin + '/IP.Chat_Logs' && localStorage.getItem('IP.Chat Logs')) {
  489. var style,
  490. funcs;
  491.  
  492. logs = JSON.parse(localStorage.getItem('IP.Chat Logs'));
  493.  
  494. style = createElement('style', function(el) {
  495. el.type = 'text/css';
  496. el.appendChild(document.createTextNode(
  497. '#screen {\n' +
  498. 'position: fixed;\n' +
  499. 'height: 100%;\n' +
  500. 'width: 100%;\n' +
  501. 'background-color: rgba(0, 0, 0, .7);\n' +
  502. 'top: 0px;\n' +
  503. 'left: 0px;\n' +
  504. 'transition: all .3s ease-in-out;\n' +
  505. 'opacity: 0;\n' +
  506. 'display: none;\n' +
  507. '}\n\n' +
  508.  
  509. '#confirm {\n' +
  510. 'position: fixed;\n' +
  511. 'font-size: 3em;\n' +
  512. 'background-color: rgba(255, 255, 255, .9);\n' +
  513. 'box-shadow: 0px 0px 3px;\n' +
  514. 'height: 40px;\n' +
  515. 'line-height: 40px;\n' +
  516. 'width: 620px;\n' +
  517. 'text-align: center;\n' +
  518. 'top: 50%;\n' +
  519. 'left: 50%;\n' +
  520. 'margin-top: -32px;\n' +
  521. 'margin-left: -350px;\n' +
  522. 'padding: 10px 20px;\n' +
  523. 'border-radius: 5px;\n' +
  524. 'transition: all .3s ease-in-out;\n' +
  525. 'opacity: 0;\n' +
  526. 'display: none;\n' +
  527. '}\n\n' +
  528.  
  529. '#space {\n' +
  530. 'font-size: 20px;\n' +
  531. '}\n\n' +
  532.  
  533. '#logs {\n' +
  534. 'margin: 8px 0;\n' +
  535. 'padding: 10px;\n' +
  536. 'background-color: #fcfcfc;\n' +
  537. '}\n\n' +
  538.  
  539. '#logs img.bbc {\n' +
  540. 'vertical-align: middle;\n' +
  541. '}\n\n' +
  542.  
  543. '#logs > .log {\n' +
  544. 'transition: all .3s ease-in-out;\n' +
  545. 'overflow: hidden;\n' +
  546. '}\n\n' +
  547.  
  548. '#logs > .log:hover {\n' +
  549. // 'background-color: #f5f5f5;\n' +
  550. '}\n\n' +
  551.  
  552. '.delete {\n' +
  553. // 'display: none;\n' +
  554. 'float: right;\n' +
  555. 'background-color: #444;\n' +
  556. 'padding: 3px 5px;\n' +
  557. 'color: #eee;\n' +
  558. 'font-size: 15px;\n' +
  559. 'letter-spacing: 2px;\n' +
  560. 'text-transform: uppercase;\n' +
  561. 'cursor: pointer;\n' +
  562. '}\n\n' +
  563.  
  564. '.delete:hover {\n' +
  565. 'background-color: #222;\n' +
  566. '}\n\n' +
  567.  
  568. '.deleted {\n' +
  569. 'background-color: #222 ! important;\n' +
  570. 'color: #eee ! important;\n' +
  571. 'font-size: 0px ! important;\n' +
  572. '}\n\n' +
  573.  
  574. '.deleted > * {\n' +
  575. 'display: none;\n' +
  576. '}'
  577. ));
  578. });
  579.  
  580. document.title = 'IP.Chat Logs';
  581. document.body.style.fontFamily = 'monospace';
  582. document.head.appendChild(style);
  583.  
  584. // Body creation
  585.  
  586. empty(document.body);
  587.  
  588. document.body.appendChild(createElement('div', function(filter) {
  589. filter.id = 'screen';
  590. }));
  591.  
  592. document.body.appendChild(createElement('div', function(confirm) {
  593. confirm.id = 'confirm';
  594. }));
  595.  
  596. document.body.appendChild(createElement('div', function(space) {
  597. space.id = 'space';
  598.  
  599. space.appendChild(document.createTextNode('0% full'));
  600.  
  601. space.appendChild(createElement('span', function(delete_all) {
  602. delete_all.id = 'delete_all';
  603. delete_all.className = 'delete';
  604. delete_all.appendChild(document.createTextNode('Delete All'));
  605. delete_all.onclick = deleteAllLogs;
  606. }));
  607.  
  608. space.appendChild(createElement('span', function(hide) {
  609. hide.id = 'hide_non-logs';
  610. hide.className = 'delete';
  611. hide.style.marginRight = '10px';
  612. hide.appendChild(document.createTextNode('Hide Non-Logs'));
  613. hide.onclick = function() {
  614. var i = 0,
  615. deletes;
  616.  
  617. fade(document.getElementById('space'), 'out');
  618. for (i = 0, deletes = document.getElementsByClassName('delete'); i < deletes.length; i++) {
  619. fade(deletes[i], 'out');
  620. }
  621. };
  622. }));
  623. }));
  624.  
  625. document.body.appendChild(createElement('pre', function(pre) {
  626. pre.id = 'logs';
  627. }));
  628.  
  629. for (i = 0; i < localStorage.length; i++) {
  630. filled += localStorage.getItem(localStorage.key(i)).length;
  631. }
  632. occupied = roundToNthDecimal((filled / CAPACITY) * 100, 1);
  633. document.getElementById('space').childNodes[0].nodeValue = occupied + '% full';
  634.  
  635. for (i = 0; i < logs.length; i++) {
  636. if (document.getElementById('logs').hasChildNodes()) {
  637. document.getElementById('logs').appendChild(document.createTextNode('\n'));
  638. }
  639.  
  640. document.getElementById('logs').appendChild(createLog(logs, i));
  641. }
  642. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址