selection carat bug
[4Free-FSE.git] / Thread-Rebuilder.user.js
blob9fe880a0d42d75ad81a46abaa084a7e272db6aea
1         // ==UserScript==
2         // @name         Thread Rebuilder
3         // @namespace    http://tampermonkey.net/
4         // @version      1.2
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 thread_data = [['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         //set listeners to build interface in 4chanX
23         document.addEventListener("4chanXInitFinished", function(e){
24                 var len = document.links.length;
25                 for(var links = 0 ; links < len ; links++){
26                         var class_name = document.links[links].parentNode.className ;
27                         if(class_name == "postNum desktop" || class_name == "qr-link-container"
28                            || class_name == "brackets-wrap qr-link-container-bottom")
29                                 document.links[links].addEventListener("click", enhance4ChanX);
30                 }
32                 //ENHANCE DUMP TABS (COVER, 482PX - 482PX)
33                 //DUMP LIST MAX-HEIGHT TO 490
35                 document.getElementById("fourchanx-css").textContent += ".qr-preview { height: 482px; width: 482px; background-size: cover;}";
36                 document.getElementById("fourchanx-css").textContent += "#dump-list { min-height: 400px; width: 509px;}";
38         }, false);
40         
41         var enhance4ChanX = function(){
42                 var qr_window = document.getElementById("qr");
44                 if(document.getElementById("qrRebuilder") !== null) qr_window.removeChild(document.getElementById("qrRebuilder"));
45                 
46                 var thread_rebuilder_table = document.createElement("TABLE");
47                 thread_rebuilder_table.setAttribute("id", "qrRebuilder");
48                 thread_rebuilder_table.setAttribute("style", "text-align:center");
49                 qr_window.appendChild(thread_rebuilder_table);
51                 var instruction_row = document.createElement("TR");
52                 var top_row_nodes = [document.createElement("BR"),
53                                                    document.createTextNode("Insert the thread number of the post to rebuild"),
54                                                    document.createElement("BR"),
55                                                    document.createTextNode("Must be in the 4chan archives"),
56                                                    document.createElement("BR"),
57                                                   ];
58                 top_row_nodes.forEach(
59                         function(node){
60                                 instruction_row.appendChild(node);
61                         });
62                 thread_rebuilder_table.appendChild(instruction_row);
64                 var thread_row = document.createElement("TR");
65                 var second_row_nodes = [
66                         document.createTextNode("Thread: "),
67                         document.createElement("INPUT"),
68                         document.createElement("INPUT"),
69                 ];
70                 second_row_nodes.forEach(
71                         function(node){
72                                 thread_row.appendChild(node);
73                         });
74                 thread_rebuilder_table.appendChild(thread_row);
76                 second_row_nodes[1].setAttribute("ID", "threadInput");
77                 second_row_nodes[1].setAttribute("style", "width:44.9%");
79                 second_row_nodes[2].setAttribute("ID", "threadButton");
80                 second_row_nodes[2].setAttribute("type", "button");
81                 second_row_nodes[2].setAttribute("value", "Set Rebuild Queue");
82                 
83                 second_row_nodes[2].addEventListener("click", function(){
84                         getThread(second_row_nodes[1].value);
85                         postID = setInterval(postRoutine, 1000);
86                         if(timeListen === undefined) timeListen = setInterval(timeListenerFunction, 1000);
87                 });
88         };
90         var thread_data_length = 0;
91         var posts_created = 0;
92         var postID = "";
93         var postRoutine = function(){
94                 if(semaphore == 0){
95                         semaphore++;
96                         thread_data_length = thread_data[0].length;
97                         fillID = setInterval(fillRoutine, 10);
98                         stopRoutine();
99                 }
100         };
101         
102         var stopRoutine = function(){
103                 clearInterval(postID);
104         };
106         var fillID  = "";
107         var fillRoutine = function(){
108                 if(posts_created >= thread_data_length) {semaphore_posts  = 0 ; stopFillRoutine();}
109                 else if(semaphore_posts == 1){
110                         semaphore_posts--;
111                         createPost(thread_data[0][posts_created], thread_data[1][posts_created], thread_data[2][posts_created]);
112                         posts_created++;
113                 }
114         };
116         var stopFillRoutine = function(){
117                 clearInterval(fillID);
118         };
120         var setPropperLinking = function(text){
121                 var search_regex = RegExp(">>\\d+", "g");
122                 var result;
123                 var index_old = -1;
124                 var link_arr = Array();
125                 while((result = search_regex.exec(text)) != null){
126                         var end_index = search_regex.lastIndex;
127                         var post_no = result.toString().replace(/>/g, "");
128                         link_arr.push([post_no, end_index]);
129                 }
130         //hunt down the text of what it linked to               
131                 var responding_text = Array();  
132                 URL  = "https://a.4cdn.org/" + board + "/thread/" + document.getElementById("threadInput").value + ".json";
133                         var xhr = new GM_xmlhttpRequest(({
134                                 method: "GET",
135                                 url: URL,
136                                 responseType : "json",
137                                 onload: function(data){
138                                         data = data.response["posts"];
139                                         if(data == undefined){
140                                                 alert("Invalid Thread ID: " + threadNo + ". ");
141                                         }
142                                         else{
143                                                 link_arr.forEach(function(link_item){
144                                                         for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
145                                                                 if(parseInt(link_item[0]) == parseInt(data[data_entry]["no"])){
146                                                                         responding_text.push([ [post_no, end_index], data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, ""), data[data_entry]["md5"]]);
147                                                                         break;
148                                                                 }
149                                                         }
150                                                 });
151                                                 
152                                                 var current_url = window.location.href;
153                                                 var hash_index = current_url.lastIndexOf("#") != -1 ? current_url.lastIndexOf("#"):  window.location.href.length;
154                                                 var current_thread = window.location.href.substring(current_url.lastIndexOf("/")+1, hash_index);
155                                                 //open current thread to hunt down links
156                                                 URL  = "https://a.4cdn.org/" + board + "/thread/" + current_thread + ".json";
157                                                 var xhr = new GM_xmlhttpRequest(({
158                                                         method: "GET",
159                                                         url: URL,
160                                                         responseType : "json",
161                                                         onload: function(data){
162                                                                 data = data.response["posts"];
163                                                                 if(data == undefined){
164                                                                         alert("Invalid Thread ID: " + threadNo + ". ");
165                                                                 }
166                                                                 else{
167                                                                         responding_text.forEach(function(response_item){
168                                                                                 for(var data_entry = 0 ; data_entry < data.length ; data_entry++){
169                                                                                         if((response_item[1] == data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, "") || response_item[1] == null) 
170                                                                                                 && (response_item[2] == data[data_entry]["md5"] || response_item[2] == null)){
171                                                                                                 var start_index = response_item[0][0].legth - response_item[0][1];
172                                                                                                 text = text.substring(0, start_index) + ">>" + data[data_entry]["no"] + text.substring(response_item[0][1]);
173                                                                                                         break;
174                                                                                         }
175                                                                                 }
176                                                                         });
177                                                                                                 document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value = text;
178                                                                                                 document.getElementById("add-post").click();
179                                                                                                 semaphore_posts++;
180                                                                 }
181                                                         }
182                                                 }));
183                                         }
184                                 }
185                         }));
186         };
187         
188         //2) GET ARCHIVED THREAD
189         var getThread = function(threadNo){
190                 thread_data = [[], [], [], []];
192                 URL  = "https://a.4cdn.org/" + board + "/thread/" + threadNo + ".json";
193                 ////console.log(URL);
194                 var xhr = new GM_xmlhttpRequest(({
195                         method: "GET",
196                         url: URL,
197                         responseType : "json",
198                         onload: function(data){
199                                 data = data.response;
200                                 ////console.log(data);
201                                 if(data == undefined){
202                                         alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
203                                         //draw from desu instead
204                                 }
205                                 else{
206                                         var len = data["posts"].length;
207                                         for(var i = 1 ; i < len ; i++){
208                                                 var comment = data["posts"][i]["com"];
209                                                 if(comment !== undefined)
210                                                         thread_data[0].push(comment);
211                                                 else
212                                                         thread_data[0].push(-1);
214                                                 var filename = "" + data["posts"][i]["tim"] + data["posts"][i]["ext"];
215                                                 if(filename !== undefined && filename.indexOf("undefined") == -1)
216                                                    thread_data[1].push("https://i.4cdn.org/" + board + "/" + filename);
217                                                 else  thread_data[1].push(-1);
219                                                 thread_data[2].push(data["posts"][i]["filename"]);
221                                                 thread_data[3].push(data["posts"][i]["no"]);
222                                         }
223                                 }
224                                 semaphore--;
225                         }
226                 }));
228         };
229         //3) RIP POSTS AND IMAGES
230         var createPost = function(text, imageURL, imageName){
231                 if(imageURL != -1){
232                         var xhr = new GM_xmlhttpRequest(({
233                                 method: "GET",
234                                 url: imageURL,
235                                 responseType : "arraybuffer",
236                                 onload: function(response)
237                                 {
238                                         var blob;
239                                         var ext = ".jpg";
240                                         if(imageURL.indexOf(".jpg") > -1){
241                                                 blob = new Blob([response.response], {type:"image/jpeg"});
242                                                 ext = ".jpg";
243                                         }
244                                         else if(imageURL.indexOf(".png") > -1){
245                                                 blob = new Blob([response.response], {type:"image/png"});
246                                                 ext = ".png";
247                                         }
248                                         else if(imageURL.indexOf(".gif") > -1){
249                                                 blob = new Blob([response.response], {type:"image/gif"});
250                                                 ext = ".gif";
251                                         }
252                                         else if(imageURL.indexOf(".webm") > -1){
253                                                 blob = new Blob([response.response], {type:"video/webm"});
254                                                 ext = ".webm";
255                                         }
257                                         var name = imageName + ext;
259                                         //SEND RESULTING RESPONSE TO 4CHANX FILES === QRSetFile
260                                         var detail = {file:blob, name:name};
261                                         if (typeof cloneInto === 'function') {
262                                                 detail  = cloneInto(detail , document.defaultView);
263                                         }
265                                         document.dispatchEvent(new CustomEvent('QRSetFile', {bubbles:true, detail}));
267                                         if(text !== "" && text !== undefined && text !== -1) {
268                                                 text = createPostComment(text);
269                                                 setPropperLinking(text);
270                                         }
271                                         else{
272                                                 document.getElementById("add-post").click();
273                                                 semaphore_posts++;
274                                         }
275                                 }
276                         }));
277                 }
278                 else{
279                         text = createPostComment(text);
280                         setPropperLinking(text);
281                 }
282         };
284         //4) CREATE POST QUEUE
285         var createPostComment = function(text){
286                 text = text.replace(/<a href="\/[a-zA-Z]+\/" class="quotelink">/g, "");
287                 text = text.replace(/<span class="deadlink">/g, "");
288                 
289                 var quote_regex = /<a href="#p[0-9]+" class="quotelink">&gt;&gt;[0-9]+/g;
290                 var find = text.match(quote_regex);
291                 if(find){
292                         find.forEach(function(match){
293                                 var index_start = text.indexOf(match);
294                                 var match_len = match.length;
295                                 var index_len = index_start + match_len;
296                                 var first_quote = match.indexOf('"');
297                                 var second_quote = match.indexOf('"', first_quote + 1);
298                                 var post_no = match.substring(first_quote + 3, second_quote);
300                                 match = ">>" + post_no;
302                                 text = text.substr(0, index_start) + match +  text.substr(index_len);
303                         });
304                 }
306                 text = text.replace(/<span class="quote">/g, "");
307                 text = text.replace(/<br>/g, "\n");
308                 text = text.replace(/&#039;/g, "'");
309                 text = text.replace(/&gt;/g, ">");
310                 text = text.replace(/<\/a>/g, "");
311                 text = text.replace(/<wbr>/g, "");
312                 text = text.replace(/<\/span>/g, "");
314                 return text;
315         };
317         var checked = false;
318         var timeListenerFunction = function(){
319                 var time = document.getElementById("qr-filename-container").nextSibling.value.replace(/[a-zA-Z]+/g, "");
320                 if(time  <= 5){
321                         checked = false;
322                 }
323                 else if(time > 5){
324                         checked = true;
325                 }
326         };
328         
329 document.addEventListener('QRPostSuccessful', function(e) {
330                         document.getElementById("dump-list").childNodes[1].click();
331                         setPropperLinking(document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value);
332 }, false);