Help icon and small things
[4Free-FSE.git] / Thread-Rebuilder.user.js
blob1aeb79e751b554047d32eb92a61c6b3eee6e1ab7
1         // ==UserScript==
2         // @name         Thread Rebuilder
3         // @namespace    http://tampermonkey.net/
4         // @version      2.5
5         // @description  try to take over the world!
6         // @author       ECHibiki /qa/
7         // @match https://boards.4chan.org/*/thread/*
8         // @match http://boards.4chan.org/*/thread/*
9         // @grant         GM_xmlhttpRequest
10         // @updateURL    https://github.com/ECHibiki/4chan-UserScripts/raw/master/Thread-Rebuilder.user.js
11         // @downloadURL  https://github.com/ECHibiki/4chan-UserScripts/raw/master/Thread-Rebuilder.user.js
12         // @run-at document-start
13         // ==/UserScript==
15         var board = "qa";
16         var thread_data = [['Comment'], ['Image URLs'], ['Image Names'] ,['Post No.']];
17         var semaphore = 1;
18         var semaphore_posts = 1;
19         var timeListen;
21         var use_offsite_archive = false;
22         var window_displayed = false;
23         var in_sequence = false;
24         var tool_top_visible = false;
25         
26         var help_icon_source = " data:image/jpeg;base64,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"
28         //1) CREATE INTERFACE
29         //set listener to build interface in 4chanX
30         //set listeners to build interface in 4chanX
31 document.addEventListener("4chanXInitFinished", function(e){
32         document.addEventListener("QRDialogCreation", enhance4ChanX);
34         rebuildWindow();
35         rebuildButton();
37         use_offsite_archive =  localStorage.getItem("ArchiveType") == 0 ? true : false;
38         if(use_offsite_archive) document.getElementById("OffsiteArchive").checked = true;
39         else document.getElementById("OnsiteArchive").checked = true;
41         loaded = true;
42 }, false);
44 //is storage possible
45 function storageAvailable(type) {
46     try {
47         var storage = window[type],
48             x = '__storage_test__';
49         storage.setItem(x, x);
50         storage.removeItem(x);
51         return true;
52     }
53     catch(e) {
54                 //From https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
55         return e instanceof DOMException && (
56             // everything except Firefox
57             e.code === 22 ||
58             // Firefox
59             e.code === 1014 ||
60             // test name field too, because code might not be present
61             // everything except Firefox
62             e.name === 'QuotaExceededError' ||
63             // Firefox
64             e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
65             // acknowledge QuotaExceededError only if there's something already stored
66             storage.length !== 0;
67     }
70 //settings for time expiration on image hiding
71 function rebuildWindow(){
72     var style = document.createElement('style');
73     style.innerHTML = ".inputs{background-color:rgb(200,200,200);margin:5px 7px;width:100px;}";
74     document.body.appendChild(style);
76     var background_div = document.createElement("div");
77     background_div.setAttribute("style", "border:solid 1px black;position:fixed;width:100%;height:100%;background-color:rgba(200,200,200,0.3);top:0;left:0;display:none; z-index:9");
78     background_div.setAttribute("id", "rebuildBackground");
79     document.body.appendChild(background_div);
80     background_div.addEventListener("click", rebuildToggle);
82     var window_div = document.createElement("div");
83     window_div.setAttribute("style", "border:solid 1px black;position:fixed;width:400px;background-color:rgb(200,200,200);left:40%;top:20%;margin-bottom:0;  display:none; z-index:10");
84     window_div.setAttribute("id", "rebuildWindow");
86     var close_div = document.createElement("div");
87     close_div.setAttribute("style", "border:solid 1px black;position:absolute;width:25px;height:25px;background-color:rgba(255,100,90,0.9); right:3px;top:3px; z-index:10");
88     close_div.addEventListener("click", rebuildToggle);
89     window_div.appendChild(close_div);
91     var title_para = document.createElement("p");
92     title_para.setAttribute("style", "margin-left:5px;margin-top:5px");
93     var title_text = document.createTextNode("Rebuild Settings");
94     title_para.appendChild(title_text);
95     window_div.appendChild(title_para);
97     var container_div = document.createElement("div");
98     container_div.setAttribute("style","background-color:white;margin:0 0;padding:5px;");
99     window_div.appendChild(container_div);
101     var rebuild_label_local = document.createElement("label");
102     var rebuild_text_local = document.createTextNode("Use 4chan Archives: ");
103     rebuild_label_local.appendChild(rebuild_text_local);
104     container_div.appendChild(rebuild_label_local);
105     var rebuild_input_local = document.createElement("input");
106         rebuild_input_local.setAttribute("type", "radio");
107         rebuild_input_local.setAttribute("name", "ArchiveSettings");
108     rebuild_input_local.setAttribute("id", "OnsiteArchive");
109     container_div.appendChild(rebuild_input_local);
110     container_div.appendChild(rebuild_input_local);
111     container_div.appendChild(document.createElement("br"));
113         var rebuild_label_offsite = document.createElement("label");
114     var rebuild_text_offsite = document.createTextNode("Use Offsite Archives: ");
115     rebuild_label_offsite.appendChild(rebuild_text_offsite);
116     container_div.appendChild(rebuild_label_offsite);
117     var rebuild_input_offsite = document.createElement("input");
118         rebuild_input_offsite.setAttribute("type", "radio");
119         rebuild_input_offsite.setAttribute("name", "ArchiveSettings");
120     rebuild_input_offsite.setAttribute("id", "OffsiteArchive");
121     container_div.appendChild(rebuild_input_offsite);
122     container_div.appendChild(rebuild_input_offsite);
123     container_div.appendChild(document.createElement("br"));
125     var set_button = document.createElement("input");
126     set_button.setAttribute("type", "button");
127     set_button.setAttribute("id", "setTime");
128     set_button.setAttribute("value", "Set Archive");
129     set_button.addEventListener("click", function(){
130         if (storageAvailable('localStorage')) {
131                         var radio_options = document.getElementsByName("ArchiveSettings");
132                         for (var radio_input = 0 ; radio_input < radio_options.length; radio_input++)
133                                 if(radio_options[radio_input].checked){
134                                         localStorage.setItem("ArchiveType", radio_input);
135                                         if(radio_input == 0) use_offsite_archive = true;
136                                 }
137             rebuildToggle();
138         }
139     });
140     container_div.appendChild(set_button);
142     document.body.appendChild(window_div);
146 function rebuildToggle(){
147     if(window_displayed){
148         document.getElementById("rebuildWindow").style.display = "none";
149         document.getElementById("rebuildBackground").style.display = "none";
150         window_displayed = false;
151     }
152     else{
153         document.getElementById("rebuildWindow").style.display = "inline-block";
154         document.getElementById("rebuildBackground").style.display = "inline-block";
155         window_displayed = true;
156     }
159 function rebuildButton(){
160     var rebuild_button = document.createElement("input");
161     rebuild_button.setAttribute("Value", "Thread Rebuilder Settings");
162     rebuild_button.setAttribute("type", "button");
163     rebuild_button.setAttribute("style", "position:absolute;top:105px");
164     rebuild_button.addEventListener("click", rebuildWindow);
165     if(document.body === null){
166         setTimeout(rebuildButton, 30);
167     }
168     else{
169         document.body.appendChild(rebuild_button);
170         rebuild_button.addEventListener("click", rebuildToggle);
171     }
174 var enhance4ChanX = function(){
175         var qr_window = document.getElementById("qr");
177         if(document.getElementById("qrRebuilder") !== null) qr_window.removeChild(document.getElementById("qrRebuilder"));
179         var thread_rebuilder_table = document.createElement("TABLE");
180         thread_rebuilder_table.setAttribute("id", "qrRebuilder");
181         thread_rebuilder_table.setAttribute("style", "text-align:center");
182         qr_window.appendChild(thread_rebuilder_table);
184         var thread_row = document.createElement("TR");
186         var help_icon_container = document.createElement("A");
187         help_icon_container.href = "javascript:void(0)";
188         help_icon_container.title = "Click to View Help!";
189         var help_icon = document.createElement("IMG");
190         help_icon.setAttribute("style", "height:" + option_text_size * 1.25 + "px;margin:-4px 10px");
191         help_icon.src = help_icon_source;
193         help_icon_container.appendChild(help_icon);
194         thread_row.appendChild(help_icon_container);
196         var tooltip_div = document.createElement("DIV");
197         tooltip_div.innerHTML = "Insert the thread number of the post to rebuild<br/>Must be in either the 4chan archives or archived.moe";
198         tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;");
199         help_icon_container.addEventListener("click", function(ev){
200                 if(tool_top_visible)
201                         tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;");
202                 else
203                         tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:block;position:absolute;"
204                                 + "left:" +  (ev.clientX - qr_window.getBoundingClientRect().x) +
205                                 "px;top:" +  (ev.clientY - qr_window.getBoundingClientRect().y ) + "px;");
206                 tool_top_visible = !tool_top_visible;
207         });
208         qr_window.appendChild(tooltip_div);
209         
210         var second_row_nodes = [
211                 document.createTextNode("Thread: "),
212                 document.createElement("INPUT"),
213                 document.createElement("INPUT"),
214         ];
215         second_row_nodes.forEach(
216                 function(node){
217                         thread_row.appendChild(node);
218                 });
219         thread_rebuilder_table.appendChild(thread_row);
221         second_row_nodes[1].setAttribute("ID", "threadInput");
222         second_row_nodes[1].setAttribute("style", "width:35.0%");
224         second_row_nodes[2].setAttribute("ID", "threadButton");
225         second_row_nodes[2].setAttribute("type", "button");
226         second_row_nodes[2].setAttribute("value", "Set Rebuild Queue");
228         second_row_nodes[2].addEventListener("click", function(){
229                 in_sequence = true;
230                 killAll();
231                 getThread(second_row_nodes[1].value);
232                 postID = setInterval(postRoutine, 1000);
233                 if(timeListen === undefined) timeListen = setInterval(timeListenerFunction, 1000);
234         });
235         qr_window.appendChild(document.createElement("hr"));
238 var thread_data_length = 0;
239 var posts_created = 0;
240 var postID = "";
241 var postRoutine = function(){
242         if(semaphore == 0){
243                 semaphore++;
244                 thread_data_length = thread_data[0].length;
245                 fillID = setInterval(fillRoutine, 10);
246                 stopRoutine();
247         }
250 var stopRoutine = function(){
251         clearInterval(postID);
254 var fillID  = "";
255 var fillRoutine = function(){
256         if(posts_created >= thread_data_length) {semaphore_posts  = 0 ; stopFillRoutine();}
257         else if(semaphore_posts == 1){
258                 semaphore_posts--;
259                 createPost(thread_data[0][posts_created], thread_data[1][posts_created], thread_data[2][posts_created]);
260                 posts_created++;
261         }
264 var stopFillRoutine = function(){
265         clearInterval(fillID);
268 var setPropperLinking = function(text){
269         var search_regex = RegExp(">>\\d+", "g");
270         var result;
271         var index_old = -1;
272         var link_arr = Array();
273         while((result = search_regex.exec(text)) != null){
274                 var end_index = search_regex.lastIndex;
275                 var post_no = result.toString().replace(/>/g, "");
276                 link_arr.push([post_no, end_index]);
277         }
278 //hunt down the text of what it linked to
279 //Get the links inside of the origonal message to show text contents
280         var responding_text = Array();
281         if(use_offsite_archive)
282                 URL  = "https://www.archived.moe/_/api/chan/thread/?board=" + board + "&num=" + document.getElementById("threadInput").value;
283         else
284                 URL  = "https://a.4cdn.org/" + board + "/thread/" + document.getElementById("threadInput").value + ".json";
285                 var xhr = new GM_xmlhttpRequest(({
286                         method: "GET",
287                         url: URL,
288                         responseType : "json",
289                         onload: function(data){
290                                 if(use_offsite_archive)
291                                         data = data.response["" + document.getElementById("threadInput").value]["posts"];
292                                 else
293                                         data = data.response["posts"];
294                                 if(data == undefined){
295                                         alert("Invalid Thread ID: " + document.getElementById("threadInput").value + ". ");
296                                 }
297                                 else{
298                                         link_arr.forEach(function(link_item){
299                                                 for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
300                                                         if(parseInt(link_item[0]) == parseInt(data[data_entry]["no"])){
301                                                                 if(use_offsite_archive)
302                                                                         responding_text.push([ [post_no, end_index], data[data_entry]["comment_processed"].replace(/(&gt;&gt;|https:\/\/www\.archived\.moe\/.*\/thread\/.*\/#)\d+/g, ""), link_item["media"]["safe_media_hash"] ]);
303                                                                 else
304                                                                         responding_text.push([ [post_no, end_index], data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, ""), data[data_entry]["md5"] ]);
305                                                                 break;
306                                                         }
307                                                 }
308                                         });
310                                         var current_url = window.location.href;
311                                         var hash_index = current_url.lastIndexOf("#") != -1 ? current_url.lastIndexOf("#"):  window.location.href.length;
312                                         var current_thread = window.location.href.substring(current_url.lastIndexOf("/")+1, hash_index);
313                                         var current_url =  "https://a.4cdn.org/" + board + "/thread/" + current_thread + ".json";
314                                         //open current thread to hunt down the text found in links
315                                         var xhr = new GM_xmlhttpRequest(({
316                                                 method: "GET",
317                                                 url: current_url,
318                                                 responseType : "json",
319                                                 onload: function(data){
320                                                         data = data.response["posts"];
321                                                         if(data == undefined){
322                                                                 alert("Invalid Thread ID: " + document.getElementById("threadInput").value + ". ");
323                                                         }
324                                                         else{
325                                                                 responding_text.forEach(function(response_item){
326                                                                         for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
327                                                                                 if((response_item[1] == data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, "") || response_item[1] == null)
328                                                                                         && (response_item[2] == data[data_entry]["md5"] || response_item[2] == null)){
329                                                                                         var start_index = response_item[0][0].legth - response_item[0][1];
330                                                                                         text = text.substring(0, start_index) + ">>" + data[data_entry]["no"] + text.substring(response_item[0][1]);
331                                                                                                 break;
332                                                                                 }
333                                                                         }
334                                                                 });
335                                                                                         document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value = text;
336                                                                                         document.getElementById("add-post").click();
337                                                                                         semaphore_posts++;
338                                                         }
339                                                 }
340                                         }));
341                                 }
342                         }
343                 }));
347 //2) GET ARCHIVED THREAD
348 var getThread = function(threadNo){
349         thread_data = [[], [], [], []];
351         if(use_offsite_archive)
352                 URL  = "https://www.archived.moe/_/api/chan/thread/?board=" + board + "&num=" + document.getElementById("threadInput").value;
353         else
354                 URL  = "https://a.4cdn.org/" + board + "/thread/" + document.getElementById("threadInput").value + ".json";
355         var xhr = new GM_xmlhttpRequest(({
356                 method: "GET",
357                 url: URL,
358                 responseType : "json",
359                 onload: function(data){
360                         var starting_post = -1;
361                         if(use_offsite_archive){
362                                 starting_post = 0;
363                                 data = data.response["" + document.getElementById("threadInput").value];
364                         }
365                         else{
366                                 starting_post = 1;
367                                 data = data.response;
368                         }
369                         if(data == undefined){
370                                 alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
371                         }
372                         else{
373                                 if(use_offsite_archive) data["posts"] = Object.values(data["posts"]);
374                                 var len = data["posts"].length;
376                                 for(var post_number = starting_post ; post_number < len ; post_number++){
377                                         var comment = undefined;
378                                         if(use_offsite_archive)
379                                                 comment = data["posts"][post_number]["comment"];
380                                         else
381                                                 comment = data["posts"][post_number]["com"];
382                                         if(comment !== undefined && comment !== null)
383                                                 thread_data[0].push(comment);
384                                         else
385                                                 thread_data[0].push(-1);
387                                         var filename = undefined;
388                                         if(use_offsite_archive)
389                                                 if(data["posts"][post_number]["media"] !== null)
390                                                         filename = "" + data["posts"][post_number]["media"]["media_filename"];
391                                         else
392                                                 filename = "" + data["posts"][post_number]["tim"] + data["posts"][post_number]["ext"];
394                                         if(filename !== undefined && filename !== null && filename.indexOf("undefined") == -1)
395                                                 if(use_offsite_archive)
396                                                         if(data["posts"][post_number]["media"] !== null)
397                                                                 thread_data[1].push(data["posts"][post_number]["media"]["remote_media_link"]);
398                                                         else  thread_data[1].push(-1);
399                                                 else
400                                                         thread_data[1].push("https://i.4cdn.org/" + board + "/" + filename);
401                                         else  thread_data[1].push(-1);
403                                         if(use_offsite_archive)
404                                                 if(data["posts"][post_number]["media"] !== null)
405                                                         thread_data[2].push(data["posts"][post_number]["media"]["media_id"]);
406                                         else
407                                                 thread_data[2].push(data["posts"][post_number]["filename"]);
409                                         if(use_offsite_archive)
410                                                 thread_data[3].push(data["posts"][post_number]["num"]);
411                                         else
412                                                 thread_data[3].push(data["posts"][post_number]["no"]);
413                                 }
414                         }
415                         semaphore--;
416                 }
417         }));
419 //3) RIP POSTS AND IMAGES
420 var createPost = function(text, imageURL, imageName){
421         if(imageURL != -1){
422                 var response_type = "arraybuffer";
423                 if(use_offsite_archive) response_type = "text"
424                 var xhr = new GM_xmlhttpRequest(({
425                         method: "GET",
426                         url: imageURL,
427                         responseType : response_type,
428                         onload: function(response)
429                         {
430                                 if(use_offsite_archive){
431                                         var parser = new DOMParser();
432                                         var content_attribute = parser.parseFromString(response.response, "text/html").getElementsByTagName("META")[0].getAttribute("content");
433                                         var redirect_url = content_attribute.substring(content_attribute.indexOf("http"));
434                                         var xhr = new GM_xmlhttpRequest(({method:"GET", url: redirect_url, responseType:"arraybuffer",
435                                                 onload:function(response){
436                                                         inputImage(response, text,  imageURL, imageName);
437                                                 }
438                                         }));
439                                 }
440                                 else{
441                                         inputImage(response, text, imageURL, imageName);
442                                 }
443                         }
444                 }));
445         }
446         else{
447                 text = createPostComment(text);
448                 setPropperLinking(text);
449         }
452 function inputImage(response, text, imageURL, imageName){
453                                 var blob;
454                                 var ext = ".jpg";
455                                 if(imageURL.indexOf(".jpg") > -1){
456                                         blob = new Blob([response.response], {type:"image/jpeg"});
457                                         ext = ".jpg";
458                                 }
459                                 else if(imageURL.indexOf(".png") > -1){
460                                         blob = new Blob([response.response], {type:"image/png"});
461                                         ext = ".png";
462                                 }
463                                 else if(imageURL.indexOf(".gif") > -1){
464                                         blob = new Blob([response.response], {type:"image/gif"});
465                                         ext = ".gif";
466                                 }
467                                 else if(imageURL.indexOf(".webm") > -1){
468                                         blob = new Blob([response.response], {type:"video/webm"});
469                                         ext = ".webm";
470                                 }
472                                 var name = imageName + ext;
474                                 //SEND RESULTING RESPONSE TO 4CHANX FILES === QRSetFile
475                                 var detail = {file:blob, name:name};
476                                 if (typeof cloneInto === 'function') {
477                                         detail  = cloneInto(detail , document.defaultView);
478                                 }
480                                 document.dispatchEvent(new CustomEvent('QRSetFile', {bubbles:true, detail}));
482                                 if(text !== "" && text !== undefined && text !== -1) {
483                                         text = createPostComment(text);
484                                         setPropperLinking(text);
485                                 }
486                                 else{
487                                         document.getElementById("add-post").click();
488                                         semaphore_posts++;
489                                 }
492 //4) CREATE POST QUEUE
493 var createPostComment = function(text){
494         text = text.replace(/<a href="\/[a-zA-Z]+\/" class="quotelink">/g, "");
495         text = text.replace(/<span class="deadlink">/g, "");
497         var quote_regex = /<a href="#p[0-9]+" class="quotelink">&gt;&gt;[0-9]+/g;
498         var find = text.match(quote_regex);
499         if(find){
500                 find.forEach(function(match){
501                         var index_start = text.indexOf(match);
502                         var match_len = match.length;
503                         var index_len = index_start + match_len;
504                         var first_quote = match.indexOf('"');
505                         var second_quote = match.indexOf('"', first_quote + 1);
506                         var post_no = match.substring(first_quote + 3, second_quote);
508                         match = ">>" + post_no;
510                         text = text.substr(0, index_start) + match +  text.substr(index_len);
511                 });
512         }
514         text = text.replace(/<span class="quote">/g, "");
515         text = text.replace(/<br>/g, "\n");
516         text = text.replace(/&#039;/g, "'");
517         text = text.replace(/&gt;/g, ">");
518         text = text.replace(/<\/a>/g, "");
519         text = text.replace(/<wbr>/g, "");
520         text = text.replace(/<\/span>/g, "");
522         return text;
525 var checked = false;
526 var timeListenerFunction = function(){
527         var time = document.getElementById("qr-filename-container").nextSibling.value.replace(/[a-zA-Z]+/g, "");
528         if(time  <= 5){
529                 checked = false;
530         }
531         else if(time > 5){
532                 checked = true;
533         }
536 document.addEventListener('QRPostSuccessful', function(e) {
537         if(in_sequence){
538                 document.getElementById("dump-list").childNodes[1].click();
539                 setPropperLinking(document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value);
540         }
541 }, false);
544 function killAll(){
545         thread_data_length = 0;
546         posts_created = 0;
547         stopRoutine();
548         postID = "";
549         semaphore = 1;
550         semaphore_posts = 1;
551         stopFillRoutine();
552         fillID  = "";
553         thread_data = [['Comment'], ['Image URLs'], ['Image Names'] ,['Post No.']];
554         //CLEAR DUMP LIST
555         var qr_dumplist = document.getElementById("dump-list").childNodes;
556         var qr_dumplist_len = qr_dumplist.length;
557         var current_preview = 0;
558         while(qr_dumplist_len - current_preview > 1){
559                 qr_dumplist[0].firstChild.click();
560                 current_preview++;
561         }