IPB Thread Updater

shows new posts while reading a thread

  1. // ==UserScript==
  2. // @name IPB Thread Updater
  3. // @author ameboide
  4. // @version 2011.07.05
  5. // @namespace http://userscripts.org/scripts/show/105667
  6. // @description shows new posts while reading a thread
  7. // @include http://*/index.php?showtopic=*
  8. // ==/UserScript==
  9.  
  10. //configuraciones
  11. try{
  12. //fix para usar data persistente sin pseudogreasemonkey
  13. if (!GM_getValue || GM_getValue.toString().indexOf("not supported")>-1) {
  14. GM_getValue=function (key,def) {
  15. if(!localStorage || !localStorage.hasOwnProperty(key)) return def;
  16. var val = localStorage[key];
  17. return val !== undefined ? val : def;
  18. };
  19. GM_setValue=function (key,value) {
  20. if(!localStorage) return null;
  21. return localStorage[key]=value;
  22. };
  23. }
  24. }catch(e){}
  25.  
  26. var conf = {
  27. notifAlert: GM_getValue('notifAlert', false),
  28. notifTip: GM_getValue('notifTip', true),
  29. activo: GM_getValue('activo', false),
  30. segs: GM_getValue('segs', 23),
  31. pregSegs: GM_getValue('pregSegs', false)
  32. };
  33.  
  34. //constantes
  35. var url = document.location.href.match(/^.+\?/)[0];
  36. var id = document.location.href.match(/showtopic=(\d+)/)[1];
  37. var st = document.location.href.match(/st=(\d+)/);
  38. st = st ? Number(st[1]) : 0;
  39.  
  40. var subforo = document.querySelector('#navstrip a:last-of-type').href;
  41.  
  42. var reNum = new RegExp('who_posted\\('+id+'\\);">(\\d+)');
  43.  
  44. var selPosts = '.ipbtable[cellspacing="1"]';
  45. var contPosts = document.querySelector(selPosts).parentNode;
  46.  
  47. var textoBotonActivo = 'Stop watching this thread for updates';
  48. var textoBotonInactivo = 'Watch this thread for updates';
  49.  
  50. var activo = conf.activo;
  51.  
  52. //interfaz conf
  53. var divConf = document.createElement('div');
  54. var br = document.querySelector('#ipbwrapper>br');
  55. br.parentNode.insertBefore(divConf, br);
  56.  
  57. var boton = document.createElement('button');
  58. boton.style.width = '400px';
  59. textoBoton();
  60. divConf.appendChild(boton);
  61. boton.addEventListener('click', function(){
  62. if(activo){
  63. activo = false;
  64. textoBoton();
  65. }
  66. else{
  67. var val = conf.pregSegs ? prompt('Interval between checks (in seconds)', conf.segs) : conf.segs;
  68. if(val === null) return;
  69. if(val>0) conf.segs = val;
  70. GM_setValue('segs', conf.segs);
  71. document.getElementById('TU_lbl_pregSegs').lastChild.textContent =
  72. 'Change checking interval ('+conf.segs+' seconds)';
  73.  
  74. activo = true;
  75. textoBoton();
  76. revisar();
  77. }
  78. }, true);
  79.  
  80. checkbox('activo', 'Start turned on by default');
  81. checkbox('notifAlert', 'Alert on new posts');
  82. checkbox('notifTip', 'Show notification on new posts');
  83. checkbox('pregSegs', 'Change checking interval ('+conf.segs+' seconds)');
  84.  
  85. function checkbox(nombre, texto){
  86. var cb = document.createElement('input');
  87. cb.type = 'checkbox';
  88. cb.checked = conf[nombre];
  89. var lbl = document.createElement('label');
  90. lbl.id = 'TU_lbl_'+nombre;
  91. lbl.appendChild(cb);
  92. lbl.appendChild(document.createTextNode(texto));
  93. cb.addEventListener('click', function(evt){
  94. var val = evt.target.checked == true;
  95. conf[nombre] = val;
  96. GM_setValue(nombre, val);
  97. }, true);
  98.  
  99. divConf.appendChild(lbl);
  100. }
  101.  
  102. function textoBoton(extra){
  103. boton.innerHTML = (activo ? textoBotonActivo : textoBotonInactivo) + (extra ? ' ' + extra : '');
  104. }
  105.  
  106. //inicializar notificador
  107. var divNotif = document.createElement('div');
  108. var spanNotif = document.createElement('span');
  109. var txtNotif = document.createElement('a');
  110. var xNotif = document.createElement('span');
  111.  
  112. divNotif.style.display = 'none';
  113. divNotif.style.position = 'fixed';
  114. divNotif.style.textAlign = 'center';
  115. divNotif.style.top = '0px';
  116. divNotif.style.width = '100%';
  117. divNotif.style.padding = '23px';
  118. divNotif.style.fontSize = '23px';
  119.  
  120. spanNotif.style.padding = '23px';
  121.  
  122. xNotif.innerHTML = '[X]';
  123. xNotif.style.cursor = 'pointer';
  124. xNotif.addEventListener('click', function(evt){
  125. divNotif.style.display = 'none';
  126. evt.stopPropagation();
  127. return false;
  128. }, true);
  129.  
  130. document.body.appendChild(divNotif);
  131. divNotif.appendChild(spanNotif);
  132. spanNotif.appendChild(txtNotif);
  133. spanNotif.appendChild(document.createTextNode(' '));
  134. spanNotif.appendChild(xNotif);
  135. var nots = 0;
  136.  
  137. function notificar(num, id){
  138. if(conf.notifAlert) alert(num + ' new posts in ' + document.title);
  139.  
  140. if(conf.notifTip){
  141. txtNotif.innerHTML = num + ' new posts';
  142. txtNotif.href = '#'+id;
  143. spanNotif.style.backgroundColor = '#ff0';
  144. divNotif.style.display = '';
  145. nots++;
  146.  
  147. setTimeout(function(){
  148. spanNotif.style.backgroundColor = '#ffb';
  149. }, 500);
  150. setTimeout(function(){
  151. if(!--nots) divNotif.style.display = 'none';
  152. }, 6000);
  153. }
  154. }
  155.  
  156. //aca empieza el script de verdad...
  157. function revisar(){
  158. if(!activo) return;
  159.  
  160. var xhr = new XMLHttpRequest();
  161. xhr.onreadystatechange = function(){
  162. if (xhr.readyState == 4){
  163. try{
  164. if(xhr.status == 200){
  165. var ultimo = document.querySelectorAll(selPosts).length + st;
  166. var num = xhr.responseText.match(reNum);
  167. num = num ? Number(num[1])+1 : 0;
  168. if(num > ultimo) agregarNuevos(ultimo);
  169. }
  170. else{ //wtf?
  171. }
  172. }catch(e){}
  173.  
  174. textoBoton();
  175. if(activo) setTimeout(revisar, conf.segs*1000);
  176. }
  177. }
  178.  
  179. xhr.open('GET', subforo, true);
  180. xhr.send(null);
  181.  
  182. textoBoton('(checking)');
  183. }
  184.  
  185. function agregarNuevos(inicio){
  186. var xhr = new XMLHttpRequest();
  187. xhr.onreadystatechange = function(){
  188. if (xhr.readyState == 4){
  189. if(xhr.status == 200){
  190. var div = document.createElement('div');
  191. div.innerHTML = xhr.responseText;
  192. var posts = div.querySelectorAll(selPosts);
  193. for(var i=0; i<posts.length; i++) contPosts.appendChild(posts[i]);
  194. notificar(posts.length, posts[0].querySelector('a[name^=entry]').getAttribute('name'));
  195. }
  196. else{ //wtf?
  197. }
  198. textoBoton();
  199. }
  200. }
  201.  
  202. xhr.open('GET', url + 'showtopic=' + id + '&st=' + inicio, true);
  203. xhr.send(null);
  204.  
  205. textoBoton('(updating)');
  206. }
  207.  
  208. if(activo) revisar();