docs and Ignoring-Enhancement edits in proggress
[4Free-FSE.git] / Thread-Rebuilder.user.js
blob72e663a16827e9ca2fa2286d631fda3f1f3e69be
1         // ==UserScript==
2         // @name         Thread Rebuilder
3         // @namespace    http://tampermonkey.net/
4         // @version      1.1
5         // @description  try to take over the world!
6         // @author       You
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         // ==/UserScript==
14         var board = "qa";
15         var threadData = [['Comment'], ['Image URLs'], ['Image Names'] ,['Post No.']];
16         var semaphore = 1;
17         var semaphore_posts = 1;
18         var timeListen;
20         //1) CREATE INTERFACE
21 //set listener to build interface in 4chanX
22 window.onload = function(){
23     var len = document.links.length;
24     for(var i = 0 ; i < len ; i++){
25                 var class_name = document.links[i].parentNode.className ;
26                 if(class_name == "postNum desktop" || class_name == "qr-link-container"
27                    || class_name == "brackets-wrap qr-link-container-bottom")
28                         document.links[i].addEventListener("click", enhance4ChanX);
29     }
31     //ENHANCE DUMP TABS (COVER, 482PX - 482PX)
32     //DUMP LIST MAX-HEIGHT TO 490
34     document.getElementById("fourchanx-css").textContent += ".qr-preview { height: 482px; width: 482px; background-size: cover;}";
35     document.getElementById("fourchanx-css").textContent += "#dump-list { min-height: 400px; width: 509px;}";
38         
39         var enhance4ChanX = function(){
41                 var qrWindow = document.getElementById("qr");
43                 if(document.getElementById("qrRebuilder") !== null) qrWindow.removeChild(document.getElementById("qrRebuilder"));
44                 //document.getElementById("dump-button").click();
46                 ////console.log(document.getElementById("qr").getElementsByTagName("TEXTAREA")[0]);
47                 var dList = document.getElementById("dump-list");
48                 var filenamecontainer = document.getElementById("qr-filename-container");
49                 var BGImg = "";
50                 var oldBGImg = "";
52                 /*
53                 var observer = new MutationObserver(function(mutate){
54                         BGImg = dList.firstChild.style.backgroundImage;
55                         if(BGImg !== oldBGImg && imgURL !== ""){
56                                 //console.log("CHANGED");
57                                 dList.firstChild.style.backgroundImage = "url(" + imgURL + ")";
58                                 //console.log("CHANGED");
59                                 oldBGImg = dList.firstChild.style.backgroundImage;
60                                 //console.log("CHANGED");
61                                 //console.log(imgURL);
62                         }
63                         else if (imgURL == ""){
65                         }
66                 });
67                 observer.observe(dList , {attributes: true,subtree:true, childList: true, characterData: true });*/
69                 if(document.getElementById("qr-filerm") !== null)
70                         document.getElementById("qr-filerm").addEventListener("click", function(){imgURL = "";});
71                 else return;
73                 var qrTable = document.createElement("TABLE");
74                 qrTable.setAttribute("id", "qrRebuilder");
75                 qrTable.setAttribute("style", "text-align:center");
76                 qrWindow.appendChild(qrTable);
78                 var instructionRow = document.createElement("TR");
79                 var topRowNodes = [document.createElement("BR"),
80                                                    document.createTextNode("Insert the thread number of the post to rebuild"),
81                                                    document.createElement("BR"),
82                                                    document.createTextNode("Must be in the 4chan archives"),
83                                                    document.createElement("BR"),
84                                                   ];
85                 topRowNodes.forEach(
86                         function(node){
87                                 instructionRow.appendChild(node);
88                         });
89                 qrTable.appendChild(instructionRow);
91                 var threadRow = document.createElement("TR");
92                 var secondRowNodes = [
93                         document.createTextNode("Thread: "),
94                         document.createElement("INPUT"),
95                         document.createElement("INPUT"),
96                 ];
97                 secondRowNodes.forEach(
98                         function(node){
99                                 threadRow.appendChild(node);
100                         });
101                 qrTable.appendChild(threadRow);
103                 secondRowNodes[1].setAttribute("ID", "threadInput");
104                 secondRowNodes[1].setAttribute("style", "width:44.9%");
106                 secondRowNodes[2].setAttribute("ID", "threadButton");
107                 secondRowNodes[2].setAttribute("type", "button");
108                 secondRowNodes[2].setAttribute("value", "Set Rebuild Queue");
109                 secondRowNodes[2].addEventListener("click", function(){
110                         ////console.log("exce");
111                         getThread(secondRowNodes[1].value);
112                         //wait until done
113                         postID = setInterval(postRoutine, 1000);
114                         if(timeListen === undefined) timeListen = setInterval(timeListenerFunction, 1000);
115                 });
117         };
119         var len = 0;
120         var i = 0;
122         var postID = "";
123         var postRoutine = function(){
124                 if(semaphore == 0){
125                         semaphore++;
126                         len = threadData[0].length;
127                         ////console.log(len);
128                         fillID = setInterval(fillRoutine, 10);
129                         stopRoutine();
130                 }
131         };
132         var stopRoutine = function(){
133                 ////console.log("Post Ends");
134                 clearInterval(postID);
135         };
137         var fillID  = "";
138         var fillRoutine = function(){
139                 ////console.log(semaphore_posts + " " + i);
140                 if(i >= len) {semaphore_posts  = 0 ; stopFillRoutine();}
141                 else if(semaphore_posts == 1){
142                         semaphore_posts--;
143                         createPost(threadData[0][i], threadData[1][i], threadData[2][i]);
144                         i++;
145                 }
146         };
148         var stopFillRoutine = function(){
149                 ////console.log("Fill Ends");
150                 clearInterval(fillID);
151         };
153         var setPropperLinking = function(text){
154                 //console.log(text);
155                 var search_regex = RegExp(">>\\d+", "g");
156                 var result;
157                 var index_old = -1;
158                 var link_arr = Array();
159                 while((result = search_regex.exec(text)) != null){
160                         var end_index = search_regex.lastIndex;
161                         var post_no = result.toString().replace(/>/g, "");
162                         link_arr.push([post_no, end_index]);
163                 }
164         //hunt down the text of what it linked to               
165                 var responding_text = Array();  
166                 URL  = "https://a.4cdn.org/" + board + "/thread/" + document.getElementById("threadInput").value + ".json";
167                         ////console.log(URL);
168                         var xhr = new GM_xmlhttpRequest(({
169                                 method: "GET",
170                                 url: URL,
171                                 responseType : "json",
172                                 onload: function(data){
173                                         data = data.response["posts"];
174                                         ////console.log(data);
175                                         if(data == undefined){
176                                                 alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
177                                                 //draw from desu instead
178                                         }
179                                         else{
180                                                 link_arr.forEach(function(link_item){
181                                                         for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
182                                                         //console.log(parseInt(link_item[0]));
183                                                         //console.log(parseInt(data[data_entry]["no"]));
184                                                                 if(parseInt(link_item[0]) == parseInt(data[data_entry]["no"])){
185                                                                         responding_text.push([ [post_no, end_index], data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, ""), data[data_entry]["md5"]]);
186                                                                         //console.log(responding_text);
187                                                                         break;
188                                                                 }
189                                                         }
190                                                         //console.log("---")
191                                                 });
192                                                 
193                                                 var current_url = window.location.href;
194                                                 var hash_index = current_url.lastIndexOf("#") != -1 ? current_url.lastIndexOf("#"):  window.location.href.length;
195                                                 var current_thread = window.location.href.substring(current_url.lastIndexOf("/")+1, hash_index);
196                                                 //open current thread to hunt down links
197                                                 URL  = "https://a.4cdn.org/" + board + "/thread/" + current_thread + ".json";
198                                                 ////console.log(URL);
199                                                 var xhr = new GM_xmlhttpRequest(({
200                                                         method: "GET",
201                                                         url: URL,
202                                                         responseType : "json",
203                                                         onload: function(data){
204                                                                 data = data.response["posts"];
205                                                                 ////console.log(data);
206                                                                 if(data == undefined){
207                                                                         alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
208                                                                         //draw from desu instead
209                                                                 }
210                                                                 else{
211                                                                         responding_text.forEach(function(response_item){
212                                                                                 for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
213                                                                                         //console.log (response_item);
214                                                                                         //console.log(data[data_entry]);
215                                                                                         //console.log ("----");
216                                                                                         if((response_item[1] == data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, "") || response_item[1] == null) 
217                                                                                                 && (response_item[2] == data[data_entry]["md5"] || response_item[2] == null)){
218                                                                                                 var start_index = response_item[0][0].legth - response_item[0][1];
219                                                                                                 text = text.substring(0, start_index) + ">>" + data[data_entry]["no"] + text.substring(response_item[0][1]);
220                                                                                                                 //console.log(text);
221                                                                                                                 break;
222                                                                                         }
223                                                                                 }
224                                                                         });
225                                                                                                         document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value = text;
226                                                                                                 document.getElementById("add-post").click();
227                                                                                                 semaphore_posts++;
228                                                                 }
229                                                         }
230                                                 }));
231                                         }
232                                 }
233                         }));
234         };
235         
236         //2) GET ARCHIVED THREAD
237         var getThread = function(threadNo){
238                 threadData = [[], [], [], []];
240                 URL  = "https://a.4cdn.org/" + board + "/thread/" + threadNo + ".json";
241                 ////console.log(URL);
242                 var xhr = new GM_xmlhttpRequest(({
243                         method: "GET",
244                         url: URL,
245                         responseType : "json",
246                         onload: function(data){
247                                 data = data.response;
248                                 ////console.log(data);
249                                 if(data == undefined){
250                                         alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
251                                         //draw from desu instead
252                                 }
253                                 else{
254                                         var len = data["posts"].length;
255                                         for(var i = 1 ; i < len ; i++){
256                                                 var comment = data["posts"][i]["com"];
257                                                 if(comment !== undefined)
258                                                         threadData[0].push(comment);
259                                                 else
260                                                         threadData[0].push(-1);
262                                                 var filename = "" + data["posts"][i]["tim"] + data["posts"][i]["ext"];
263                                                 if(filename !== undefined && filename.indexOf("undefined") == -1)
264                                                    threadData[1].push("https://i.4cdn.org/" + board + "/" + filename);
265                                                 else  threadData[1].push(-1);
267                                                 threadData[2].push(data["posts"][i]["filename"]);
269                                                 threadData[3].push(data["posts"][i]["no"]);
270                                         }
271                                 }
272                                 ////console.log(threadData);
273                                 semaphore--;
274                         }
275                 }));
277         };
278         //3) RIP POSTS AND IMAGES
279         var createPost = function(text, imageURL, imageName){
280                 ////console.log("url: " + imageURL);
281                 if(imageURL != -1){
282                         var xhr = new GM_xmlhttpRequest(({
283                                 method: "GET",
284                                 url: imageURL,
285                                 responseType : "arraybuffer",
286                                 onload: function(response)
287                                 {
288                                         var blob;
289                                         var ext = ".jpg";
290                                         if(imageURL.indexOf(".jpg") > -1){
291                                                 blob = new Blob([response.response], {type:"image/jpeg"});
292                                                 ext = ".jpg";
293                                         }
294                                         else if(imageURL.indexOf(".png") > -1){
295                                                 blob = new Blob([response.response], {type:"image/png"});
296                                                 ext = ".png";
297                                         }
298                                         else if(imageURL.indexOf(".gif") > -1){
299                                                 blob = new Blob([response.response], {type:"image/gif"});
300                                                 ext = ".gif";
301                                         }
302                                         else if(imageURL.indexOf(".webm") > -1){
303                                                 blob = new Blob([response.response], {type:"video/webm"});
304                                                 ext = ".webm";
305                                         }
307                                         var name = imageName + ext;
309                                         ////console.log("----------------");
310                                         ////console.log("Blob: "); ////console.log(blob);
311                                         ////console.log("MIME: " + blob.type);
312                                         ////console.log("Name: " + name);
314                                         //SEND RESULTING RESPONSE TO 4CHANX FILES === QRSetFile
315                                         var detail = {file:blob, name:name};
316                                         if (typeof cloneInto === 'function') {
317                                                 detail  = cloneInto(detail , document.defaultView);
318                                         }
319                                         ////console.log("Detail: ");////console.log(detail);
320                                         document.dispatchEvent(new CustomEvent('QRSetFile', {bubbles:true, detail}));
322                                         if(text !== "" && text !== undefined && text !== -1) {
323                         text = createPostComment(text);
324                         setPropperLinking(text);
325                                         }
326                                         else{
327                                                                                                 document.getElementById("add-post").click();
328                                                                                                 semaphore_posts++;
329                                         }
330                                 }
331                         }));
332                 }
333                 else{
334                         text = createPostComment(text);
335                         setPropperLinking(text);
336                 }
337         };
339         //4) CREATE POST QUEUE
340         var createPostComment = function(text){
341                 ////console.log("text-Before: " + text);
343                 text = text.replace(/<a href="\/[a-zA-Z]+\/" class="quotelink">/g, "");
344                 text = text.replace(/<span class="deadlink">/g, "");
345                 
346                 var quote_regex = /<a href="#p[0-9]+" class="quotelink">&gt;&gt;[0-9]+/g;
347                 var find = text.match(quote_regex);
348                 if(find){
349                         find.forEach(function(match){
350                                 ////console.log("---==");
351                                 var index_start = text.indexOf(match);
352                                 var match_len = match.length;
353                                 var index_len = index_start + match_len;
354                                 var first_quote = match.indexOf('"');
355                                 var second_quote = match.indexOf('"', first_quote + 1);
356                                 var post_no = match.substring(first_quote + 3, second_quote);
358                                 match = ">>" + post_no;
360                                 text = text.substr(0, index_start) + match +  text.substr(index_len);
361                         });
362                 }
364                 text = text.replace(/<span class="quote">/g, "");
365                 text = text.replace(/<br>/g, "\n");
366                 text = text.replace(/&#039;/g, "'");
367                 text = text.replace(/&gt;/g, ">");
368                 text = text.replace(/<\/a>/g, "");
369                 text = text.replace(/<wbr>/g, "");
370                 text = text.replace(/<\/span>/g, "");
372                 ////console.log("text-After: " + text);
373                 //if(text.match(/^>>[0-9]+$/g))   document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value = text +  "\n" + Math.floor(Math.random() * 1000).toString(62)/*.replace(/[^a-z]+/g, '')*/;
374                 //else
375                 return text;
376         };
378         var checked = false;
379         var timeListenerFunction = function(){
380                 var time = document.getElementById("qr-filename-container").nextSibling.value.replace(/[a-zA-Z]+/g, "");
381                 if(time  <= 5){
382                         checked = false;
383                         //console.log(time + "A");
384                 }
385                 else if(time > 5){
386                         checked = true;
387                         //console.log(time + "B");
388                 }
389         };
391         
392 document.addEventListener('QRPostSuccessful', function(e) {
393                         document.getElementById("dump-list").childNodes[1].click();
394                         setPropperLinking(document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value);
395 }, false);