Thread rebuilder fix
[4Free-FSE.git] / builds / 4-Free.user.js
blobd25670dffcf66a4369a8bc79373983c238c3a5f3
1 var __extends = (this && this.__extends) || (function () {
2 var extendStatics = Object.setPrototypeOf ||
3 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
4 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
5 return function (d, b) {
6 extendStatics(d, b);
7 function __() { this.constructor = d; }
8 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
9 };
10 })();
11 // ==UserScript==
12 // @name 4Free-FSE [4chan X Enhancement]
13 // @author ECHibiki - /qa/
14 // @description 4Free - Free Stuff Enhancments. 7 additional features on top of 4chanX
15 // @version 1.3.13
16 // @namespace http://verniy.xyz/
17 // @match *://boards.4chan.org/*
18 // @updateURL https://raw.githubusercontent.com/ECHibiki/4Free-FSE/master/builds/4-Free.user.js
19 // @downloadURL https://raw.githubusercontent.com/ECHibiki/4Free-FSE/master/builds/4-Free.user.js
20 // @grant GM_xmlhttpRequest
21 // @run-at document-start
22 // @icon data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QB4RXhpZgAATU0AKgAAAAgABgExAAIAAAARAAAAVgMBAAUAAAABAAAAaAMDAAEAAAABAAAAAFEQAAEAAAABAQAAAFERAAQAAAABAAAOxFESAAQAAAABAAAOxAAAAABBZG9iZSBJbWFnZVJlYWR5AAAAAYagAACxj//bAEMAAgEBAgEBAgICAgICAgIDBQMDAwMDBgQEAwUHBgcHBwYHBwgJCwkICAoIBwcKDQoKCwwMDAwHCQ4PDQwOCwwMDP/bAEMBAgICAwMDBgMDBgwIBwgMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEIAHQAeAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APozxLp8ujX7W89pLZ3EbEPHIpVgckdKqxz+XEVb5Wz15z9MVqeOvHd98R/GF5rl5sW8vsbxCu1VAXYABnpgY5PNY8SZHRiM9f8APvXsGZcubX7PpFrKl1DL9s374Y5MyRbSB86Y4z1HJz7YqraRrJdfvP8AVnuO1aCeFtSjsv7QazvItPiuEt5LryiscUjDIUt0BxzyelZMrCCNSqyTSbgojQfM7EhVVeeSSQO3X05o2Dc6PS/C1xcTwXGLuztVLF7uEYO1flKxMQVMhJCgnIXJYhgu1t+xtQLOOzt44tPsFcukKbmVWxjezHLySEYBkcs57nGAI9C0WXSNBt7a4l8yZcvKUJ2tI2N2PYABQepCLnmu++Hvw9k1K6+0TSbbWPjchI83I6Dvgg9+x968uriFJ+Rs8O1oyh4N+HE2sSLIy/uR1PTNel6f4RsdNt1VYwy7RnPr3/CtC3ijtbfyokWONeFCjCrQh3nHfrkc5rjlNs6IxSRpeELlNNvWt/Mgs7W8UxTyeQGEanuAP8815f8AFj9nSz+ImoSXGg6hb+H9caYbbw23m2l5yADNCGQkkc70ZHzgsXA2nvmJSTG5frTTyM+p/WiFSUHeISinueZ/EeD4xfCr7Po66mmqWclvkS2lxEr5BxyZVTAPYby3qO9eJ69Za1FdT3GsWOsWsxO6ee7t3CKf9qXBj/JiK+v7tdltGJGhm+0J5hIbcyjJXY3p0zj3FQTaYBDD5sK+TIu6POD8uSOPTkH06V1Rx009UjL6vG2h8fQXLQRLNbzbvMUjKH+Fhg8+hBPTqDUBn83y9qIu3cdwbDP35JOOO2AM+5r0f9ovwDD4X8UWt9Zr5drqyNuQfdSaPbk+nzKwPuVY9ck+eTEKobq33eR7Yr0qdRTipIwlGzsTIy3ARfLjjX+NlUtgdyR7Dnj0op2p6jFqgtRBZw2f2e3WKTa7N9odckyHPc+g44FFaEk0+nwxW8Xl3CzNINzgKQYzzwcjB6A5HrUIRBhfMWPzMgsxPyY+mev0/rWleWMUNo0igbupCnAH+fSsu+/0yTdI0kk7EIEUbpJCBjAHU4A/ADtRcB15fbbZbeO4mELnfJGJS0ZYcBseuAeozj614/8AHKy8Q+P9WsbbRbqzsdL0m7MzT3WoX2kx3lwqFY57bVbQlIdm6RF81XjkaQkgqqPX1N+z18E4/Eeqz3XivTt2m+Vi3gl+aGQn/nof4xj+FcrzjLda9ST4bWdnqErxTNHb7z5ccI2hF7DJ7e2OleXja8Zw9nHruehgJSo1VWtqtrn58w/Gf4x/Bi3Ua9D4mislHyTeLPDv9u6aqdQ39saHljkfxT2gPc57fUHwV/bij8UeDtKX/hHLPXZGt42dvB/iOy1h9zAE/wCiytb3YGT0MWe3XivXpPhR4bjeSRNPa1uJBgy2dxJZyPzn5mhZC3frnrXP+MP2dPD/AI/h8rVoYdYVRiMarp1lqDRgdvNkgM+O2fN3e4ryXTmlaEvv/p/ket9dw1SV61Ja9Vpb0Stf5th/w194EW5jt9ZvNS8I3QdYWt/EOkXmkszHOMvNGIyTg/dYjiu08E+O9B+IP/ID17RdaUZOdOvorzAHX/VseleD+OvgLafBPw899a+JbTwppszeWIrfxXfeG7d+4VRcS3tvI3HCCFQa+fdW1nw74x1SaFtP1C4aFdyanrPgDRr23Z+w+0RzadfPg4y3lgHsfQjHEb8t/T/g/wCQnSy+fw1HH1V/wS/U+ivGPxR8beFfiZdWfxMk8QfC7wj4gebR9G1O2NjJBYX4dDb3DThXYKVRztuAqPvbfEYlk8q/8NP20Ldf2bIvGXjCyurhtG1e68N67qGh2ok0+O5tpWi+1/M48u3mwjBiSqtIFzjazfF+gfs/LrXw/bTZfi7dXT65cyWmuJa3Gu6KmsyCQ7ITAbO7tyYfL2oV+UeXk7iOO80PwT44+E/wg1L4e+D/ABcukXGoQ3UWkWsvjm2jtraCbPm77O402N5yQ07sUkiBZzgIowJftY7xf3N/ob/V8NUjpKPTqo6L1bd38+57D8K/+Cm/hO9+MfjHTfE97qVjpd3qFtH4Thh0qfULidTH5bweXaJI7SPIiyKuCSZ2AyE4+rJ2Vk3LlQwzggqRn2PP51+Z3wc/Z48Yfs6/Fux8S+EdZnsUXSriy1OWTxV4ZuLlN3lkG2M0axpEWjwyupcL/wAtSCyn2OL9p7x+mnLI3jya4hJDJKmo+CLlT68pdxg/hU06lRL34t+if6lYrL6E53w9SKVusl+if5s+lP2iNCbV/hFqFxEokm0pk1BRjOxEOJT+ELynjuB9K+b5pFjEe2RJdyhzgEGM85U56nocjI5HPUVW+IH7XfjBtG1W60/xTqUsdw0sMOkQeHfD2rSeUyEL88OrruySF/vFjwvOKNMSS1toVuGWW4WIJIy8KXwASPxya9rLarlGSaat3PBx+F9k17yd+zv+iNGwhW7Dbg67hhCB3z+oxnuOSPpRVixjaW3VF4kUkhy2FVQMkZx7569/eivS5jgsdD4V8Lan4+1Z7fSd3yyYnu2A8q34B6g8vz90YxxkrkGvZ/h/8E9E8ByNcLbrd38ww00o3YH91QeAAe3qM9ck+JeFPFXiHwJoyQaNd3umWjLJMiiFJo5AZHZnAmVwAHLDCbVz1Get3xB8WvFmoiRk8QamLGYnyYs20cyD/aeCONwR6/KDjpjiuOvRrTdk0kawlBan0Zql/a6VZNd311BYWkQJe4uHEcSAcncxIAryXXv22vhnpt1cW9n4qs9fuoRlotFVtQX6ebGDAp6/ekHQ18q/GY6h4n+HHiC9e6u77VPFDx6fayXc7zNHauwi4ZiWCmEzTN3+cjsBXCmzs/hT4Au5bdN8Gk2sl0+771y6IWJP+0xAGPcAdqyjgUviZt7S+x9Kyf8ABSe38Ty6hH4Z8H3zR2V29ibrWLyOHdKhw5WKHzd6g8cyJk59K8e8W/tp/FH4leGfEeqQeIo/Dujx29wNMh0GyWGW6EcbYmMrmSf5nB2CORNwAP8AFivP/D3wu8UX3w2sfDfhvSLjVNTktWju5w/k28BCGS5d5cHaW+ZFwCd8seOSAfqrwb+xsvgfWfCUN1rdneajuTVnhsLQpZ2Ftb7WiVWkbMhabygCVUbVkG3owivKjQhKdtlf+vU3w9GVWpGC6u3+Z5n8GP2YfEX7QOoeH/Ek3nx26TR/aPEWplrmaQzRmIhZHJkmYvIo4baDgFlr7a+Ev7P3gj4W6Sv2fSLO6uLdnFxqGoQpPcPtY5bLDCDgHagAA9TkmHw7HexeBdM0mS+iuJPIa0sXe2EXl3FrzFkp8uB5W/G3oh6918S6mfE/gHXY4PNt212wHlc4eBriIQBeOjq4OfQ1lLFJx5um5EqMufke97HnH7Pvj6/0f4Sya9fRs0dt4sXxFFFklja3ytazMqjnd5kl1KoHDBk6biB9N/EXwnpet+DrG8tdSje9hkS70+6VxJ5EwGVkQjnBBKsAcOjMpyGIrzTxx8NF8NeDbZtMtbRY7C38iWKWTy4liXY8YHH8EkUQAGOGbvXMaV4p1LwhcWtjJc6U2nXzBdNkZXVQSu77OXyQCQGZOORuUY2KG4cLmDnNRqaOV7et9vua+47cVgYcjqUPs7+lt/vT+TR6/oHiaTWdPhuVZ4nbIkj8zd5MiMUdM9yrqy5HXbWP4f1C40f4k+INL8uG30vUIYdY09Ik2LubdFdxYzztdYZM8Y+1Adq5PwZ4wvLL4p6lok1nMv8AatnFqsTQyedGGUrBOuMK4A227Z24zIxJGcV2OoD/AIqLR7lTtmWWa0cEZHlPE0jD674Ij9Aa9PVHlGZ8VvgnoHxz8GzaB4m02x1JlBW0vZoEa6sJcgx3EUuN6SIwVtykZKnsSK+KtLurq8so2uPLN1AzW0xRFCmWFjE/A4B3I25eobcDyDX6DLhQrMPlZ1XI7FiAP1Ir5U+JvgFfDvxH8WaWltAy/wBtXGrQksyn/TNs7qecffLNwONw5GTW1CbTsO7cbPoeWq8sDn5nVhyAOMZ9vp/Siuk1rwzMu0+Wq7UCgKgXj3x169Tk+9FdXMjHUovrN1cafDBJcSy29qzmCCSQskG7G4qp4UsQMleTt5qnq+qySadct8/mKjvuH0PP1q5b2vl3MZm8yKJ2wWHYGtHxXptimnpJbNbtI2S67929eM5Azzz3xnmtWQZXhn4IX3xz8SWPh7SbyxsGsYn1Cea6LsvkxgQ4UKpJbdPHwSBw3Paur+MP7E/g/wCHXw4ittUudS8Tavq0pKhlW3tIY7dGuZJGiBJKDylDAu2Q33epr0f9jDQ7bQ7c3DSSNfa1b3LQqeQtrbS28e4n1Msrr058o8kg11XjSFfGP7TNho8/m/YdN8KXbhk5xPey+TtP+15NvKw9s+tcU6j5/JHRFWR47+3p8ZNb+BvhfUIvhv4Rg8R+Ko5LXQ/DmgW8YgtxNLKtzKSFwqxMsUJblQBbSZaMHePz9/aL/wCCpXxV/Z6+MPhPw3BDBca9Y+H7HTdcsLSxtL22tb2Oea1ktxPIGwEkt5V+WQFjkknGR+qGo22laf4p8Laz4mm/svy1u572V0LCE3Dr8rYBwFknVN3RVZiflzj5x/ao/wCCPtj+1z4i16+0vw54T8Er4X1C/wBZk13w/przXPiqO/ma4W4uMz5urpkfKTArHFJHIuDEyJFOCw+GxFd0sQ0o2V/zX4srEY2rg6UasE93ay+T/BfI7L9kL9pa6+PPwVt/EEtpJaX9lqscyxGOSMySeUEMZ8wfKXhfjDOCI5H3MDmvbP7WsYtetfJuF+yXU8N6GdNqpHJKssgH+8YzKCe6z9NorhP+Cfn7Ldh8Ev2bNX0Ftc1zxBZ+I9al1QNqMCw3Glv9ltbZ7aORXYTCKW2kAn+USEsdm3lu31H4TX1v8QNJLKl1ot5E0eoFcpslVg6YAOUBZp2UgnYzlMjKE/O4mVOjVnQi7xV0n/X3fI9SnV+sxjiLWbs7ev8AV/mU/wBtLxp46j8Kw6L8OtMsH1KZD/aGoakN1nZpJujCspyHbknZtkxkMYyADX4y/wDBSL9qz48fsmfGTT/Att8Tjqmr3WlR6nqGn2mnR3NpYQs2yFSJYf8AWMYmkyqL5f7tgSWBX94/DOiT2VkunapL/aFrbsBBcnCyPGPuiQdN69Ny8MBnCnIr5c/bd/4J03X7aXijxx4eh0fw3pdpDc6f4ij1+x0SGPVHtVsBCkd5ciRJ76AXVrMPswZCEKEPmKIHuyHC4fE1eWu0l3fTscuaZhUwtD92n8tfU+Y/+Ce//BRLVvi54r8Ft4qabR/F+ntDbXVvNIfIubab908sW4n92BJvKgkpJGFPG0t96fH3xbfeGdJ8K6lYm4kurHxFHdSRo20zxC1uhJGfZw2w56FweoBH55fCv/gmO/grQfinY654gjvL3RdMRPDMbrEl7p91b5nnnCK7E7Fe1QqrOkYu4kLkspr9EfibIPFfhvRr1bdo1k0ptXlT72xZPLYn2wqucd69jExhGu6UJcyj1/E58PJVacK1mlK+57Zof2bxT4Sja3kV7bVIBJBcKPnMciZVhn2YEV4b8cdKmvPifHetGrSanptvfPjPVl8iVR7o8ERPoJDmvSP2W9W8/wALzaLcMrSaDcmNDGSxeGRPNjbnHRzLH7eT36nD8Yaol3d3EckMc0mk6xf2dyjgeZJbyTNIio/VVdHmT2KZx8oJ546MnltdHlur6NbXcNusEMsbCILMXfcHfJyRxwOnFFdXfaVFZ3DLHIs0anCyKv8ArF7NjsSOSp5ByOMYBW3MYnj2iXlurtFcXV5p9vPBJDLJB87OpB+TaMHaeAQSc0f8INbxhGt7mO93KplkVSIycBioLAMCOh46g9RgmgtnJJpy3W3dbNKIidy7g2CcY6jjv06VpaT4lOnwNGq7lzwSM7RXU79CEj0D4JeIbHw18VYorpbiGU6DY6fYpER9nhE/kX06ncd3yvLNg8n5TnoK7G1muZPiJ8WLy1tWutS8O3GmSW9vHhpLuBLFJXjTPSSTfcxLngMVbvXi/gtbrxb4os47aG5m1CxmhjVI1Z3uI4owwCgDJ3RL5Z255YivrD4e6MND8eavrX2ETPrKQGdpW2SJthjibjHXMO7nGCMZ644po6NVqcL4l1W1tPHPgm8h2XFlrj3FpbXqMcIZIRNER2w5hC8jOSuMc10E3gu2v/D0OjyW+3SoNqrZwu0EAVeibUIBj7FD8pHBBFP+KXwonsLZrTTYUk0mS7GtaW0X/MPmBPmbe4VTIX2fiOQwHa6fDHrvh+21CGPatym5k7xP0dD7qwIP0rxMwotTVWD3PTwuIXsvZSVzBSFbCyhhiRIYIFCRxIoVIlAACqBwAAAAB0AFVbHWYb+/ureNlka1YJKVYNsbAO046NhlODzgg9607+LyzgZ68ZqBIdu5lX7xySBjJxjmvFa1OiMkOHSsfxXoEfijTFtrhrxUXO1ra7mtZkBxuCyRMrqGwMgMA2BkGtqKEuea0bDS1kDOVYqoycDNXT5k/ddmLmj9pXPK5vhNY6doy6XpOlafZf2nKIvLhhWJZcbpGLlcE5AclmySzc5LHPQXfwxbSbGSxkIbydDFnJJ1LstsqqPwUH6ls12Pg3Q7rxB8RTcuGt7PTrUqsPBIaQjG8jIzhWJUEgDyjyRmk8XazGurXkm7y4lJ3Pj+HaBnHsiAkehr6HAUuSnfq9TixmIc6ijskrHOfs+6TDpXjTXo2UrcCwsI7gE/cYSXjD6fK4ri/F2jyXet6TrUbsIdbfU7uQfwjZOdyntkAqwPsw6Zq1r3jhUk1a102Vr7xN4wwPsVofNuYLSIMFBVckM7NKN2AFRgSVO3Olqlo/gD4eXUniKa3h1K8sbjT9J04OrTQpO8jSSsASN3zkkjgKoUncwUd3W5zSerbOP8TNa21/I1i1wYWUcSsFLkDvgHGDnBHbr2wVyOq+I/kPzfr0orQws2eS6dcq3yrnLcPnoRkED8x/Kuk061WJMJ/wAtSBx3H+H+FcXAs67ZAuxclQxzhiMZ/LI/MVpWHiX7GwV9zMpz8vrXXIzXke5fCrSktpmvFm8l7FNz7HKM7AhgoKnJBVJeOn8x79pOow6P4f8AtTK915Z8twsn7x9z7SQ2Qc5568nPQnNfIvwp+IcmufEBtFjkaPzILGD/AIHdXEttGeP7u+Q/RhXpmrfH2x017bSnuIVuI7iS6uLeSTasiLM8aQuwOYxJJ8pkAIjVGZsAZriq9zo15T3L/ha2mr4l0GxtdJk023jn8yUyfLuDxsMhAcHIfO4knHr1rlPix4u1n4K/Eq3XR7OHVNF1N1iu9OaTynDSSRxQyQyMPLRvMkWM+Yyo2Uyy43ri6v8AEez8SfDzWNSjuY4rWxm2OJCsnkyx5dlkCnCAuzLCy8BVQDKSFG80/wCCh/x303wh4e+G+pateR2el+OLS50aa7limuLeGW4hge3Z4ImQzZkJVEd0jEjxs7Kqk1xykpwlE0pxcZJ9D1n4VfHvwf8AtEaDPq3g7W7TV4LKY299AMx3elzAkGG5gbEkMgII2uBnGQWGCb994HtdU8TWmrtc6pb3VntAEGoSxQyKpJ2vGG2MpLcgjnjOQBX4yt8FvFXgD492/wARrXxxrXwOkbUQ2t31pLafadOHnPaXxj0+JfJ+xxanGgniknl2QahaStEyEtX178H/APgpX8TNV0nWLrWI/h/q3wzs3NnonxYukl0WPxLKmFkFtpDFpL+YSCSL/RWSJnjJXAIUeFUw/v2jr1/roexGLSUou19P+AfoXcQWul6Y19d3VvaWcXMks0gjRR7seK5jSfjjpPjLS7htEs9WutLhBzrBtDHZSEdkZ9vmHIxgDHQgt0r468DeL9Y1O9s/F3ibUPEureG5ZY4rzxP45hjsLOzWWWPyL+z0aJv9GgjYIGe5bLRzFmQha+vfhZ8RtFaORdsf2yCKW583UGCR2BjkMd5Ei4CosVxknYFXZNGd2CK7KNOko8+5x1JSTtH7zvfAN83h34f6tqd1b3FrJAHncXA2u+2MOCfqTx0+gHFfJ/7UPx31zwTcTaXfRy2cO8RPDDj7QWJzG5wS3luApD9OeSM8+weK/jxp+ufBPxVLpd9NqiRXqW0ctvEGM6GFZEMQcBZAwjKqTlHPOSpzXxT+0P8AFuH4c6p4ij1KSC40vThNHdO9/JNa65pJlWO6064vI3jk1C8smkikFtbPHbRohDyYzXpSl7qb0uckY+8+p0X7P/j+38ea14lim+yxx2dgISiXCySRGVm++BnaR5IIHJHX0r1A6qsfg2S8j2wzOx3GJdu/JZWBx1GM/gK/Pf8AY3+LDH46eINDXVpGuv7EvfMgfZCr+XPB5LRRKAoPlO7HAzjceRzX3D4Nu77XfgHNeLD5kipJKwx90C4ZfywQK6cPbkHXTjJ38ihquusPl+YcZ59xn+WKK41tdmcOGRXaUDBJbMfOTgevbnPX8aK1Oc0LiyWxgUqFbcc5PX8qa1wRYrbNHb/LOZ/N8j/SORgqX/ujGdvqSas3c9vLo800syR3MbLtg2EtMCDlg3QYIHBI+9x3qlrEllaX0f2O4e7ikiRy5iMflOfvJjJzg9+9dLMkdl+zto73nxj0OZo2/wCJlr0EJcngpZW5vWHHT5gB9WFfKt1+0dd6N/wUZ+IHgrUNSaz1nUvG1zo2l3kBMU+jWjuZvttixYL9o+zmKLLEgAuCCuQ/17+y9eWNl8UfCdxeXCho9U1KMKWxHbi8sIFhkdj/AHm025jA7tIO/B/Gf9sP4lap4r/ak8YavqUVvBqEd+LqAyD7OAypsXdOzptYwNbPiEO6mRTwQVrzcVdrQ9HC07/cfq/8UPGd98MfDdppFjM0cK7bHTprVd0dzDBFNKYFjd1ZsOgMlhIwlhZnktGkBktBn/t8yR+N/Dv7IvheRry4h1jVLia5SzmjiumtrOyjeQRs5A5QBSSQMN34FfMX7M37eGtftJ/BvxJH4ohtb6a0tF0N7m4aCG8vZrkERpchx9muShhGDmC5dWJihmdHJ1f+CnGv32ueNfgqtvbrLH8N/g/qnjOWMXb2k9lcX4NnbSLJHPBPGwna3YmKRmxwYZlbaOPC8/JL2mjute5VaMYuPJ5u39fI8R8V/sM+Pm8K/DTWNFuPH/xW8I+J/DFj4k1Xw9qk8lm8l3Hp9u9xavctCBKrpDarB98lYfL6RxtXcf8AD5/xZ+z5H/wjrfBLS/D+rXB+1XEGui8lv5o5CxZ5DNBHKzu3JkdmJOc/N0+a/wBsP9tjVPEVpo/gfwn4y8SWXhHw2Le2isLvWbuQf6MhSG7WWS3trkKwCFLdw6qApJ3DA+fNU12Ky169S+t7+4uLaMX1+93bSRtAGIxM27GN29cEksxYYzW+DouNNe0sdEsUlC0N+t7P9L/ifZvg3/gsr4k1L4sG41TQfBsng27Q6ZqOiXy3Vxp2kxy5R7qMNI8kWxXJkjj2h4wVAU7SPob4lfGXXvg14ttofHPiS7ivLNbfUdKvvGOnCOTVIPLFvaanb+HFP+rlS2htbyXUpWZD9mutgBr8qr3VrGef7ZHIzw8IlyWHmoD0VyOGU54Jz1Hfk7/hH4jrBDHYTMlnqEblrK8aMzNOQu0W79SY3QeWBhhtKqBlVJKuHjD34L1/zOfnc3aTP2M8Dftb2fxw+HvjZbGS4nuNQ3f2nY6rqb6jexXKWM4WO7lCRwliIH+W0H2dY3RY2OCa+Q/2v/2nfEXxm8U3+pX8lmsfhe5kgiEG210fwvBuZPKijGS2QQHChpNpDEA7a5H/AIJcftE2N3+0cvhGSB7fTddTZD9ok3XDSQWtwUt5xk4kjSa4j+b5yqqGwQBXE/FzU/CPwc8Ta94duNUtbbxL4fvrhbV8SXl9aXHmySjaFz5eXkJI3KCHJI+bmK0bwhK12ro0w9ueUbpbO70O68F6RrVhHp97ptrPo10Yvt1pPHixs4wyMBMgBM90GUnDykK4PzfxLX67/sbXcHjz9jDUtXhjjX7fYymFUO5QPsyXGFJycGSQ4J6hQfevwE8dftg6pJfSXHh2E2O5HWI30glFqrLEzrDFnYoWWNnTdvwZXAGTiv1Y/wCDen/govoPx3+Dz/A/xhexWPxD0dXbThLiNfE2mrbxRZiOfmuYY4v3ifeZAJRuAl8vShTqRvJ7E47EUJKMIatddl6HawtGuqTKfvxArgc5YcGiqM9rcWupbZd32pQpl4437QW/8eJorsPPLupTt57/AO8efxpkB8+QH7u4ngdvaiiuqRlHYXXLdpI/H1ss00Mdt4Ig1KHy22mG6glZ4Zl/20eeRh2y3IPSvwpv/G+sxfES78SrqU39ueJ52bULt445ZJZJiZZJRvU7XZ1B4wPbpgorjrap3O1Nr2dj6o/4Jm+CYbP9vL4YaPDfavHY+OPEdlbeIEW+kH9swpHeTeTcc/vIzJDE2xsqDGpUKQCK/wDwU++OPiS+/bi+LlgdQkjs4NJ8H6RLBGzLFeWVvYQXqW0qZ2tGbuKK4PAbzI1wVXKkorjj8H9eRdbSRzn7Svxd1TwZ8GfBPhvSI7XTI9O8PR+Kv7Rtg8epXFxcXtxG8Tzht3kKEQqibTlFyxxivmrWfjh4g1vU0+3XTXzSN8zXUslwxIyM5dyc8n86KK6cGlyM9HM2701/dRa1t99xZvtjC38bLPEFAjfG3nHvuOfwrH1i5ltLS6khllhkhiYxujlWTAOMEc0UVueTLYh/Z28Yah8Nfj94D1jSpvJu9O1+xuIQR8gImjypAx8rKSpHdSRxX3x+21+zf4d+Kf8AwU18X2t81/ax6h4asNXm+ySrGTcLD9nDcqeqW6E+rFietFFaUkrWPPnJ/wBfI+Gbm2W3uJI/mfy5zEGc5YjPf8vpXuP7Id/J4L/a7+EuqaWxstQh8X6VbxzxEq8QluY4mZT2YK7YI7nv0ooohu0aVPs/I/Y/VdcuLi71Hcy/6ZfXnnAIuGK3k5BHHy/RcDHGMYFFFFYm8tz/2Q==
23 // ==/UserScript==
25 Uses:
26 https://github.com/ccd0/4chan-x/wiki/4chan-X-API
27 https://github.com/ECHibiki/4chan-UserScripts/blob/master/MD5%20Filters%20by%20QAJPYOtGo.txt
30 ## About 4chanX-FSE
31 4chanX-Free Stuff Enhancements is a userscript that operates with 4chanX to give it additional features. These enhancements were written by me from early 2017 up to 2018 as a way to teach myself how to work with JavaScript while giving something back to the community I took part in.
32 Some of these features are simple, like the password viewer, others are more complex using multiple concurent AJAX calls such as the thread rebuilder or the image adder. <br/>
33 Below is a description of the features this package has to offer.
35 ### Danbooru Image Adder
36 #### Adds images to your posts
37 Adds an image to your post taken from the danbooru's image collection.<br/>
38 Supply it with tags via an autocomplete, set the rating(s/q/e) and it will give an image for you to post with.
40 ### Kita-Yen
41 #### Color text
42 Converts the colors of special symbols from plain black into other prettier colors(yen == purple, kita == dark grey).<br/>
43 #### Hotkeys for Convinience
44 <strong>Press ctrl+\ for ¥</strong>
45 Highlights the whole line in purple much like how greentext works<br/>
46 <strong>Press ctrl+k for キタ━━━(゚∀゚)━━━!!</strong>
47 Highlights just the word in dark gray<br/>
49 ### 4chan-Ignoring-Enhancements
50 #### Hides images.
51 Gives the ability to hide images with ___ctrl+shift+click___. Stores in browser memory for new sessions.<br/>
52 Also includes over 20,000 MD5 filters of things like frogs, goldface, guro done by from QAJPYOtGo<br/>
53 https://github.com/ECHibiki/4chan-UserScripts/blob/master/MD5%20Filters%20by%20QAJPYOtGo.txt
54 #### Word Filters
55 Also includes the ability to do word replacements with a regex replacement system.<br>
57 ### Thread Rebuilder
58 #### Rebuild dead threads from scratch
59 Rebuild a thread from 4chan's archive.<br/>
60 Simple system that could use some additions(using 4chan's offsite archives for example)
62 ### Visible Password
63 #### Shows your 4chan post/delete password
64 * Displays your 4chan password in an inputbox.
65 * Top left is the post password, Bottom right is the delete password.
66 * Edit the input boxes to change them.
68 __Note:__ some 4chan boards don't allow custom post passwords. May require cookie manipulation, but this has not yet been tested...
71 var Constants = /** @class */ (function () {
72 function Constants() {
74 Constants.DEFAULT_HIDE_EXPIRATION_TIME = 172800000;
75 Constants.MILLISECONDS_TO_THE_HOUR = 3600000;
76 Constants.HELP_ICON_SOURCE = "data:image/jpeg;base64,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";
77 Constants.BLANK_PNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAALiMAAC4jAHM9rsvAAAAG3RFWHRTb2Z0d2FyZQBDZWxzeXMgU3R1ZGlvIFRvb2zBp+F8AAAAo0lEQVR42u3RAQ0AAAjDMO5f9LFBSCdhTdvRnQIEiIAAERAgAgJEQIC4AERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABERAgAgIEAEBIiBABAQIECACAkRAgAjI9xbzUCtI4axs4wAAAABJRU5ErkJggg==";
78 return Constants;
79 }());
80 //unassociated functions
81 var Generics = /** @class */ (function () {
82 function Generics() {
84 Generics.storageAvailable = function (storage_type) {
85 try {
86 var storage = window[storage_type];
87 storage.setItem('x', 'x');
88 storage.removeItem('x');
89 return 1;
91 catch (e) {
92 return e;
95 //What Browser
96 Generics.detectBrowser = function () {
97 if ((navigator.userAgent.indexOf('Opera') || navigator.userAgent.indexOf('OPR')) != -1) {
98 console.log('Opera');
99 return 0;
101 else if (navigator.userAgent.indexOf('Chrome') != -1) {
102 console.log('Chrome');
103 return 1;
105 else if (navigator.userAgent.indexOf('Safari') != -1) {
106 console.log('Safari');
107 return 2;
109 else if (navigator.userAgent.indexOf('Firefox') != -1) {
110 console.log('FireFox');
111 return 3;
113 else if (navigator.userAgent.indexOf('MSIE') != -1) {
114 console.log('IE');
115 return 4;
117 else {
118 console.log('Other');
119 return -1;
122 //gets json keys by regex test
123 Generics.getJSONPropertiesByKeyName = function (JSON_obj, regex_string) {
124 var regex = new RegExp("^" + regex_string + "$");
125 var rtnArray = Array();
126 for (var key in JSON_obj)
127 if (regex.test(key))
128 rtnArray.push(key);
129 return rtnArray;
131 //send alert to 4chanx
132 Generics.alert4ChanX = function (message, type, time) {
133 var detail = { type: type, content: message, lifetime: time };
134 var event = new CustomEvent('CreateNotification', { bubbles: true, detail: detail });
135 document.dispatchEvent(event);
137 Generics.getJSON = function (url, callback, extra) {
138 var all_extra = [];
139 for (var _i = 3; _i < arguments.length; _i++) {
140 all_extra[_i - 3] = arguments[_i];
142 var xhr = new XMLHttpRequest();
143 xhr.open('GET', url, true);
144 xhr.responseType = 'json';
145 xhr.onload = function () {
146 var status = xhr.status;
147 if (status == 200) {
148 callback.apply(void 0, [null, xhr.response, extra].concat(all_extra));
150 else {
151 callback(status);
154 xhr.send();
156 return Generics;
157 }());
158 var FeatureInterface = /** @class */ (function () {
159 function FeatureInterface() {
161 return FeatureInterface;
162 }());
163 var TopBar = /** @class */ (function () {
164 function TopBar() {
165 this.shortcuts_container = document.getElementById("shortcuts");
166 this.shortcuts_menu = document.getElementById("shortcut-menu");
167 this.fse_icon_container = document.createElement("SPAN");
168 this.fse_icon_node = document.createElement("A");
169 this.fse_style_node = document.createElement("STYLE");
170 this.fa_fse_style = ".fa_jpy::before{content:'\f157'}";
171 this.fse_style_node.innerHTML = this.fa_fse_style;
172 this.fse_icon_container.setAttribute("class", "shortcut brackets-wrap");
173 this.fse_icon_node.setAttribute("class", "fa fa-jpy");
174 this.fse_icon_node.setAttribute("href", "javascript:void(0);");
175 this.fse_icon_node.setAttribute("title", "4F-FSE Settings");
176 this.fse_icon_node.textContent = "4F-FSE Settings";
177 this.settings_window = new SettingsWindow();
179 TopBar.prototype.build = function () {
180 var _this = this;
181 document.head.appendChild(this.fse_style_node);
182 this.fse_icon_container.appendChild(this.fse_icon_node);
183 this.shortcuts_container.insertBefore(this.fse_icon_container, this.shortcuts_menu);
184 //https://stackoverflow.com/questions/44606399/typescript-how-to-access-the-class-instance-from-event-handler-method
185 this.fse_icon_node.addEventListener("click", function (evt) { return _this.open4FSettings(_this.settings_window); });
187 TopBar.prototype.open4FSettings = function (settings_window) {
188 settings_window.displayWindow();
190 TopBar.prototype.getSettingsArr = function () {
191 return this.settings_window.getSettingsArr();
193 return TopBar;
194 }());
195 var ImageHider = /** @class */ (function (_super) {
196 __extends(ImageHider, _super);
197 function ImageHider() {
198 var _this = _super.call(this) || this;
199 _this.listener_obj = {};
200 _this.retrieveStates();
201 _this.init();
202 _this.activate();
203 return _this;
205 //retrieve from memory the hidden images
206 //Images are stored in memory as f<ID_NUMBER>IMG and recalled using the storage_key
207 //Function makes a check to see if the hiding time limit for the thread has expired or not.
208 //Note: Must have the DOM itterate through before retrieval
209 ImageHider.prototype.retrieveStates = function () {
210 var _this = this;
211 var storage_position = 0;
212 var JSON_storage = {}; /*;any bypasses dot notation issues on objects*/
213 var storage_key;
214 var local_store_size = window.localStorage.length;
215 while (storage_position < local_store_size) {
216 storage_key = window.localStorage.key(storage_position);
217 JSON_storage[storage_key] = window.localStorage.getItem(storage_key);
218 storage_position++;
220 this.threads_to_hide = Generics.getJSONPropertiesByKeyName(JSON_storage, '[0-9]+IMG');
221 //aquire each time to check for changes
222 this.hide_expiration_time = parseInt(JSON_storage.Expiration_Time);
223 if (this.hide_expiration_time === null)
224 this.hide_expiration_time = Constants.DEFAULT_HIDE_EXPIRATION_TIME;
225 var md5_filters = JSON_storage.MD5_List_FSE;
226 if (md5_filters !== undefined && md5_filters !== null) {
227 this.md5_filters_arr = md5_filters.split('\n');
228 //remove trailing and starting slash
229 this.md5_filters_arr.forEach(function (md5, index) {
230 md5 = md5.trim();
231 _this.md5_filters_arr[index] = md5.substring(1, md5.length - 1);
235 ImageHider.prototype.storeStates = function () {
236 var item_pairs = [];
237 for (var _i = 0; _i < arguments.length; _i++) {
238 item_pairs[_i] = arguments[_i];
240 window.localStorage.setItem(item_pairs[0], item_pairs[1]);
242 ImageHider.prototype.init = function () {
243 this.hotkeyListeners();
245 //hide image onclick listener.
246 //Method 404's a given image. This 404'ing allows image dissabling to be toggled on and off.
247 //Post number associated with the image is stored in local storage.
248 ImageHider.prototype.hideOnClick = function (event) {
249 var is_hidden = event.target.src.substring(21, 29) == ",iVBORw0";
250 var hide_group_id;
251 if (((this.listener_obj[17] || this.listener_obj[91]) && this.listener_obj[16]) && !is_hidden) {
252 event.preventDefault();
253 event.stopPropagation();
254 hide_group_id = event.target.getAttribute('hide-grouping');
255 this.storeStates(hide_group_id, "" + Date.now());
256 [].slice.call(document.querySelectorAll('img[hide-grouping="' + hide_group_id + '"]')).forEach(function (image_node) {
257 image_node.setAttribute('hidden-src', image_node.src);
258 image_node.src = Constants.BLANK_PNG;
261 else if ((this.listener_obj[17] || this.listener_obj[91]) && this.listener_obj[16]) {
262 event.preventDefault();
263 event.stopPropagation();
264 hide_group_id = event.target.getAttribute('hide-grouping');
265 window.localStorage.removeItem(hide_group_id);
266 event.target.src = event.target.getAttribute('hidden-src');
267 [].slice.call(document.querySelectorAll('img[hide-grouping="' + hide_group_id + '"]')).forEach(function (image_node) {
268 image_node.src = image_node.getAttribute('hidden-src');
271 this.retrieveStates();
272 return true;
274 //hotkeys for ctrl[17] and shift[16]
275 ImageHider.prototype.hotkeyListeners = function () {
276 var _this = this;
277 window.addEventListener("keydown", function (e) {
278 _this.listener_obj[e.keyCode] = true;
279 }, { passive: false, capture: false, once: false });
280 window.addEventListener("keyup", function (e) {
281 _this.listener_obj[e.keyCode] = false;
282 }, { passive: false, capture: false, once: false });
284 ImageHider.prototype.decideAction = function (node) {
285 //tagname is always upper in HTML, in xml it's displayed as written.
286 if (node.tagName === 'IMG' || node.tagName === 'VIDEO') {
287 if (node.id === "ihover") {
288 this.hideHoverImageNode(node);
289 return;
291 if (node.getAttribute('data-md5') !== null) {
292 this.hideImageNode(node);
296 //Activate
297 ImageHider.prototype.activate = function () {
298 console.log("4F-FSE: ImageHider Active");
300 ImageHider.prototype.hideImageNode = function (image_node) {
301 var _this = this;
302 var sister_node = image_node.parentNode.parentNode.parentNode.getElementsByClassName('catalog-thumb')[0]; // the catalog sister to index
303 var sister_node_non_exist = false;
304 if (sister_node === undefined) {
305 sister_node_non_exist = true;
307 var image_node_already_run = false;
308 if (/\d+IMG/.test(image_node.getAttribute('hide-grouping'))) {
309 image_node_already_run = true;
310 if (!sister_node_non_exist) {
311 if (/\d+IMG/.test(sister_node.getAttribute('hide-grouping'))) {
312 return;
316 if (!image_node_already_run)
317 image_node.setAttribute('hide-grouping', image_node.parentNode.parentNode.id.substring(1) + 'IMG');
318 if (!sister_node_non_exist)
319 sister_node.setAttribute('hide-grouping', image_node.parentNode.parentNode.id.substring(1) + 'IMG');
320 if (!image_node_already_run)
321 image_node.addEventListener('click', function (evt) { return _this.hideOnClick(evt); });
322 if (!sister_node_non_exist)
323 sister_node.addEventListener('click', function (evt) { return _this.hideOnClick(evt); });
324 var threadstore_len = this.threads_to_hide.length;
325 var node_group_id = image_node.getAttribute('hide-grouping');
326 for (var thread = 0; thread < threadstore_len; thread++) {
327 if (node_group_id == this.threads_to_hide[thread]) {
328 if (!image_node_already_run) {
329 image_node.setAttribute('hidden-src', image_node.src);
330 image_node.src = Constants.BLANK_PNG;
332 if (!sister_node_non_exist) {
333 sister_node.setAttribute('hidden-src', sister_node.src);
334 sister_node.src = Constants.BLANK_PNG;
336 return;
339 //index node holds the MD5
340 var node_md5 = image_node.getAttribute('data-md5');
341 if (this.md5_filters_arr !== undefined) {
342 var md5_filters_arr_len = this.md5_filters_arr.length;
343 for (var md5 = 0; md5 < md5_filters_arr_len; md5++) {
344 if (node_md5 == this.md5_filters_arr[md5]) {
345 this.threads_to_hide.push();
346 if (!image_node_already_run) {
347 image_node.setAttribute('hidden-src', image_node.src);
348 image_node.src = Constants.BLANK_PNG;
350 if (!sister_node_non_exist) {
351 sister_node.setAttribute('hidden-src', sister_node.src);
352 sister_node.src = Constants.BLANK_PNG;
354 return;
359 ImageHider.prototype.hideHoverImageNode = function (image_node) {
360 var unprocessed_id = image_node.getAttribute('data-full-i-d');
361 var proccessed_id = unprocessed_id.substring(unprocessed_id.indexOf('.') + 1);
362 var image_node_id = proccessed_id + 'IMG';
363 if (image_node === undefined)
364 return;
365 for (var thread = 0, threadstore_len = this.threads_to_hide.length; thread < threadstore_len; thread++) {
366 if (image_node_id == this.threads_to_hide[thread]) {
367 image_node.removeAttribute('src');
368 return;
371 //thread node holds the MD5
372 var node_md5;
373 // if(is_embeded_post) node_md5 = image_node.getAttribute('data-md5');
374 /*else */ node_md5 = document.getElementById('f' + proccessed_id).getElementsByTagName('IMG')[0].getAttribute('data-md5');
375 if (this.md5_filters_arr !== undefined) {
376 for (var md5 = 0, md5_filters_arr_len = this.md5_filters_arr.length; md5 < md5_filters_arr_len; md5++) {
377 if (node_md5 == this.md5_filters_arr[md5]) {
378 image_node.removeAttribute('src');
379 return;
384 return ImageHider;
385 }(FeatureInterface));
386 var TextReplacer = /** @class */ (function (_super) {
387 __extends(TextReplacer, _super);
388 function TextReplacer() {
389 var _this = _super.call(this) || this;
390 _this.text_filters = []; //object
391 _this.filtered_threads = [];
392 _this.retrieveStates();
393 _this.init();
394 _this.activate();
395 return _this;
397 TextReplacer.prototype.init = function () {
398 this.filtered_threads = [];
401 TextReplacer.prototype.activate = function () { console.log("4F-FSE: TextReplacer Active"); };
402 TextReplacer.prototype.decideAction = function (node) {
403 if (node.tagName == "BLOCKQUOTE") {
404 if (node.className == "postMessage") {
405 var blockquote_id = node.id;
406 var already_filtered = false;
407 this.filtered_threads.forEach(function (thread_id) {
408 if (thread_id == blockquote_id) {
409 already_filtered = true;
410 return;
414 else
415 return;
416 if (!already_filtered && this.text_filters.length !== 0) {
417 var itterator = document.createNodeIterator(node, NodeFilter.SHOW_TEXT);
418 var localNode;
419 while ((localNode = itterator.nextNode())) {
420 for (var filter = 0; filter < this.number_of_filters; filter++) {
421 if (this.text_filters[filter].Active === "true") {
422 var last_slash_index = this.text_filters[filter].Regex.lastIndexOf("/");
423 var filter_text = this.text_filters[filter].Regex.substring(1, last_slash_index);
424 var flag = this.text_filters[filter].Regex.substring(last_slash_index + 1);
425 var regex = new RegExp(filter_text, flag);
426 var node_text = localNode.textContent;
427 if (regex.test(node_text)) {
428 localNode.textContent = node_text.replace(regex, this.text_filters[filter].Replacement);
429 this.filtered_threads.push(blockquote_id);
437 TextReplacer.prototype.retrieveStates = function () {
438 var _this = this;
439 var storage_index = 0;
440 var JSON_storage = {};
441 var storage_key;
442 while (storage_index < window.localStorage.length) {
443 storage_key = window.localStorage.key(storage_index);
444 JSON_storage[storage_key] = window.localStorage.getItem(storage_key);
445 storage_index++;
447 this.number_of_filters = JSON_storage["filter_quantity"];
448 var filters = Generics.getJSONPropertiesByKeyName(JSON_storage, "[0-9]+FLT");
449 filters.sort();
450 filters.forEach(function (filter) {
451 _this.text_filters.push(TextReplacer.formatFilterSettings(JSON_storage[filter]));
454 //Splits the saved settings into components
455 TextReplacer.formatFilterSettings = function (input) {
456 var processed_input = (input.split('=')).map(function (x) { return decodeURIComponent(x); });
457 return { Active: processed_input[0], Regex: processed_input[1], Replacement: processed_input[2] };
459 TextReplacer.prototype.storeStates = function () { };
460 return TextReplacer;
461 }(FeatureInterface));
462 var DanbooruImageAdder = /** @class */ (function (_super) {
463 __extends(DanbooruImageAdder, _super);
464 function DanbooruImageAdder() {
465 var _this = _super.call(this) || this;
466 _this.timeout_functions = [];
467 _this.img_URL = "";
468 _this.post_number = 0;
469 _this.page_number = 0;
470 _this.json_page_numbers_used = [];
471 _this.previous_images = [];
472 _this.json_numbers_used = [];
473 _this.previous_page = 9001;
474 _this.subdomain_regex = new RegExp("http(|s)://");
475 _this.maximum_attempts = 20;
476 _this.time_max = 10;
477 _this.time = 10;
478 _this.init();
479 return _this;
481 DanbooruImageAdder.prototype.init = function () {
482 var _this = this;
483 this.time = this.time_max;
484 this.number_of_attempts = this.maximum_attempts;
485 document.addEventListener("QRDialogCreation", function (evt) {
486 _this.enhance4ChanX_HTML();
487 _this.enhanced4ChanXListeners();
490 DanbooruImageAdder.prototype.enhance4ChanX_HTML = function () {
491 var qr_window = document.getElementById("qr");
492 /*Should I auto open things for the user?*/
493 // var imagedump_opener:any = document.getElementById("dump-button");
494 // if(imagedump_opener !== null){imagedump_opener.click();}
495 // else{return;}
496 //image setting html elements.
497 var qr_image_adder_table = document.createElement("TABLE");
498 qr_image_adder_table.setAttribute("id", "qrImages");
499 qr_image_adder_table.setAttribute("style", "text-align:center");
500 qr_window.appendChild(qr_image_adder_table);
501 var options_row = document.createElement("TR");
502 options_row.setAttribute("ID", "or");
503 options_row.setAttribute("style", "margin:5px;");
504 qr_image_adder_table.appendChild(options_row);
505 var checkbox_safe = document.createElement("INPUT");
506 checkbox_safe.setAttribute("id", "safe");
507 checkbox_safe.setAttribute("type", "checkbox");
508 checkbox_safe.checked = true;
509 var checkbox_safe_text = document.createTextNode("Safe");
510 var checkbox_questionable = document.createElement("INPUT");
511 checkbox_questionable.setAttribute("id", "questionable");
512 checkbox_questionable.setAttribute("type", "checkbox");
513 var checkbox_questionable_text = document.createTextNode("Questionable");
514 var checkbox_explicit = document.createElement("INPUT");
515 checkbox_explicit.setAttribute("id", "explicit");
516 checkbox_explicit.setAttribute("type", "checkbox");
517 var checkbox_explicit_text = document.createTextNode("Explicit");
518 options_row.appendChild(checkbox_safe_text);
519 options_row.appendChild(checkbox_safe);
520 options_row.appendChild(checkbox_questionable_text);
521 options_row.appendChild(checkbox_questionable);
522 options_row.appendChild(checkbox_explicit_text);
523 options_row.appendChild(checkbox_explicit);
524 var image_tagging_row = document.createElement("TR");
525 this.help_icon_container = document.createElement("A");
526 this.help_icon_container.href = "javascript:void(0)";
527 this.help_icon_container.title = "Click to View Help!";
528 var help_icon = document.createElement("IMG");
529 help_icon.setAttribute("class", "help_icon");
530 help_icon.src = Constants.HELP_ICON_SOURCE;
531 this.help_icon_container.appendChild(help_icon);
532 image_tagging_row.appendChild(this.help_icon_container);
533 var tooltip_div = document.createElement("DIV");
534 tooltip_div.innerHTML = "Insert Tags to search from danbooru in the text box to the side.<br/>The URL for the image will be bellow. Some browsers such as chrome allow you to select this text<br/>Do Not Use \"order:\" tags<br/>Do Not Use \"rating:\" tags<br/>For more speed uncheck all boxes!<hr/>Submit bugs to <a href='https://github.com/ECHibiki/4chan-UserScripts'>my Github</a>";
535 (tooltip_div).setAttribute("class", "tooltip-4F");
536 (tooltip_div).setAttribute("id", "tooltipIA");
537 qr_window.appendChild(tooltip_div);
538 var second_row_nodes = [
539 document.createTextNode("Tags: "),
540 document.createElement("INPUT"),
541 document.createElement("INPUT"),
542 document.createElement("A"),
543 document.createElement("INPUT"),
545 second_row_nodes.forEach(function (node) {
546 image_tagging_row.appendChild(node);
548 qr_image_adder_table.appendChild(image_tagging_row);
549 var auto_complete_row = document.createElement("TR");
550 auto_complete_row.setAttribute("ID", "auto-complete-row");
551 auto_complete_row.setAttribute("style", "margin:5px;");
552 qr_image_adder_table.appendChild(auto_complete_row);
553 second_row_nodes[1].setAttribute("ID", "tag_input");
554 var option_text_size = 18;
555 second_row_nodes[1].setAttribute("style", "width:44.9%;" + "font-size:" + option_text_size + "px");
556 second_row_nodes[3].setAttribute("ID", "timer");
557 second_row_nodes[3].setAttribute("style", "width:20%;margin:0 5px");
558 second_row_nodes[4].setAttribute("ID", "urlContainer");
559 second_row_nodes[4].setAttribute("style", "width:75%;margin:5px -25px");
560 second_row_nodes[4].setAttribute("disabled", "");
561 second_row_nodes[2].setAttribute("ID", "imageButton");
562 second_row_nodes[2].setAttribute("type", "button");
563 second_row_nodes[2].setAttribute("value", "Set Image");
564 //textarea expansion;
565 qr_window.getElementsByTagName("TEXTAREA")[0].style.width = "110%";
566 qr_window.appendChild(document.createElement("hr"));
568 DanbooruImageAdder.prototype.enhanced4ChanXListeners = function () {
569 var _this = this;
570 this.highQualityImages();
571 document.getElementById("qr-filerm").addEventListener("click", function (evt) { return _this.clearImage(); });
572 var qr_reference = document.getElementById("qr");
573 var tooltip_div = document.getElementById("tooltipIA");
574 this.help_icon_container.addEventListener("click", function (evt) {
575 if (_this.tool_tip_visible)
576 tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;");
577 else
578 tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:block;position:absolute;"
579 + "left:" + (evt.clientX - qr_reference.getBoundingClientRect().x) +
580 "px;top:" + (evt.clientY - qr_reference.getBoundingClientRect().y) + "px;");
581 _this.tool_tip_visible = !_this.tool_tip_visible;
583 var tag_input = document.getElementById("tag_input");
584 tag_input.addEventListener("input", function (evt) {
585 _this.setTagInterface(tag_input, document.getElementById("auto-complete-row"));
587 document.getElementById("imageButton").addEventListener("click", function (evt) { return _this.activate(); });
589 DanbooruImageAdder.prototype.highQualityImages = function () {
590 var _this = this;
591 var imagedump_file_list = document.getElementById("dump-list");
592 //used for setting and unsetting high resolution thumbs for dump list.
593 var dumplist_image = "";
594 var previous_dumplist_image = "";
595 var observer = new MutationObserver(function (mutate) {
596 dumplist_image = imagedump_file_list.firstChild.style.backgroundImage;
597 if (dumplist_image !== previous_dumplist_image && _this.img_URL !== "") {
598 imagedump_file_list.firstChild.style.backgroundImage = "url(" + _this.img_URL + ")";
599 previous_dumplist_image = imagedump_file_list.firstChild.style.backgroundImage;
601 else if (_this.img_URL == "") { }
603 observer.observe(imagedump_file_list, { attributes: true, subtree: true, childList: true, characterData: true });
605 DanbooruImageAdder.prototype.activate = function () {
606 var _this = this;
607 //on setimage click clear flags, timers and start another search
608 this.json_page_numbers_used = Array();
609 this.previous_page = 9001;
610 //reset a failed_to_find_required_tags boolean
611 this.primed_for_fail = false;
612 for (var i = 0; i < this.timeout_functions.length; i++) {
613 clearInterval(this.timeout_functions[i]);
615 this.tag_incorrect_state = false;
616 this.timeout = false;
617 //freeze interface to prevent mid opperation changes
618 document.getElementById("tag_input").setAttribute("disabled", "1");
619 document.getElementById("imageButton").setAttribute("disabled", "1");
620 this.time = this.time_max;
621 this.timeout_functions.push(setInterval(function () { return _this.counterFunction(); }, 1000));
622 //start the search
623 this.setImage(this);
625 //remove the high quallity image from the dump list
626 DanbooruImageAdder.prototype.clearImage = function () {
627 var imagedump_file_list = document.getElementById("dump-list");
628 imagedump_file_list.firstChild.style.backgroundImage = "url()"; //trigger mutation event
629 this.img_URL = ""; //get mutation to set to dead
631 DanbooruImageAdder.prototype.setTagInterface = function (tag_input_node, auto_complete_row) {
632 var tags = tag_input_node.value;
633 if (this.old_tags_before_change !== tags) {
634 this.previous_images = [];
635 var tag_carat_position = tag_input_node.selectionStart - 1;
636 var closest_tag = (function () {
637 var current_chararcter = tags.charAt(tag_carat_position);
638 var i = 0;
639 var right_most = tag_carat_position;
640 while (current_chararcter != " " && current_chararcter != "" && current_chararcter !== undefined) {
641 i++;
642 current_chararcter = tags.charAt(tag_carat_position + i);
643 if (current_chararcter != " " && current_chararcter != "")
644 right_most = tag_carat_position + i;
646 right_most += 1;
647 current_chararcter = tags.charAt(tag_carat_position);
648 i = 0;
649 var leftMost = tag_carat_position;
650 while (current_chararcter != " " && current_chararcter != "" && current_chararcter !== undefined) {
651 i++;
652 current_chararcter = tags.charAt(tag_carat_position - i);
653 if (current_chararcter != " " && current_chararcter != "")
654 leftMost = tag_carat_position - i;
656 return tags.substring(leftMost, right_most);
657 })();
658 var xhr = new GM_xmlhttpRequest(({
659 method: "GET",
660 url: "https://danbooru.donmai.us/tags.json?search[name_matches]=" + closest_tag + "*&search[order]=count",
661 responseType: "json",
662 onload: function (data) {
663 data = data.response;
664 var tagArray = tags.split(" ");
665 while (auto_complete_row.hasChildNodes()) {
666 auto_complete_row.removeChild(auto_complete_row.lastChild);
668 var qr_width = document.getElementById("qr").offsetWidth;
669 var tag_table = document.createElement("TABLE");
670 tag_table.setAttribute("style", "border:1px solid black;margin-top:5px");
671 var tag_row = document.createElement("TR");
672 for (var i = 0; i < 5; i++) {
673 var a = document.createElement("A");
674 var tagText = data["" + i];
675 if (tagText == "" || tagText === undefined)
676 break;
677 tagText = tagText["name"];
678 var a_txt = document.createTextNode(data[i]["name"]);
679 var tag_data = document.createElement("TD");
680 tag_data.setAttribute("style", "padding:5px;font-size:15px;font-weight:bold;border:1px solid black;");
681 a.appendChild(a_txt);
682 tag_data.appendChild(a);
683 tag_row.appendChild(tag_data);
684 tag_table.appendChild(tag_row);
685 auto_complete_row.appendChild(tag_table);
686 if (tag_table.offsetWidth > qr_width - 10) {
687 tag_row.removeChild(tag_data);
688 tag_table = document.createElement("TABLE");
689 tag_row = document.createElement("TR");
690 tag_row.appendChild(tag_data);
691 tag_table.appendChild(tag_row);
692 tag_table.setAttribute("style", "border:1px solid black;");
693 auto_complete_row.appendChild(tag_table);
695 a.addEventListener("click", function (evt) {
696 tagArray[tagArray.indexOf(closest_tag)] = this.textContent;
697 document.getElementById("tag_input").value = tagArray.join(" ");
701 }));
703 this.old_tags_before_change = tag_input_node.value;
705 //a series of calls on other functions that leads to the image being searched for
706 DanbooruImageAdder.prototype.setImage = function (this_) {
707 //Set image tags.
708 var tags = document.getElementById("tag_input").value.trim();
709 if (tags.indexOf(":") > -1) {
710 Generics.alert4ChanX("Character ':' not used for functional purpose", "warning");
712 var tags_arr = tags.split(" ");
713 var xhr_image_load = new GM_xmlhttpRequest(({
714 method: "GET",
715 //returns a list of all tags and their properties
716 url: "https://danbooru.donmai.us/tags.json?search[name]=" + tags_arr.join() + "&search[order]=count",
717 responseType: "json",
718 onload: function (data) {
719 this_.json_tag = this_.verifyTags(data, tags_arr);
720 if (this_.failed_to_find_required_tags_state)
721 return;
722 //set the end
723 var end_URL = this_.ratingURL(this_.json_tag);
724 var URL = this_.setPostAndPage(end_URL);
725 this_.send_URL = URL;
726 //final check, sends final request after function or calls this function again
727 Generics.getJSON(URL, function (err, data, tags, _this_) { return this_.checkPageFromDanbooru(err, data, tags, _this_); }, tags_arr, this_);
729 }));
731 //make 4chanX alerts on issues, and account for error cases.
732 DanbooruImageAdder.prototype.verifyTags = function (data, tags) {
733 data = data.response;
734 this.json_tag = data;
735 this.failed_to_find_required_tags_state = false;
736 //if data has a null or undefined case, return an error
737 if (data.length == 0) {
738 Generics.alert4ChanX("All tags incorrect", "error", 10);
739 this.failed_to_find_required_tags_state = true;
740 document.getElementById("timer").textContent = "";
741 document.getElementById("tag_input").removeAttribute("disabled");
742 document.getElementById("imageButton").removeAttribute("disabled");
743 return this.json_tag;
745 else if (data.length != tags.length && !this.tag_incorrect_state) {
746 this.tag_incorrect_state = true;
747 if (document.getElementById("tag_input").value.trim() == "")
748 Generics.alert4ChanX("No Tags", "info", 2);
749 else
750 Generics.alert4ChanX("One Tag Incorrect", "warning");
752 //tag size. Smallest tag is placed at bottom of JSON
753 this.smallest_tag_size = parseInt(data[data.length - 1]["post_count"]);
754 return this.json_tag;
756 //evaluate the rating restrictions to account for danbooru's tagging limitations
757 DanbooruImageAdder.prototype.ratingURL = function (tags) {
758 var URL = "";
759 //evaluate the 3! possible permutations
760 if (document.getElementById("safe").checked) {
761 if (document.getElementById("questionable").checked) {
762 if (document.getElementById("explicit").checked) {
763 if (tags.length > 1)
764 URL = "&utf8=%E2%9C%93&tags=" + tags[tags.length - 2]["name"] + "+" + tags[tags.length - 1]["name"];
765 else
766 URL = "&utf8=%E2%9C%93&tags=" + tags[tags.length - 1]["name"];
768 else {
769 URL = "&utf8=%E2%9C%93&tags=" + "-rating%3Aexplicit" + "+" + tags[tags.length - 1]["name"];
772 else if (document.getElementById("explicit").checked) {
773 URL = "&utf8=%E2%9C%93&tags=" + "-rating%3Aquestionable" + "+" + tags[tags.length - 1]["name"];
775 else {
776 URL = "&utf8=%E2%9C%93&tags=" + "rating%3Asafe" + "+" + tags[tags.length - 1]["name"];
779 else if (document.getElementById("questionable").checked) {
780 if (document.getElementById("explicit").checked) {
781 URL = "&utf8=%E2%9C%93&tags=" + "-rating%3Asafe" + "+" + tags[tags.length - 1]["name"];
783 else {
784 URL = "&utf8=%E2%9C%93&tags=" + "rating%3Aquestionable" + "+" + tags[tags.length - 1]["name"];
787 else if (document.getElementById("explicit").checked) {
788 URL = "&utf8=%E2%9C%93&tags=" + "rating%3Aexplicit" + "+" + tags[tags.length - 1]["name"];
790 else {
791 if (tags.length > 1)
792 URL = "&utf8=%E2%9C%93&tags=" + tags[tags.length - 2]["name"] + "+" + tags[tags.length - 1]["name"];
793 else
794 URL = "&utf8=%E2%9C%93&tags=" + tags[tags.length - 1]["name"];
796 return URL;
798 //set where to search
799 DanbooruImageAdder.prototype.setPostAndPage = function (end_URL) {
800 this.post_number = 0;
801 //page
802 if (this.top_page != this.top_page_max)
803 this.smallest_tag_size = this.top_page * 20;
804 if (this.smallest_tag_size == 0)
805 this.smallest_tag_size = 100;
806 var escape_cond = true;
807 this.page_number = ((Math.floor(Math.random() * 10000)) % Math.ceil(this.smallest_tag_size / 20)) % 1000; //1000 is max page search limit
808 if (this.page_number == 0 && this.previous_page == 0) {
809 this.primed_for_fail = true;
811 this.json_numbers_used.push(this.page_number);
812 this.previous_page = this.page_number;
813 var URL = "https://danbooru.donmai.us/posts.json?page=" + this.page_number + end_URL;
814 return URL;
816 //check if valid url location
817 DanbooruImageAdder.prototype.checkPageFromDanbooru = function (err, data, tags, this_arr) {
818 if (err != null) {
819 console.log('Something went wrong: ' + err);
820 Generics.alert4ChanX("Danbooru Server Did Not Perform request -- Error: " + err, "error");
821 document.getElementById("timer").textContent = "";
822 document.getElementById("tag_input").removeAttribute("disabled");
823 document.getElementById("imageButton").removeAttribute("disabled");
825 else {
826 do {
827 var duplicate = false;
828 //check for repeating images found
829 this_arr.previous_images.forEach(function (item) {
830 if (item[0] == this_arr.page_number && item[1] == this_arr.post_number) {
831 duplicate = true;
832 this_arr.post_number++;
835 } while (duplicate);
836 this_arr.number_of_attempts--;
837 if (this_arr.primed_for_fail) {
838 Generics.alert4ChanX("No Results: All found for tags \"" + document.getElementById("tag_input").value + "\"", "error");
839 this_arr.reset_search_timer_fields();
840 return;
842 //Out of items on current json page so go to next page
843 else if ((data.length < this_arr.post_number + 1) && this_arr.number_of_attempts > 0) {
844 if (this_arr.top_page > this_arr.page_number) {
845 this_arr.top_page = this_arr.page_number + this_arr.post_number / 20;
847 //posts
848 this_arr.post_number = 0;
849 document.getElementById("timer").textContent = this_arr.number_of_attempts + "|" + this_arr.time;
850 this_arr.setImage(this_arr);
852 else if (this_arr.number_of_attempts > 0) {
853 //ALL PARAMETERS WILL BE RESET INSIDE JSON
854 document.getElementById("timer").textContent = this_arr.number_of_attempts + "|" + this_arr.time;
855 Generics.getJSON(this_arr.send_URL, function (err, data, tags, _this_arr) { return this_arr.setImageFromDanbooru(err, data, tags, _this_arr); }, tags, this_arr);
857 else {
858 Generics.alert4ChanX("Not found", "error");
859 this_arr.reset_search_timer_fields();
860 return;
864 DanbooruImageAdder.prototype.reset_search_timer_fields = function () {
865 this.top_page = this.top_page_max;
866 this.number_of_attempts = this.maximum_attempts;
867 document.getElementById("timer").textContent = "";
868 document.getElementById("tag_input").removeAttribute("disabled");
869 document.getElementById("imageButton").removeAttribute("disabled");
871 //finally draw from the JSON page to generate and place the post into the 4chanX dumplist
872 DanbooruImageAdder.prototype.setImageFromDanbooru = function (err, data, tags, this_arr) {
873 if (err != null) {
874 console.log('Something went wrong: ' + err);
875 Generics.alert4ChanX("Danbooru Server Did Not Perform request -- Error: " + err, "error");
876 document.getElementById("timer").textContent = "";
877 document.getElementById("tag_input").removeAttribute("disabled");
878 document.getElementById("imageButton").removeAttribute("disabled");
880 else {
881 this_arr.json_page = data;
882 var image_found = false;
883 for (this_arr.post_number = this_arr.post_number; this_arr.post_number < 20; this_arr.post_number++) {
884 if (this_arr.timeout) {
885 //Case1: Took too long to scan the page.
886 //Result: Kills search
887 Generics.alert4ChanX("timeout after " + this_arr.time + " seconds", "error");
888 for (var i = 0; i < this_arr.timeout_functions.length; i++) {
889 clearInterval(this_arr.timeout_functions[i]);
891 this_arr.reset_search_timer_fields();
892 return;
894 else if (this_arr.json_page["" + this_arr.post_number] == undefined) {
895 //Case2: reaches an undefined page.
896 //Result: Switches to a new page
897 this_arr.top_page = this_arr.page_number;
898 this_arr.setImage(this_arr);
899 return;
901 //set the page to search
902 var end_URL = this_arr.json_page["" + this_arr.post_number].file_url;
903 var URL = "https://danbooru.donmai.us" + end_URL;
904 if (this_arr.subdomain_regex.test(end_URL))
905 URL = end_URL;
906 //place url in visible box
907 this_arr.urlContainterFunction(URL);
911 :{id: 3038118, created_at: "2018-03-02T15:27:56.469-05:00", uploader_id: 49091, score: 6,…}
912 approver_id:null
913 bit_flags:0
914 children_ids:null
915 created_at:"2018-03-02T15:27:56.469-05:00"
916 down_score:0
917 fav_count:10
918 fav_string:"fav:553974 fav:467363 fav:455311 fav:490034 fav:505064 fav:482030 fav:351935 fav:66907 fav:467355 fav:519151"
919 file_ext:"jpg"
920 file_size:30492
921 file_url:"/data/__miyuki_kantai_collection_drawn_by_kumadano__7a12a196cc1aa9f794bca81a2a14bb81.jpg"
922 has_active_children:false
923 has_children:false
924 has_large:false
925 has_visible_children:false
926 id:3038118
927 image_height:800
928 image_width:450
929 is_banned:false
930 is_deleted:false
931 is_flagged:false
932 is_note_locked:false
933 is_pending:false
934 is_rating_locked:false
935 is_status_locked:false
936 large_file_url:"/data/__miyuki_kantai_collection_drawn_by_kumadano__7a12a196cc1aa9f794bca81a2a14bb81.jpg"
937 last_comment_bumped_at:null
938 last_commented_at:null
939 last_noted_at:null
940 md5:"7a12a196cc1aa9f794bca81a2a14bb81"
941 parent_id:null
942 pixiv_id:null
943 pool_string:""
944 preview_file_url:"/data/preview/7a12a196cc1aa9f794bca81a2a14bb81.jpg"
945 rating:"s"
946 score:6
947 source:"https://twitter.com/kumadano/status/969629578137251840"
948 tag_count:28
949 tag_count_artist:1
950 tag_count_character:1
951 tag_count_copyright:1
952 tag_count_general:24
953 tag_count_meta:1
954 tag_string:"1girl black_legwear blue_sailor_collar blue_skirt brown_eyes brown_hair commentary_request full_body grin kantai_collection kumadano miyuki_(kantai_collection) pleated_skirt ribbon sailor_collar school_uniform serafuku short_hair short_sleeves simple_background skirt smile socks solo standing wavy_hair white_background wrists_extended"
955 tag_string_artist:"kumadano"
956 tag_string_character:"miyuki_(kantai_collection)"
957 tag_string_copyright:"kantai_collection"
958 tag_string_general:"1girl black_legwear blue_sailor_collar blue_skirt brown_eyes brown_hair full_body grin pleated_skirt ribbon sailor_collar school_uniform serafuku short_hair short_sleeves simple_background skirt smile socks solo standing wavy_hair white_background wrists_extended"
959 tag_string_meta:"commentary_request"
960 up_score:6
961 updated_at:"2018-03-03T09:09:32.357-05:00"
962 uploader_id:49091
963 uploader_name:"---"
966 var failed_to_find_required_tags = false;
967 if (end_URL === undefined ||
968 end_URL.indexOf(".mp4") > -1 || end_URL.indexOf(".webm") > -1 || end_URL.indexOf(".swf") > -1 || end_URL.indexOf(".zip") > -1) {
969 continue;
971 else {
972 tags.forEach(function (tag) {
973 //if tag contains an order then whatever
974 if (tag.indexOf("order:") > -1) { }
975 //if it contains a raiting, check the rating character at the seventh index
976 else if (tag.indexOf("rating:") > -1) {
977 if (tag.charAt(7) !== this_arr.json_page["" + this_arr.post_number]["rating"]) {
978 failed_to_find_required_tags = true;
981 //otherwise check if the tagstring contains the tags
982 else if (this_arr.json_page["" + this_arr.post_number]["tag_string"].indexOf(tag) == -1) {
983 failed_to_find_required_tags = true;
987 if (failed_to_find_required_tags) {
988 continue;
990 else {
991 if (this_arr.json_page["" + this_arr.post_number].file_size >= 4000000) {
992 var end_URL = this_arr.json_page["" + this_arr.post_number].large_file_url;
993 var URL = "https://danbooru.donmai.us" + end_URL;
994 if (this_arr.subdomain_regex.test(end_URL))
995 URL = end_URL;
997 document.getElementById("timer").textContent = "...";
998 this_arr.img_URL = URL;
999 var xhr = new GM_xmlhttpRequest(({
1000 method: "GET",
1001 url: URL,
1002 responseType: "arraybuffer",
1003 onload: function (response) {
1004 //is it a non existent image?
1005 if (response.response.byteLength <= 387) {
1006 Generics.alert4ChanX("Image Does Not Exist on Danbooru(404 error)\nDanbooru seems to be updating image servers???", "error");
1008 var blob;
1009 if (end_URL.indexOf(".jpg") > -1)
1010 blob = new Blob([response.response], { type: "image/jpeg" });
1011 else if (end_URL.indexOf(".png") > -1)
1012 blob = new Blob([response.response], { type: "image/png" });
1013 else if (end_URL.indexOf(".gif") > -1)
1014 blob = new Blob([response.response], { type: "image/gif" });
1015 var counter = document.getElementById("timer");
1016 while (counter.hasChildNodes())
1017 counter.removeChild(counter.lastChild);
1018 this_arr.reset_search_timer_fields();
1019 this_arr.time = this_arr.time_max;
1020 var name = end_URL.replace(/(data|cached)/g, "");
1021 name = name.replace(/\//g, "");
1022 //SEND RESULTING RESPONSE TO 4CHANX FILES === QRSetFile
1023 var detail = { file: blob, name: name };
1024 if (typeof cloneInto === 'function') {
1025 detail = cloneInto(detail, document.defaultView);
1027 document.dispatchEvent(new CustomEvent('QRSetFile', { bubbles: true, detail: detail }));
1029 }));
1030 //end function;
1031 image_found = true;
1032 //SET PAGE&POST AS FOUND
1033 this_arr.previous_images.push([this_arr.page_number, this_arr.post_number]);
1034 this_arr.post_number = 9001;
1037 if (!image_found) {
1038 // this_arr.top_page = this_arr.page_number;
1039 this_arr.setImage(this_arr);
1043 DanbooruImageAdder.prototype.urlContainterFunction = function (url) {
1044 var url_box = document.getElementById("urlContainer");
1045 url_box.value = url;
1047 DanbooruImageAdder.prototype.counterFunction = function () {
1048 if (!this.timeout) {
1049 this.time--;
1050 if (this.time < 0) {
1051 this.timeout = true;
1052 this.time = this.time_max;
1056 DanbooruImageAdder.prototype.decideAction = function (node) { };
1057 DanbooruImageAdder.prototype.retrieveStates = function () { };
1058 DanbooruImageAdder.prototype.storeStates = function () {
1059 var items = [];
1060 for (var _i = 0; _i < arguments.length; _i++) {
1061 items[_i] = arguments[_i];
1064 return DanbooruImageAdder;
1065 }(FeatureInterface));
1066 var ThreadRebuilder = /** @class */ (function (_super) {
1067 __extends(ThreadRebuilder, _super);
1068 function ThreadRebuilder() {
1069 var _this = _super.call(this) || this;
1070 _this.board = "qa";
1071 _this.thread_data = [['Comment'], ['Image URLs'], ['Image Names'], ['Post No.']];
1072 _this.semaphore = 1;
1073 _this.semaphore_posts = 1;
1074 _this.use_offsite_archive = false;
1075 _this.window_displayed = false;
1076 _this.in_sequence = false;
1077 _this.tool_top_visible = false;
1078 _this.thread_data_length = 0;
1079 _this.posts_created = 0;
1080 _this.checked = false;
1081 _this.init();
1082 return _this;
1084 ThreadRebuilder.prototype.init = function () {
1085 var pathname = window.location.pathname.substring(1);
1086 this.board = pathname.substring(0, pathname.indexOf("/"));
1087 this.activate();
1089 ThreadRebuilder.prototype.retrieveStates = function () {
1090 this.use_offsite_archive = localStorage.getItem("ArchiveType") == "0" ? true : false;
1092 ThreadRebuilder.prototype.storeStates = function () {
1093 var items = [];
1094 for (var _i = 0; _i < arguments.length; _i++) {
1095 items[_i] = arguments[_i];
1098 ThreadRebuilder.prototype.activate = function () {
1099 var _this = this;
1100 document.addEventListener("QRDialogCreation", function (e) { return _this.enhance4ChanX(); });
1101 document.addEventListener('QRPostSuccessful', function (e) {
1102 if (_this.in_sequence) {
1103 document.getElementById("dump-list").childNodes[1].click();
1104 _this.setPropperLinking(document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value);
1106 }, false);
1108 ThreadRebuilder.prototype.decideAction = function (node) { };
1109 ThreadRebuilder.prototype.enhance4ChanX = function () {
1110 var _this = this;
1111 var qr_window = document.getElementById("qr");
1112 if (document.getElementById("qrRebuilder") !== null)
1113 qr_window.removeChild(document.getElementById("qrRebuilder"));
1114 var thread_rebuilder_table = document.createElement("TABLE");
1115 thread_rebuilder_table.setAttribute("id", "qrRebuilder");
1116 thread_rebuilder_table.setAttribute("style", "text-align:center");
1117 qr_window.appendChild(thread_rebuilder_table);
1118 var thread_row = document.createElement("TR");
1119 var option_text_size = 18;
1120 var help_icon_container = document.createElement("A");
1121 help_icon_container.href = "javascript:void(0)";
1122 help_icon_container.title = "Click to View Help!";
1123 var help_icon = document.createElement("IMG");
1124 help_icon.setAttribute("style", "height:" + option_text_size * 1.25 + "px;margin:-4px 10px");
1125 help_icon.src = Constants.HELP_ICON_SOURCE;
1126 help_icon_container.appendChild(help_icon);
1127 thread_row.appendChild(help_icon_container);
1128 var tooltip_div = document.createElement("DIV");
1129 tooltip_div.innerHTML = "Insert the thread number of the post to rebuild<br/>Must be in either the 4chan archives or archived.moe<hr/>Submit bugs to <a href='https://github.com/ECHibiki/4chan-UserScripts'>my Github</a>";
1130 tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;");
1131 help_icon_container.addEventListener("click", function (evt) {
1132 if (_this.tool_top_visible)
1133 tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;");
1134 else
1135 tooltip_div.setAttribute("style", "z-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:block;position:absolute;"
1136 + "left:" + (evt.clientX - qr_window.getBoundingClientRect().x) +
1137 "px;top:" + (evt.clientY - qr_window.getBoundingClientRect().y) + "px;");
1138 _this.tool_top_visible = !_this.tool_top_visible;
1140 qr_window.appendChild(tooltip_div);
1141 var second_row_nodes = [
1142 document.createTextNode("Thread: "),
1143 document.createElement("INPUT"),
1144 document.createElement("INPUT"),
1146 second_row_nodes.forEach(function (node) {
1147 thread_row.appendChild(node);
1149 thread_rebuilder_table.appendChild(thread_row);
1150 second_row_nodes[1].setAttribute("ID", "threadInput");
1151 second_row_nodes[1].setAttribute("style", "width:35.0%");
1152 second_row_nodes[2].setAttribute("ID", "threadButton");
1153 second_row_nodes[2].setAttribute("type", "button");
1154 second_row_nodes[2].setAttribute("value", "Set Rebuild Queue");
1155 second_row_nodes[2].addEventListener("click", function () {
1156 _this.in_sequence = true;
1157 _this.killAll();
1158 _this.getThread(second_row_nodes[1].value);
1159 _this.postID = setInterval(function () { return _this.postRoutine(); }, 1000);
1160 if (_this.timeListen === undefined)
1161 _this.timeListen = setInterval(function () { return _this.timeListenerFunction(); }, 1000);
1163 qr_window.appendChild(document.createElement("hr"));
1166 ThreadRebuilder.prototype.postRoutine = function () {
1167 var _this = this;
1168 if (this.semaphore == 0) {
1169 this.semaphore++;
1170 this.thread_data_length = this.thread_data[0].length;
1171 this.fillID = setInterval(function () { return _this.fillRoutine(); }, 10);
1172 this.stopRoutine();
1176 ThreadRebuilder.prototype.stopRoutine = function () {
1177 clearInterval(this.postID);
1180 ThreadRebuilder.prototype.fillRoutine = function () {
1181 if (this.posts_created >= this.thread_data_length) {
1182 this.semaphore_posts = 0;
1183 this.stopFillRoutine();
1185 else if (this.semaphore_posts == 1) {
1186 this.semaphore_posts--;
1187 this.createPost(this.thread_data[0][this.posts_created], this.thread_data[1][this.posts_created], this.thread_data[2][this.posts_created]);
1188 this.posts_created++;
1192 ThreadRebuilder.prototype.stopFillRoutine = function () {
1193 clearInterval(this.fillID);
1195 ThreadRebuilder.prototype.setPropperLinking = function (text) {
1196 var _this = this;
1197 var search_regex = RegExp(">>\\d+", "g");
1198 var result;
1199 var index_old = -1;
1200 var link_arr = Array();
1201 while ((result = search_regex.exec(text)) != null) {
1202 var end_index = search_regex.lastIndex;
1203 var post_no = result.toString().replace(/>/g, "");
1204 link_arr.push([post_no, end_index]);
1206 //hunt down the text of what it linked to
1207 //Get the links inside of the origonal message to show text contents
1208 var responding_text = Array();
1209 if (this.use_offsite_archive)
1210 var URL = "https://www.archived.moe/_/api/chan/thread/?board=" + this.board + "&num=" + document.getElementById("threadInput").value;
1211 else
1212 var URL = "https://a.4cdn.org/" + this.board + "/thread/" + document.getElementById("threadInput").value + ".json";
1213 var xhr = new GM_xmlhttpRequest(({
1214 method: "GET",
1215 url: URL,
1216 responseType: "json",
1217 onload: function (data) {
1218 if (_this.use_offsite_archive)
1219 data = data.response["" + document.getElementById("threadInput").value]["posts"];
1220 else
1221 data = data.response["posts"];
1222 if (data == undefined) {
1223 alert("Invalid Thread ID: " + document.getElementById("threadInput").value + ". ");
1225 else {
1226 link_arr.forEach(function (link_item) {
1227 for (var data_entry = 0; data_entry < data.length; data_entry++) {
1228 if (parseInt(link_item[0]) == parseInt(data[data_entry]["no"])) {
1229 if (_this.use_offsite_archive && data[data_entry]["comment_processed"] !== undefined)
1230 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"]]);
1231 else if (data[data_entry]["com"] !== undefined)
1232 responding_text.push([[post_no, end_index], data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, ""), data[data_entry]["md5"]]);
1233 else
1234 responding_text.push([[post_no, end_index], undefined, data[data_entry]["md5"]]);
1235 break;
1239 var current_url = window.location.href;
1240 var hash_index = current_url.lastIndexOf("#") != -1 ? current_url.lastIndexOf("#") : window.location.href.length;
1241 var current_thread = window.location.href.substring(current_url.lastIndexOf("/") + 1, hash_index);
1242 var current_url = "https://a.4cdn.org/" + _this.board + "/thread/" + current_thread + ".json";
1243 //open current thread to hunt down the text found in links
1244 var xhr = new GM_xmlhttpRequest(({
1245 method: "GET",
1246 url: current_url,
1247 responseType: "json",
1248 onload: function (data) {
1249 data = data.response["posts"];
1250 if (data == undefined) {
1251 alert("Invalid Thread ID: " + document.getElementById("threadInput").value + ". ");
1253 else {
1254 responding_text.forEach(function (response_item) {
1255 for (var data_entry = 0; data_entry < data.length; data_entry++) {
1256 if (data[data_entry]["com"] !== undefined && (response_item[1] == data[data_entry]["com"].replace(/(&gt;&gt;|#p)\d+/g, "") || response_item[1] == null)
1257 && (response_item[2] == data[data_entry]["md5"] || response_item[2] == null)) {
1258 var start_index = response_item[0][0].legth - response_item[0][1];
1259 text = text.substring(0, start_index) + ">>" + data[data_entry]["no"] + text.substring(response_item[0][1]);
1260 break;
1262 else if (response_item[2] !== undefined && response_item[2] == data[data_entry]["md5"]) {
1263 var start_index = response_item[0][0].legth - response_item[0][1];
1264 text = text.substring(0, start_index) + ">>" + data[data_entry]["no"] + text.substring(response_item[0][1]);
1265 break;
1269 document.getElementById("qr").getElementsByTagName("TEXTAREA")[0].value = text;
1270 document.getElementById("add-post").click();
1271 _this.semaphore_posts++;
1274 }));
1277 }));
1280 //2) GET ARCHIVED THREAD
1281 ThreadRebuilder.prototype.getThread = function (threadNo) {
1282 var _this = this;
1283 this.thread_data = [[], [], [], []];
1284 if (this.use_offsite_archive)
1285 var URL = "https://www.archived.moe/_/api/chan/thread/?board=" + this.board + "&num=" + document.getElementById("threadInput").value;
1286 else
1287 var URL = "https://a.4cdn.org/" + this.board + "/thread/" + document.getElementById("threadInput").value + ".json";
1288 var xhr = new GM_xmlhttpRequest(({
1289 method: "GET",
1290 url: URL,
1291 responseType: "json",
1292 onload: function (data) {
1293 var starting_post = -1;
1294 if (_this.use_offsite_archive) {
1295 starting_post = 0;
1296 data = data.response["" + document.getElementById("threadInput").value];
1298 else {
1299 starting_post = 1;
1300 data = data.response;
1302 if (data == undefined) {
1303 alert("Invalid Thread ID: " + threadNo + ".\n4chan Archive ");
1305 else {
1306 if (_this.use_offsite_archive)
1307 data["posts"] = data.values(data["posts"]);
1308 var len = data["posts"].length;
1309 for (var post_number = starting_post; post_number < len; post_number++) {
1310 var comment = undefined;
1311 if (_this.use_offsite_archive)
1312 comment = data["posts"][post_number]["comment"];
1313 else
1314 comment = data["posts"][post_number]["com"];
1315 if (comment !== undefined && comment !== null)
1316 _this.thread_data[0].push(comment);
1317 else
1318 _this.thread_data[0].push("");
1319 var filename = undefined;
1320 if (_this.use_offsite_archive) {
1321 if (data["posts"][post_number]["media"] !== null)
1322 filename = "" + data["posts"][post_number]["media"]["media_filename"];
1324 else
1325 filename = "" + data["posts"][post_number]["tim"] + data["posts"][post_number]["ext"];
1326 if (filename !== undefined && filename !== null && filename.indexOf("undefined") == -1)
1327 if (_this.use_offsite_archive)
1328 if (data["posts"][post_number]["media"] !== null)
1329 _this.thread_data[1].push(data["posts"][post_number]["media"]["remote_media_link"]);
1330 else
1331 _this.thread_data[1].push("");
1332 else
1333 _this.thread_data[1].push("https://i.4cdn.org/" + _this.board + "/" + filename);
1334 else
1335 _this.thread_data[1].push("");
1336 if (_this.use_offsite_archive) {
1337 if (data["posts"][post_number]["media"] !== null)
1338 _this.thread_data[2].push(data["posts"][post_number]["media"]["media_id"]);
1340 else
1341 _this.thread_data[2].push(data["posts"][post_number]["filename"]);
1342 if (_this.use_offsite_archive)
1343 _this.thread_data[3].push(data["posts"][post_number]["num"]);
1344 else
1345 _this.thread_data[3].push(data["posts"][post_number]["no"]);
1348 _this.semaphore--;
1350 }));
1353 //3) RIP POSTS AND IMAGES
1354 ThreadRebuilder.prototype.createPost = function (text, imageURL, imageName) {
1355 var _this = this;
1356 if (imageURL != "") {
1357 var response_type = "arraybuffer";
1358 if (this.use_offsite_archive)
1359 response_type = "text";
1360 var xhr = new GM_xmlhttpRequest(({
1361 method: "GET",
1362 url: imageURL,
1363 responseType: response_type,
1364 onload: function (response) {
1365 if (_this.use_offsite_archive) {
1366 var parser = new DOMParser();
1367 var content_attribute = parser.parseFromString(response.response, "text/html").getElementsByTagName("META")[0].getAttribute("content");
1368 var redirect_url = content_attribute.substring(content_attribute.indexOf("http"));
1369 var xhr = new GM_xmlhttpRequest(({ method: "GET", url: redirect_url, responseType: "arraybuffer",
1370 onload: function (response) {
1371 _this.inputImage(response, text, imageURL, imageName);
1373 }));
1375 else {
1376 _this.inputImage(response, text, imageURL, imageName);
1379 }));
1381 else {
1382 text = this.createPostComment(text);
1383 this.setPropperLinking(text);
1386 ThreadRebuilder.prototype.inputImage = function (response, text, imageURL, imageName) {
1387 var blob;
1388 var ext = ".jpg";
1389 if (imageURL.indexOf(".jpg") > -1) {
1390 blob = new Blob([response.response], { type: "image/jpeg" });
1391 ext = ".jpg";
1393 else if (imageURL.indexOf(".png") > -1) {
1394 blob = new Blob([response.response], { type: "image/png" });
1395 ext = ".png";
1397 else if (imageURL.indexOf(".gif") > -1) {
1398 blob = new Blob([response.response], { type: "image/gif" });
1399 ext = ".gif";
1401 else if (imageURL.indexOf(".webm") > -1) {
1402 blob = new Blob([response.response], { type: "video/webm" });
1403 ext = ".webm";
1405 var name = imageName + ext;
1406 //SEND RESULTING RESPONSE TO 4CHANX FILES === QRSetFile
1407 var detail = { file: blob, name: name };
1408 detail = cloneInto(detail, document.defaultView);
1409 document.dispatchEvent(new CustomEvent('QRSetFile', { bubbles: true, detail: detail }));
1410 if (text !== "" && text !== undefined) {
1411 text = this.createPostComment(text);
1412 this.setPropperLinking(text);
1414 else {
1415 document.getElementById("add-post").click();
1416 this.semaphore_posts++;
1419 //4) CREATE POST QUEUE
1420 ThreadRebuilder.prototype.createPostComment = function (text) {
1421 var dummy = document.createElement("DIV");
1422 dummy.innerHTML = text;
1423 var inside_node = dummy.firstChild;
1424 var return_text = "";
1425 do {
1426 if (inside_node.tagName == "BR")
1427 return_text += "\n";
1428 else
1429 return_text += inside_node.textContent;
1430 } while ((inside_node = inside_node.nextSibling));
1431 return return_text;
1434 ThreadRebuilder.prototype.timeListenerFunction = function () {
1435 var time = parseInt(document.getElementById("qr-filename-container").nextSibling.value.replace(/[a-zA-Z]+/g, ""));
1436 if (time <= 5) {
1437 this.checked = false;
1439 else if (time > 5) {
1440 this.checked = true;
1443 ThreadRebuilder.prototype.killAll = function () {
1444 this.thread_data_length = 0;
1445 this.posts_created = 0;
1446 this.stopRoutine();
1447 this.postID = undefined;
1448 this.semaphore = 1;
1449 this.semaphore_posts = 1;
1450 this.stopFillRoutine();
1451 this.fillID = undefined;
1452 this.thread_data = [['Comment'], ['Image URLs'], ['Image Names'], ['Post No.']];
1453 //CLEAR DUMP LIST
1454 var qr_dumplist = document.getElementById("dump-list").childNodes;
1455 var qr_dumplist_len = qr_dumplist.length;
1456 var current_preview = 0;
1457 while (qr_dumplist_len - current_preview > 1) {
1458 qr_dumplist[0].firstChild.click();
1459 current_preview++;
1462 return ThreadRebuilder;
1463 }(FeatureInterface));
1464 var CharacterInserter = /** @class */ (function (_super) {
1465 __extends(CharacterInserter, _super);
1466 function CharacterInserter(use_kita, use_yen) {
1467 var _this = _super.call(this) || this;
1468 _this.kita_character = "キタ━━━(゚∀゚)━━━!!";
1469 _this.kita_hash_color = "#444444";
1470 _this.yen_character = "¥";
1471 _this.yen_hash_color = "#9370DB";
1472 _this.use_yen = use_yen;
1473 _this.use_kita = use_kita;
1474 _this.retrieveStates();
1475 _this.init();
1476 _this.activate();
1477 return _this;
1479 CharacterInserter.prototype.init = function () {
1480 this.addStyle();
1481 this.hotkeyListeners();
1483 CharacterInserter.prototype.activate = function () {
1484 console.log("4F-FSE: CharacterInserter Active - " + (this.use_kita ? "Character Coloring+" : "") + (this.use_yen ? " Line Coloring" : ""));
1486 CharacterInserter.prototype.decideAction = function (node) {
1487 if (node.tagName == "BLOCKQUOTE")
1488 this.colorCharacters(node);
1490 CharacterInserter.prototype.retrieveStates = function () {
1491 if (localStorage.getItem("Yen_Character") === undefined || localStorage.getItem("Yen_Character") === null)
1492 this.yen_character = "¥";
1493 else
1494 this.yen_character = localStorage.getItem("Yen_Character");
1495 if (localStorage.getItem("Yen_Color") === undefined || localStorage.getItem("Yen_Color") === null)
1496 this.yen_hash_color = "#9370DB";
1497 else
1498 this.yen_hash_color = localStorage.getItem("Yen_Color");
1499 if (localStorage.getItem("Kita_Character") === undefined || localStorage.getItem("Kita_Character") === null)
1500 this.kita_character = "キタ━━━(゚∀゚)━━━!!";
1501 else
1502 this.kita_character = localStorage.getItem("Kita_Character");
1503 if (localStorage.getItem("Kita_Color") === undefined || localStorage.getItem("Kita_Color") === null)
1504 this.kita_hash_color = "#444444";
1505 else
1506 this.kita_hash_color = localStorage.getItem("Kita_Color");
1508 CharacterInserter.prototype.storeStates = function () {
1509 var items = [];
1510 for (var _i = 0; _i < arguments.length; _i++) {
1511 items[_i] = arguments[_i];
1514 //color styling
1515 CharacterInserter.prototype.addStyle = function () {
1516 var style = document.createElement("STYLE");
1517 style.innerHTML = ".the_m_word{color:" + this.yen_hash_color + "} \n.the_k_word{color:" + this.kita_hash_color + "}";
1518 document.head.appendChild(style);
1520 //hotkeys for kita and yen
1521 CharacterInserter.prototype.hotkeyListeners = function () {
1522 var _this = this;
1523 var listener_obj = {};
1524 window.addEventListener("keydown", function (e) {
1525 listener_obj[e.keyCode] = true;
1526 var node = document.activeElement;
1527 if ((listener_obj[17] || listener_obj[91]) && listener_obj[75]) {
1528 e.preventDefault();
1529 _this.insertAtPos(node, _this.kita_character);
1531 if ((listener_obj[17] || listener_obj[91]) && listener_obj[220]) {
1532 e.preventDefault();
1533 _this.insertAtPos(node, _this.yen_character);
1535 }, { passive: false, capture: false, once: false });
1536 window.addEventListener("keyup", function (e) {
1537 listener_obj[e.keyCode] = false;
1538 }, { passive: false, capture: false, once: false });
1540 CharacterInserter.prototype.insertAtPos = function (node, buzzwords) {
1541 var sel_start = node.selectionStart;
1542 var sel_end = node.selectionEnd;
1543 var node_text = node.value;
1544 node.value = node_text.substr(0, sel_start) + buzzwords + node_text.substr(sel_end);
1545 node.selectionStart = sel_start + buzzwords.length;
1546 node.selectionEnd = sel_end + buzzwords.length;
1548 //insertion logic
1549 CharacterInserter.prototype.colorCharacters = function (root) {
1550 if (root.nodeType !== Node.ELEMENT_NODE) {
1551 return;
1553 if (root.textContent.indexOf(this.yen_character) <= -1 && root.textContent.indexOf(this.kita_character) <= -1) {
1554 return;
1556 var wbr = root.getElementsByTagName('WBR');
1557 var wbr_len = wbr.length;
1558 var wbr_indices = Array();
1559 function previousIndex(len) {
1560 if (len > 0)
1561 return wbr_indices[len - 1];
1562 else
1563 return 0;
1565 for (var wbr_item = 0; wbr_item < wbr_len; wbr_item++) {
1566 wbr_indices.push(wbr[wbr_item].previousSibling.length + previousIndex(wbr_item));
1568 while (wbr.length) {
1569 root.removeChild(wbr[wbr.length - 1]);
1571 root.normalize();
1572 var txtItterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
1573 var text_node;
1574 while ((text_node = txtItterator.nextNode())) {
1575 //disregard text inside of A tag links and already colored text
1576 if (text_node.parentNode.tagName == "A" || /the_[a-z]_word/g.test(text_node.parentNode.className))
1577 continue;
1578 this.setColor(text_node, txtItterator);
1580 //restart and add back the wbr
1581 var txtItterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
1582 var text_node;
1583 while ((text_node = txtItterator.nextNode())) {
1584 //disregard text inside of A tag links and already colored text
1585 if (text_node.parentNode.tagName == "A")
1586 continue;
1587 wbr_indices = this.addWBR(text_node, txtItterator, wbr_indices);
1590 //reinsert <wbr>
1591 CharacterInserter.prototype.addWBR = function (text_node, txtItterator, wbr_indices) {
1592 wbr_indices[0] = wbr_indices[0] - text_node.length;
1593 if (wbr_indices[0] <= 0) {
1594 var split_node = text_node.splitText(text_node.length + wbr_indices[0]);
1595 var wbr = document.createElement("WBR");
1596 split_node.parentNode.insertBefore(wbr, text_node.nextSibling);
1597 wbr_indices.shift();
1599 return wbr_indices;
1601 //give color to text inside of nodes.
1602 // first scan for yen symbols and then check the front of the text for not nested kita.
1603 CharacterInserter.prototype.setColor = function (text_node, txtItterator) {
1604 var start_text_node = text_node;
1605 var result;
1606 var yen_node = this.use_kita ? this.searchYen(text_node) : false;
1607 if (yen_node != false) {
1608 //jump to internal node
1609 text_node = txtItterator.nextNode();
1610 //scan for nested kita
1611 do {
1612 result = this.use_kita ? this.searchKita(text_node) : false;
1613 if (result != false) {
1614 //jump foreward to point after kita inserted
1615 text_node = txtItterator.nextNode();
1616 text_node = txtItterator.nextNode();
1618 } while (result != false);
1620 //scan for outside kita from start
1621 do {
1622 result = this.use_kita ? this.searchKita(start_text_node) : false;
1623 start_text_node = result.nextSibling;
1624 } while (result != false && start_text_node !== undefined);
1626 //find the location of a yen, split the text from above that position, create a span element and place split into this span.
1627 //Then take the initial text node and insert into it from after the text node.
1628 CharacterInserter.prototype.searchYen = function (text_node) {
1629 var yenIndex = text_node.textContent.indexOf(this.yen_character);
1630 if (yenIndex > -1) {
1631 var splitNode = text_node.splitText(yenIndex);
1632 var span = document.createElement('span');
1633 span.className = "the_m_word";
1634 span.appendChild(splitNode);
1635 text_node.parentNode.insertBefore(span, text_node.nextSibling);
1636 return span;
1638 return false;
1640 //find the location of a kita, isolate it by splitting from the point where the kita ends and the point where it begins.
1641 //Now that there are 3 text nodes, take the middle one from the start position index split, add the text which goes to the point of the rightmost split,
1642 //then refer back to the parent and place it after the leftmost string.
1643 CharacterInserter.prototype.searchKita = function (text_node) {
1644 var kIndex = text_node.textContent.indexOf(this.kita_character);
1645 if (kIndex > -1) {
1646 var far_split_note = text_node.splitText(kIndex + this.kita_character.length);
1647 var splitNode = text_node.splitText(kIndex);
1648 var span = document.createElement('span');
1649 span.className = "the_k_word";
1650 span.appendChild(splitNode);
1651 text_node.parentNode.insertBefore(span, text_node.nextSibling);
1652 return span;
1654 return false;
1656 return CharacterInserter;
1657 }(FeatureInterface));
1658 var PasswordViewer = /** @class */ (function (_super) {
1659 __extends(PasswordViewer, _super);
1660 function PasswordViewer() {
1661 var _this = _super.call(this) || this;
1662 _this.post_id = "postPassword";
1663 _this.del_id = "delPassword";
1664 _this.label_post = document.createElement('LABEL');
1665 _this.label_del = document.createElement('LABEL');
1666 _this.init();
1667 _this.activate();
1668 return _this;
1670 PasswordViewer.prototype.init = function () {
1671 this.node_post = document.getElementById(this.post_id);
1672 this.node_del = document.getElementById(this.del_id);
1673 this.node_post_parent = this.node_post.parentNode;
1674 this.node_del_parent = this.node_del.parentNode;
1675 this.label_post.textContent = 'Post: ';
1676 this.label_del.textContent = 'Delete: ';
1678 //activate displays passwords
1679 PasswordViewer.prototype.activate = function () {
1680 console.log("4F-FSE: PasswordViewer Active");
1681 this.node_post_parent.insertBefore(this.label_post, this.node_post);
1682 this.node_del_parent.insertBefore(this.label_del, this.node_del);
1683 this.node_post.removeAttribute('type');
1684 this.node_del.removeAttribute('type');
1685 document.getElementsByClassName('deleteform')[0].style.display = 'inline';
1686 this.node_del.style.display = 'inline';
1687 this.label_del.style.display = 'inline';
1688 this.label_del.style.paddingLeft = '10px';
1690 PasswordViewer.prototype.decideAction = function (node) { };
1691 PasswordViewer.prototype.retrieveStates = function () { };
1693 PasswordViewer.prototype.storeStates = function () { };
1695 return PasswordViewer;
1696 }(FeatureInterface));
1697 var SettingsWindow = /** @class */ (function (_super) {
1698 __extends(SettingsWindow, _super);
1699 function SettingsWindow() {
1700 var _this = _super.call(this) || this;
1701 _this.background_div = document.createElement('DIV');
1702 _this.settings_div = document.createElement('DIV');
1703 _this.close_div = document.createElement('DIV');
1704 _this.contents_div = document.createElement('DIV');
1705 _this.ul_selection_start = document.createElement('UL');
1706 _this.close_link = document.createElement('A');
1707 _this.title_para = document.createElement('P');
1708 _this.title_text = document.createTextNode('4F-FSE Settings');
1709 _this.end_para = document.createElement('P');
1710 _this.end_text = document.createTextNode('Refresh to view changes');
1711 _this.settings_style = document.createElement('STYLE');
1712 //to change order change, this AND...*
1713 _this.list_items = [
1714 { Text: " | View 『Image Hiding』 Settings", ListenerFunc: function (a_id) {
1715 _this.clearContainer();
1716 _this.contents_div.innerHTML =
1717 "\n\t\t\t\t<div id=\"disposable_container\">\n\t\t\t\t\t\t\t\t <label>Non-MD5 Expiration Time(hours): </label>\n\t\t\t\t\t\t\t\t <input id=\"Expiration_Time\">\n\t\t\t\t\t\t\t\t <hr>\n\t\t\t\t\t\t\t\t <label>MD5 Filters:</label>\n\t\t\t\t\t\t\t\t <br>\n\t\t\t\t\t\t\t\t <textarea style=\"width:98%;height:217px\" placeholder=\"Enter MD5 like on 4chanX... \n\t\t\t\t\t\t\t\t/abc123/\n\t\t\t\t\t\t\t\t/def890/\" id=\"MD5_List_FSE\"></textarea>\n\t\t\t\t\t\t\t\t<hr>\n\t\t\t\t</div>\n\t\t\t\t";
1718 document.getElementById("Expiration_Time").value = "" + (_this.setting_items.image_hiding_settings.Expiration_Time / Constants.MILLISECONDS_TO_THE_HOUR);
1719 document.getElementById("MD5_List_FSE").value = _this.setting_items.image_hiding_settings.MD5_List_FSE;
1720 var set_button = document.createElement('INPUT');
1721 document.getElementById("disposable_container").appendChild(set_button);
1722 set_button.setAttribute('VALUE', "Set Image Settings");
1723 set_button.addEventListener("click", function (evt) {
1724 _this.storeStates();
1725 _this.clearContainer();
1726 _this.rebuildContainer();
1728 set_button.setAttribute('TYPE', 'button');
1731 { Text: " | View 『Word Replacement』 Settings", ListenerFunc: function (a_id) {
1732 _this.clearContainer();
1733 var disposable_container = document.createElement("DIV");
1734 disposable_container.setAttribute("ID", "disposable_container");
1735 _this.contents_div.appendChild(disposable_container);
1736 _this.filterWindow(disposable_container);
1737 _this.filterSetTable();
1740 { Text: " | View 『Danbooru Image Adder』 Settings", ListenerFunc: function (a_id) {
1741 _this.clearContainer();
1742 var disposable_container = document.createElement("DIV");
1743 disposable_container.setAttribute("id", "disposable_container");
1744 _this.contents_div.appendChild(disposable_container);
1745 disposable_container.innerHTML = "\n\t\t\t<table style=\"text-align:center;margin-left:5px\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Very Large: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"v_large_DIA\" name=\"preivew-size\" style=\"display:inline\" type=\"radio\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Large: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"large_DIA\" name=\"preivew-size\" style=\"display:inline\" type=\"radio\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Medium: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"medium_DIA\" name=\"preivew-size\" style=\"display:inline\" type=\"radio\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Small: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"small_DIA\" name=\"preivew-size\" style=\"display:inline\" type=\"radio\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Width: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"width_DIA\" name=\"preivew-size\" style=\"width:20%\" type=\"text\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<label>Height: </label>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<input id=\"height_DIA\" name=\"preivew-size\" style=\"width:20%\" type=\"text\">\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\t\n\t\t\n\t\t\t<hr>\n\t\t\t\n\t\t\t<label>Quick Reply Min Width: </label>\n\t\t\t<input id=\"qr_width_DIA\" name=\"preivew-size\" style=\"width:20%\" type=\"text\">\n\t\t\n\t\t\t<hr>\n\t\t\n\t\t\t<input id=\"SetImageAdderProperties\" value=\"Set Preview Size\" type=\"button\">\n\t\t\t";
1746 _this.setImageAdderFields();
1747 _this.setImageAdderEventListeners();
1750 { Text: " | View 『Thread Rebuilder』 Settings", ListenerFunc: function (a_id) {
1751 _this.clearContainer();
1752 var disposable_container = document.createElement("DIV");
1753 disposable_container.setAttribute("id", "disposable_container");
1754 _this.contents_div.appendChild(disposable_container);
1755 disposable_container.innerHTML =
1756 "\n\t\t\t\t<label>Use 4chan Archives: </label>\n\t\t\t\t<input name=\"ArchiveSettings\" id=\"OnsiteArchive\" type=\"radio\">\n\t\t\t\t<br>\n\t\t\t\t<label>Use Offsite Archives: </label>\n\t\t\t\t<input name=\"ArchiveSettings\" id=\"OffsiteArchive\" type=\"radio\">\n\t\t\t\t<br>\n\t\t\t\t<input id=\"setArchive\" value=\"Set Archive\" type=\"button\">\n\t\t\t";
1757 (document.getElementById("setArchive")).addEventListener("click", function () {
1758 _this.storeStates();
1759 _this.clearContainer();
1760 _this.rebuildContainer();
1762 if (_this.setting_items.thread_rebuild_settings.Archive_Type === "0")
1763 document.getElementById("OffsiteArchive").checked = true;
1764 else if (_this.setting_items.thread_rebuild_settings.Archive_Type === "1")
1765 document.getElementById("OnsiteArchive").checked = true;
1768 { Text: " | View 『¥ Text』 Settings [Customizable]", ListenerFunc: function (a_id) {
1769 _this.clearContainer();
1770 var disposable_container = document.createElement("DIV");
1771 disposable_container.setAttribute("id", "disposable_container");
1772 _this.contents_div.appendChild(disposable_container);
1773 disposable_container.innerHTML =
1774 "\n\t\t\t\t<label>\u00A5Quote Character: </label>\n\t\t\t\t<input name=\"quoteCharacter\" id=\"quoteCharacter\" type=\"text\" value=\"\u00A5\">\n\t\t\t\t<br>\n\t\t\t\t<label>RGB Hex Color: </label>\n\t\t\t\t<input name=\"HexColorYen\" id=\"HexColorYen_text\" type=\"text\">\n\t\t\t\t<input name=\"HexColorYen\" id=\"SelectColorYen\" type=\"color\">\n\t\t\t\t<br>\n\t\t\t\t<input id=\"setQuote\" value=\"Set Quote Settings\" type=\"button\">\n\t\t\t";
1775 document.getElementById("SelectColorYen").addEventListener("input", function (evt) {
1776 document.getElementById("HexColorYen_text").value =
1777 (document.getElementById("SelectColorYen").value);
1779 document.getElementById("setQuote").addEventListener("click", function (e) {
1780 _this.storeStates();
1781 _this.clearContainer();
1782 _this.rebuildContainer();
1784 if (_this.setting_items.character_inserter_settings.Yen_Character !== undefined)
1785 document.getElementById("quoteCharacter").value = _this.setting_items.character_inserter_settings.Yen_Character;
1786 if (_this.setting_items.character_inserter_settings.Yen_Color !== undefined)
1787 document.getElementById("HexColorYen_text").value = _this.setting_items.character_inserter_settings.Yen_Color;
1788 document.getElementById("SelectColorYen").value = _this.setting_items.character_inserter_settings.Yen_Color;
1791 { Text: " | View 『Kita』 Settings [Customizable]", ListenerFunc: function (a_id) {
1792 _this.clearContainer();
1793 var disposable_container = document.createElement("DIV");
1794 disposable_container.setAttribute("id", "disposable_container");
1795 _this.contents_div.appendChild(disposable_container);
1796 disposable_container.innerHTML =
1797 "\t\t\t\t\t\t\t\t\n\t\t\t\t<script src=\"http://jscolor.js\"></script>\n\t\t\t\t<label>Kita Characters: </label>\n\t\t\t\t<input name=\"selectiveCharacter\" id=\"selectiveCharacters\" type=\"text\" value=\"\uFF77\uFF80\u2501\u2501\u2501(\uFF9F\u2200\uFF9F)\u2501\u2501\u2501!!\">\n\t\t\t\t<br>\n\t\t\t\t<label>RGB Hex Color: </label>\n\t\t\t\t<input name=\"HexColorKita\" id=\"HexColorKita_text\" type=\"text\">\n\t\t\t\t<input name=\"HexColorKita\" id=\"SelectColorKita\" type=\"color\">\n\t\t\t\t<br>\n\t\t\t\t<input id=\"setCharacter\" value=\"Set Character Settings\" type=\"button\">\n\t\t\t";
1798 document.getElementById("SelectColorKita").addEventListener("input", function (evt) {
1799 document.getElementById("HexColorKita_text").value =
1800 (document.getElementById("SelectColorKita").value);
1802 document.getElementById("setCharacter").addEventListener("click", function (e) {
1803 _this.storeStates();
1804 _this.clearContainer();
1805 _this.rebuildContainer();
1807 if (_this.setting_items.character_inserter_settings.Kita_Character !== undefined)
1808 document.getElementById("selectiveCharacters").value = _this.setting_items.character_inserter_settings.Kita_Character;
1809 if (_this.setting_items.character_inserter_settings.Kita_Color !== undefined)
1810 document.getElementById("HexColorKita_text").value = _this.setting_items.character_inserter_settings.Kita_Color;
1811 document.getElementById("SelectColorKita").value = _this.setting_items.character_inserter_settings.Kita_Color;
1814 { Text: " | Set 『Visible Password』", ListenerFunc: function (input_id) {
1815 _this.storeStates();
1816 } },
1818 _this.setting_items = {};
1819 _this.retrieveStates();
1820 _this.init();
1821 _this.activate();
1822 return _this;
1824 SettingsWindow.prototype.setImageAdderFields = function () {
1825 document.getElementById("width_DIA").value = this.setting_items.image_adder_settings.Width;
1826 document.getElementById("height_DIA").value = this.setting_items.image_adder_settings.Height;
1827 document.getElementById("qr_width_DIA").value = this.setting_items.image_adder_settings.QR_Width;
1828 if (document.getElementById("width_DIA").value == "489")
1829 document.getElementById("v_large_DIA").checked = true;
1830 else if (document.getElementById("width_DIA").value == "400")
1831 document.getElementById("large_DIA").checked = true;
1832 else if (document.getElementById("width_DIA").value == "300")
1833 document.getElementById("medium_DIA").checked = true;
1834 else if (document.getElementById("width_DIA").value == "200")
1835 document.getElementById("small_DIA").checked = true;
1837 SettingsWindow.prototype.setImageAdderEventListeners = function () {
1838 var _this = this;
1839 document.getElementById("v_large_DIA").addEventListener("click", function () {
1840 document.getElementById("width_DIA").value = "489";
1841 document.getElementById("height_DIA").value = "489";
1843 document.getElementById("large_DIA").addEventListener("click", function () {
1844 document.getElementById("width_DIA").value = "400";
1845 document.getElementById("height_DIA").value = "400";
1847 document.getElementById("medium_DIA").addEventListener("click", function () {
1848 document.getElementById("width_DIA").value = "300";
1849 document.getElementById("height_DIA").value = "300";
1851 document.getElementById("small_DIA").addEventListener("click", function () {
1852 document.getElementById("width_DIA").value = "200";
1853 document.getElementById("height_DIA").value = "200";
1855 document.getElementById("SetImageAdderProperties").addEventListener("click", function (evt) {
1856 _this.storeStates();
1857 _this.clearContainer();
1858 _this.rebuildContainer();
1861 //*...THIS
1862 SettingsWindow.prototype.retrieveStates = function () {
1863 //values used to fill out data fields
1864 this.setting_items.image_hiding_settings = { Expiration_Time: localStorage.getItem("Expiration_Time"), MD5_List_FSE: localStorage.getItem("MD5_List_FSE"), Active: localStorage.getItem("ImageHidingActive") };
1865 this.retrieveWordReplaceStates();
1866 this.retrieveImageAdderStates();
1867 this.retrieveRebuildStates();
1868 this.retrieveCharacterInsertingStates();
1869 this.setting_items.password_settings = (localStorage.getItem("PasswordActive"));
1871 SettingsWindow.prototype.retrieveActiveToggles = function () {
1872 if (localStorage.getItem("4F-FSE") === null) {
1873 document.getElementById("check-settings0").checked = true;
1874 document.getElementById("check-settings1").checked = false;
1875 document.getElementById("check-settings2").checked = false;
1876 document.getElementById("check-settings3").checked = false;
1877 document.getElementById("check-settings4").checked = true;
1878 document.getElementById("check-settings5").checked = true;
1879 document.getElementById("check-settings6").checked = true;
1880 localStorage.setItem("4F-FSE", "Success");
1881 this.displayWindow();
1882 return;
1884 document.getElementById("check-settings0").checked = localStorage.getItem("ImageHidingActive") === 'true';
1885 document.getElementById("check-settings1").checked = localStorage.getItem("TextReplaceActive") === 'true';
1886 document.getElementById("check-settings2").checked = localStorage.getItem("ImageAdderActive") === 'true';
1887 document.getElementById("check-settings3").checked = localStorage.getItem("ThreadRebuilderActive") === 'true';
1888 document.getElementById("check-settings4").checked = localStorage.getItem("YenActive") === 'true';
1889 document.getElementById("check-settings5").checked = localStorage.getItem("KitaActive") === 'true';
1890 document.getElementById("check-settings6").checked = localStorage.getItem("PasswordActive") === 'true';
1892 SettingsWindow.prototype.retrieveWordReplaceStates = function () {
1893 //acquire text filter representation
1894 var storage_index = 0;
1895 var JSON_storage = {};
1896 var storage_key;
1897 var text_filters = [];
1898 var local_store_len = window.localStorage.length;
1899 while (storage_index < local_store_len) {
1900 storage_key = window.localStorage.key(storage_index);
1901 JSON_storage[storage_key] = window.localStorage.getItem(storage_key);
1902 storage_index++;
1904 var filters = Generics.getJSONPropertiesByKeyName(JSON_storage, "[0-9]+FLT");
1905 filters.sort();
1906 filters.forEach(function (filter) {
1907 text_filters.push(TextReplacer.formatFilterSettings(JSON_storage[filter]));
1909 this.setting_items.word_replace_settings = { Number_of_Filters: localStorage.getItem("filter_quantity"), Text_Filter_List: text_filters, Active: localStorage.getItem("TextReplaceActive") };
1911 SettingsWindow.prototype.retrieveImageAdderStates = function () {
1912 this.setting_items.image_adder_settings = { Width: localStorage.getItem("width_DIA"),
1913 Height: localStorage.getItem("height_DIA"),
1914 QR_Width: localStorage.getItem("qr_width_DIA"),
1915 Active: localStorage.getItem("ImageAdderActive") };
1916 if (this.setting_items.image_adder_settings.Height === null)
1917 this.setting_items.image_adder_settings.Height = 400;
1918 if (this.setting_items.image_adder_settings.Width === null)
1919 this.setting_items.image_adder_settings.Width = 400;
1920 if (this.setting_items.image_adder_settings.QR_Width === null)
1921 this.setting_items.image_adder_settings.QR_Width = 480;
1922 document.getElementById("fourchanx-css").textContent += ".qr-preview { height:" + this.setting_items.image_adder_settings.Height + "px; width: " + this.setting_items.image_adder_settings.Width + "px; left:8%;background-size: cover;}";
1923 document.getElementById("fourchanx-css").textContent += "#dump-list { min-height: " + (this.setting_items.image_adder_settings.Width - 20) + "px; width: " + (this.setting_items.image_adder_settings.QR_Width) + "px;}";
1925 SettingsWindow.prototype.retrieveRebuildStates = function () {
1926 if (localStorage.getItem("ArchiveType_FSE") !== "1" && localStorage.getItem("ArchiveType_FSE") !== "0")
1927 localStorage.setItem("ArchiveType_FSE", "1");
1928 this.setting_items.thread_rebuild_settings = { Archive_Type: localStorage.getItem("ArchiveType_FSE"), Active: localStorage.getItem("ThreadRebuilderActive") };
1930 SettingsWindow.prototype.retrieveCharacterInsertingStates = function () {
1931 if (localStorage.getItem("Yen_Character") === undefined || localStorage.getItem("Yen_Character") === null)
1932 localStorage.setItem("Yen_Character", "¥");
1933 if (localStorage.getItem("Yen_Color") === undefined || localStorage.getItem("Yen_Color") === null)
1934 localStorage.setItem("Yen_Color", "#9370DB");
1935 if (localStorage.getItem("Kita_Character") === undefined || localStorage.getItem("Kita_Character") === null)
1936 localStorage.setItem("Kita_Character", "キタ━━━(゚∀゚)━━━!!");
1937 if (localStorage.getItem("Kita_Color") === undefined || localStorage.getItem("Kita_Color") === null)
1938 localStorage.setItem("Kita_Color", "#444444");
1939 this.setting_items.character_inserter_settings = { Yen_Active: localStorage.getItem("YenActive"), Yen_Character: localStorage.getItem("Yen_Character"), Yen_Color: localStorage.getItem("Yen_Color"),
1940 Kita_Active: localStorage.getItem("KitaActive"), Kita_Character: localStorage.getItem("Kita_Character"), Kita_Color: localStorage.getItem("Kita_Color") };
1942 SettingsWindow.prototype.storeStates = function () {
1943 //image settings
1944 this.storeImageFilterStates();
1945 //Text replace settings
1946 this.storeTextFilterStates();
1947 //Image Adder settings
1948 this.storeImageAdderStates();
1949 //Thread rebuild settings
1950 this.storeRebuildStates();
1951 //character inserter
1952 this.storeCharacterInserterStates();
1953 //Password replace settings
1954 this.storePasswordStates();
1955 this.retrieveStates();
1957 SettingsWindow.prototype.storeActiveToggles = function () {
1958 localStorage.setItem("ImageHidingActive", (document.getElementById("check-settings0").checked.toString()));
1959 localStorage.setItem("TextReplaceActive", (document.getElementById("check-settings1").checked.toString()));
1960 localStorage.setItem("ImageAdderActive", (document.getElementById("check-settings2").checked.toString()));
1961 localStorage.setItem("ThreadRebuilderActive", (document.getElementById("check-settings3").checked.toString()));
1962 localStorage.setItem("YenActive", (document.getElementById("check-settings4").checked.toString()));
1963 localStorage.setItem("KitaActive", (document.getElementById("check-settings5").checked.toString()));
1964 localStorage.setItem("PasswordActive", (document.getElementById("check-settings6").checked.toString()));
1966 SettingsWindow.prototype.storeImageFilterStates = function () {
1967 if (document.getElementById("Expiration_Time") !== null) {
1968 var time = document.getElementById("Expiration_Time");
1969 var millisecond_time = parseInt(time.value) * Constants.MILLISECONDS_TO_THE_HOUR;
1970 if (millisecond_time == 0 || millisecond_time === null || millisecond_time === undefined)
1971 millisecond_time = Constants.DEFAULT_HIDE_EXPIRATION_TIME;
1972 localStorage.setItem("Expiration_Time", millisecond_time.toString());
1973 var md5_filters = document.getElementById("MD5_List_FSE").value;
1974 localStorage.setItem("MD5_List_FSE", md5_filters);
1975 Generics.alert4ChanX("Image Settings Saved", "success", 3);
1978 SettingsWindow.prototype.storeTextFilterStates = function () {
1979 if (document.getElementById("FilterRow0") !== null) {
1980 var f_row_moving = document.getElementById("FilterRow0");
1981 var Number_of_Filters = 0;
1982 var Number_of_Filters_actual = 0;
1983 while (f_row_moving.nextSibling !== null) {
1984 if (document.getElementById("Pattern" + Number_of_Filters).value !== "")
1985 Number_of_Filters_actual++;
1986 Number_of_Filters++;
1987 f_row_moving = f_row_moving.nextSibling;
1989 window.localStorage.setItem("filter_quantity", Number_of_Filters_actual.toString());
1990 for (var pattern_input = 0; pattern_input < Number_of_Filters; pattern_input++) {
1991 var pattern_to_store = document.getElementById("Pattern" + pattern_input).value;
1992 var replacement_to_store = document.getElementById("Replacement" + pattern_input).value;
1993 var setting = 'g';
1994 try {
1995 if (pattern_to_store === "") {
1996 localStorage.removeItem(pattern_input + "FLT");
1997 continue;
1999 else if (new RegExp("^\/.*\/\\D+$").test(pattern_to_store)) { }
2000 else if (new RegExp("^\/.*\/$").test(pattern_to_store)) {
2001 pattern_to_store = pattern_to_store + setting;
2003 else if (!new RegExp("^/.*\/\\D$").test(pattern_to_store)) {
2004 pattern_to_store = "/" + pattern_to_store + "/" + setting;
2006 //test for breakages, try to cause error
2007 var error_test = new RegExp(pattern_to_store.substring(0, pattern_to_store.lastIndexOf("/") + 1), pattern_to_store.substring(pattern_to_store.lastIndexOf("/") + 1));
2009 catch (e) {
2010 Generics.alert4ChanX("Unrecoverable Regex error on pattern " + pattern_input + " for " + pattern_to_store, "error", undefined);
2011 continue;
2013 pattern_to_store = encodeURIComponent(pattern_to_store);
2014 var save_string = document.getElementById("Active" + pattern_input).checked + '=' + pattern_to_store + '=' + replacement_to_store;
2015 window.localStorage.setItem(pattern_input + "FLT", save_string);
2017 Generics.alert4ChanX("Wordfilters Updated!", "success", 3);
2020 SettingsWindow.prototype.storeImageAdderStates = function () {
2021 if (document.getElementById("SetImageAdderProperties") !== null) {
2022 var width = document.getElementById("width_DIA").value;
2023 localStorage.setItem("width_DIA", width);
2024 var height = document.getElementById("height_DIA").value;
2025 localStorage.setItem("height_DIA", height);
2026 var qr_width = document.getElementById("qr_width_DIA").value;
2027 localStorage.setItem("qr_width_DIA", qr_width);
2030 SettingsWindow.prototype.storeRebuildStates = function () {
2031 if (document.getElementById("setArchive") !== null) {
2032 localStorage.setItem("ArchiveType_FSE", document.getElementById("OffsiteArchive").checked === true ? "0" : "1");
2035 SettingsWindow.prototype.storeCharacterInserterStates = function () {
2036 if (document.getElementById("setCharacter") !== null) {
2037 localStorage.setItem("Kita_Character", document.getElementById("selectiveCharacters").value);
2038 localStorage.setItem("Kita_Color", document.getElementById("HexColorKita_text").value);
2040 else if (document.getElementById("setQuote") !== null) {
2041 localStorage.setItem("Yen_Character", document.getElementById("quoteCharacter").value);
2042 localStorage.setItem("Yen_Color", document.getElementById("HexColorYen_text").value);
2045 SettingsWindow.prototype.storePasswordStates = function () {
2046 //password view settings
2047 if (document.getElementById("check-settings6") !== null)
2048 localStorage.setItem("PasswordActive", "" + document.getElementById("check-settings6").checked);
2050 SettingsWindow.prototype.clearContainer = function () {
2051 var disposable = document.getElementById("disposable_container");
2052 if (disposable !== null)
2053 this.contents_div.removeChild(disposable);
2054 else
2055 this.contents_div.removeChild(this.ul_selection_start);
2057 SettingsWindow.prototype.rebuildContainer = function () {
2058 this.contents_div.appendChild(this.ul_selection_start);
2060 SettingsWindow.prototype.init = function () {
2061 var _this = this;
2062 this.settings_style.innerHTML = ".inputs{\n\t\t\t\t\t\t\t\t\t\t\tbackground-color:rgb(200,200,200);margin:5px 7px;width:100px;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.SettingsBackground{\n\t\t\t\t\t\t\t\t\t\t\tposition:fixed;width:100%;height:100%;background-color:rgba(200,200,200,0.3);top:0;left:0; z-index:9\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.settingsItem{\n\t\t\t\t\t\t\t\t\t\t\tfont-size:18px;list-style:katakana-iroha outside;padding:2px;color:#2e2345;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.settingsItem input{\n\t\t\t\t\t\t\t\t\t\t\ttransform: scale(1.2);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.settingsMain{\n\t\t\t\t\t\t\t\t\t\t\tborder:solid 1px black;position:fixed;background-color:rgb(200,200,200);left:40%;top:20%;margin-bottom:0; z-index:10\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.closeIcon{\n\t\t\t\t\t\t\t\t\t\t\tborder:solid 1px black;position:absolute;width:25px;height:25px;background-color:rgba(255,100,90,0.9); right:3px;top:3px; z-index:10\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.titleStyle{\n\t\t\t\t\t\t\t\t\t\t\tfont-size: 20px;padding: 12px 0px 9px 22px\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.tooltip-4F{\n\t\t\t\t\t\t\t\t\t\t\tz-index:9;padding:5px;border:1px solid black;background-color:white;word-wrap:break-word;display:none;position:absolute;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.help_icon{\n\t\t\t\t\t\t\t\t\t\t\theight:22.5px;margin:-4px 10px\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.footerStyle{\n\t\t\t\t\t\t\t\t\t\t\tpadding-left: 12px;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t.contentStyle{\n\t\t\t\t\t\t\t\t\t\t\tbackground-color:white;margin:0 0;padding:5px 25px;\n\t\t\t\t\t\t\t\t\t\t}";
2063 this.background_div.setAttribute('class', 'SettingsBackground');
2064 this.background_div.setAttribute('id', 'SettingsBackground');
2065 this.background_div.setAttribute('style', 'display:none');
2066 this.settings_div.setAttribute('class', 'settingsMain');
2067 this.settings_div.setAttribute('id', 'settingsWindow');
2068 this.settings_div.setAttribute('style', 'display:none;width:500px');
2069 this.close_link.setAttribute('href', 'javascript:void(0)');
2070 this.close_div.setAttribute('class', 'closeIcon');
2071 this.close_div.addEventListener('click', function (evt) { return _this.hideWindow(); });
2072 this.title_para.setAttribute('class', 'titleStyle');
2073 this.contents_div.setAttribute('class', 'contentStyle');
2074 this.end_para.setAttribute('class', 'footerStyle');
2075 this.ul_selection_start.setAttribute("ID", "selection_list");
2076 this.generateList(this.contents_div);
2078 SettingsWindow.prototype.generateList = function (head_node) {
2079 var _this = this;
2080 this.list_items.forEach(function (list_item, index) {
2081 var li = document.createElement('LI');
2082 li.setAttribute('class', 'settingsItem');
2083 if (list_item.Text.indexOf('View') > -1) {
2084 var input = document.createElement('INPUT');
2085 var input_id = 'check-settings' + index;
2086 input.setAttribute('TYPE', 'checkbox');
2087 input.setAttribute('ID', 'check-settings' + index);
2088 li.appendChild(input);
2089 input.addEventListener('click', function (evt) { return _this.storeActiveToggles(); });
2090 var a = document.createElement('A');
2091 a.setAttribute('href', 'javascript:void(0)');
2092 a.textContent = list_item.Text;
2093 var a_id = 'tab-settings' + index;
2094 a.setAttribute('ID', 'tab-settings' + index);
2095 var setup_func = function (_a_id) {
2096 a.addEventListener('click', function (evt) { return list_item.ListenerFunc(_a_id); });
2097 li.appendChild(a);
2098 _this.ul_selection_start.appendChild(li);
2100 setup_func(a_id);
2102 else {
2103 var input = document.createElement('INPUT');
2104 var input_id = 'check-settings' + index;
2105 input.setAttribute('TYPE', 'checkbox');
2106 input.setAttribute('ID', 'check-settings' + index);
2107 input.addEventListener('click', function (evt) { return _this.storeActiveToggles(); });
2108 var label = document.createElement('LABEL');
2109 label.appendChild(input);
2110 var label_text = document.createTextNode(list_item.Text);
2111 label.appendChild(label_text);
2112 li.appendChild(label);
2113 _this.ul_selection_start.appendChild(li);
2114 input.checked = _this.setting_items.password_settings == 'true';
2115 var setup_func = function (input_id) {
2116 label.addEventListener('click', function (evt) { return list_item.ListenerFunc(input_id); });
2118 setup_func(input_id);
2122 SettingsWindow.prototype.activate = function () {
2123 var _this = this;
2124 document.body.appendChild(this.settings_style);
2125 this.background_div.addEventListener('click', function (evt) { return _this.hideWindow(); });
2126 document.body.appendChild(this.background_div);
2127 this.settings_div.appendChild(this.close_link);
2128 this.close_link.appendChild(this.close_div);
2129 this.title_para.appendChild(this.title_text);
2130 this.settings_div.appendChild(this.title_para);
2131 this.settings_div.appendChild(this.contents_div);
2132 this.contents_div.appendChild(this.ul_selection_start);
2133 this.end_para.appendChild(this.end_text);
2134 this.settings_div.appendChild(this.end_para);
2135 document.body.appendChild(this.settings_div);
2136 this.retrieveActiveToggles();
2138 SettingsWindow.prototype.decideAction = function (node) { };
2139 SettingsWindow.prototype.getSettingsArr = function () {
2140 return this.setting_items;
2142 SettingsWindow.prototype.displayWindow = function () {
2143 this.background_div.style.display = 'block';
2144 this.settings_div.style.display = 'block';
2145 this.rebuildContainer();
2147 SettingsWindow.prototype.hideWindow = function () {
2148 this.background_div.style.display = 'none';
2149 this.settings_div.style.display = 'none';
2150 this.clearContainer();
2152 SettingsWindow.prototype.filterWindow = function (disposable_container) {
2153 var _this = this;
2154 var filter_table = document.createElement("table");
2155 filter_table.setAttribute("style", "text-align:center;");
2156 filter_table.setAttribute("id", "filter_table");
2157 disposable_container.appendChild(filter_table);
2158 var top_row = document.createElement("TR");
2159 filter_table.appendChild(top_row);
2160 var table_head_active = document.createElement("th");
2161 top_row.appendChild(table_head_active);
2162 var head_text_active = document.createTextNode("Active");
2163 table_head_active.appendChild(head_text_active);
2164 var table_head_pattern = document.createElement("th");
2165 top_row.appendChild(table_head_pattern);
2166 var headTextPattern = document.createTextNode("Pattern");
2167 table_head_pattern.appendChild(headTextPattern);
2168 var table_head_replacement = document.createElement("th");
2169 top_row.appendChild(table_head_replacement);
2170 var head_text_replacement = document.createTextNode("Replacement");
2171 table_head_replacement.appendChild(head_text_replacement);
2172 //Create the pattern table
2173 //loop to create rows
2174 var Number_of_Filters = parseInt(this.setting_items.word_replace_settings.Number_of_Filters);
2175 console.log(Number_of_Filters);
2176 if (Number_of_Filters === 0 || isNaN(Number_of_Filters))
2177 Number_of_Filters = 6;
2178 for (var i = 0; i < Number_of_Filters; i++) {
2179 var table_row_contents = document.createElement("tr");
2180 table_row_contents.setAttribute("id", "FilterRow" + i);
2181 var table_data_active = document.createElement("td");
2182 var table_checkbox_active = document.createElement("input");
2183 table_checkbox_active.setAttribute("type", "checkbox");
2184 table_checkbox_active.setAttribute("id", "Active" + i);
2185 table_data_active.appendChild(table_checkbox_active);
2186 table_row_contents.appendChild(table_data_active);
2187 var table_data_pattern = document.createElement("td");
2188 var table_input_pattern = document.createElement("input");
2189 table_input_pattern.setAttribute("class", "inputs");
2190 table_input_pattern.setAttribute("id", "Pattern" + i);
2191 table_data_pattern.appendChild(table_input_pattern);
2192 table_row_contents.appendChild(table_data_pattern);
2193 var table_data_replacement = document.createElement("td");
2194 var table_input_replacement = document.createElement("input");
2195 table_input_replacement.setAttribute("class", "inputs");
2196 table_input_replacement.setAttribute("id", "Replacement" + i);
2197 table_data_replacement.appendChild(table_input_replacement);
2198 table_row_contents.appendChild(table_data_replacement);
2199 filter_table.appendChild(table_row_contents);
2201 var table_last_contents = document.createElement("tr");
2202 var table_add_collumn = document.createElement("td");
2203 var table_add_row_button = document.createElement("input");
2204 var table_subtract_row_button = document.createElement("input");
2205 table_subtract_row_button.setAttribute("type", "button");
2206 table_subtract_row_button.setAttribute("value", "-");
2207 table_subtract_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2208 table_add_collumn.appendChild(table_subtract_row_button);
2209 table_subtract_row_button.addEventListener("click", function (evt) { return _this.filterRemoveRow(); });
2210 table_add_row_button.setAttribute("type", "button");
2211 table_add_row_button.setAttribute("value", "+");
2212 table_add_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2213 table_add_collumn.appendChild(table_add_row_button);
2214 table_add_row_button.addEventListener("click", function (evt) { return _this.filterAddRow(); });
2215 table_last_contents.appendChild(table_add_collumn);
2216 var table_set_collumn = document.createElement("td");
2217 var table_confirm_button = document.createElement("input");
2218 table_confirm_button.setAttribute("type", "button");
2219 table_confirm_button.setAttribute("id", "table_confirm_button");
2220 table_confirm_button.setAttribute("value", "Set Replacements");
2221 table_confirm_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2222 //event listeners
2223 table_confirm_button.addEventListener("click", function (evt) {
2224 _this.storeStates();
2225 _this.clearContainer();
2226 _this.rebuildContainer();
2228 table_set_collumn.appendChild(table_confirm_button);
2229 table_last_contents.appendChild(table_set_collumn);
2230 var table_close_collumn = document.createElement("td");
2231 var table_close_button = document.createElement("input");
2232 table_close_button.setAttribute("type", "button");
2233 table_close_button.setAttribute("value", "Close Without Saving");
2234 table_close_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2235 table_close_button.addEventListener("click", function (evt) {
2236 _this.clearContainer();
2237 _this.rebuildContainer();
2239 table_close_collumn.appendChild(table_close_button);
2240 table_last_contents.appendChild(table_close_collumn);
2241 filter_table.appendChild(table_last_contents);
2243 SettingsWindow.prototype.filterAddRow = function () {
2244 var _this = this;
2245 var filter_table = document.getElementById("filter_table");
2246 var Number_of_Filters = 0;
2247 var filter_children = document.getElementById("filter_table").firstChild;
2248 while (filter_children.nextSibling) {
2249 filter_children = filter_children.nextSibling;
2250 Number_of_Filters++;
2252 var table_row_contents = document.createElement("tr");
2253 table_row_contents.setAttribute("id", "FilterRow" + (Number_of_Filters - 1));
2254 filter_table.removeChild(filter_children);
2255 var table_data_active = document.createElement("td");
2256 var table_checkbox_active = document.createElement("input");
2257 table_checkbox_active.setAttribute("type", "checkbox");
2258 table_checkbox_active.setAttribute("id", "Active" + (Number_of_Filters - 1));
2259 table_data_active.appendChild(table_checkbox_active);
2260 table_row_contents.appendChild(table_data_active);
2261 var table_data_pattern = document.createElement("td");
2262 var table_input_pattern = document.createElement("input");
2263 table_input_pattern.setAttribute("class", "inputs");
2264 table_input_pattern.setAttribute("id", "Pattern" + (Number_of_Filters - 1));
2265 table_data_pattern.appendChild(table_input_pattern);
2266 table_row_contents.appendChild(table_data_pattern);
2267 var table_data_replacement = document.createElement("td");
2268 var table_input_replacement = document.createElement("input");
2269 table_input_replacement.setAttribute("class", "inputs");
2270 table_input_replacement.setAttribute("id", "Replacement" + (Number_of_Filters - 1));
2271 table_data_replacement.appendChild(table_input_replacement);
2272 table_row_contents.appendChild(table_data_replacement);
2273 filter_table.appendChild(table_row_contents);
2274 var table_last_contents = document.createElement("tr");
2275 var table_add_collumn = document.createElement("td");
2276 var table_add_row_button = document.createElement("input");
2277 var table_subtract_row_button = document.createElement("input");
2278 table_subtract_row_button.setAttribute("type", "button");
2279 table_subtract_row_button.setAttribute("value", "-");
2280 table_subtract_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2281 table_add_collumn.appendChild(table_subtract_row_button);
2282 table_subtract_row_button.addEventListener("click", function (evt) { return _this.filterRemoveRow(); });
2283 table_add_row_button.setAttribute("type", "button");
2284 table_add_row_button.setAttribute("value", "+");
2285 table_add_row_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2286 table_add_collumn.appendChild(table_add_row_button);
2287 table_add_row_button.addEventListener("click", function (evt) { return _this.filterAddRow(); });
2288 table_last_contents.appendChild(table_add_collumn);
2289 var table_set_collumn = document.createElement("td");
2290 var table_confirm_button = document.createElement("input");
2291 table_confirm_button.setAttribute("type", "button");
2292 table_confirm_button.setAttribute("id", "table_confirm_button");
2293 table_confirm_button.setAttribute("value", "Set Replacements");
2294 table_confirm_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2295 //event listeners
2296 table_confirm_button.addEventListener("click", function (evt) {
2297 _this.storeStates();
2298 _this.clearContainer();
2299 _this.rebuildContainer();
2301 table_set_collumn.appendChild(table_confirm_button);
2302 table_last_contents.appendChild(table_set_collumn);
2303 var table_close_collumn = document.createElement("td");
2304 var table_close_button = document.createElement("input");
2305 table_close_button.setAttribute("type", "button");
2306 table_close_button.setAttribute("value", "Close Without Saving");
2307 table_close_button.setAttribute("style", "padding: 7px 0; margin:5px 0;");
2308 table_close_button.addEventListener("click", function (evt) {
2309 _this.clearContainer();
2310 _this.rebuildContainer();
2312 table_close_collumn.appendChild(table_close_button);
2313 table_last_contents.appendChild(table_close_collumn);
2314 filter_table.appendChild(table_last_contents);
2316 SettingsWindow.prototype.filterRemoveRow = function () {
2317 var filter_table = document.getElementById("filter_table");
2318 var Number_of_Filters = 0;
2319 var filter_children = document.getElementById("filter_table").firstChild;
2320 while (filter_children.nextSibling) {
2321 filter_children = filter_children.nextSibling;
2322 Number_of_Filters++;
2324 if (Number_of_Filters != 2) {
2325 filter_table.deleteRow(--Number_of_Filters);
2328 SettingsWindow.prototype.filterSetTable = function () {
2329 var filter_length = this.setting_items.word_replace_settings.Number_of_Filters;
2330 for (var filter_count = 0; filter_count < filter_length; filter_count++) {
2331 if (this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Active === null ||
2332 this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Regex === null ||
2333 this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Replacement === null)
2334 return;
2335 if (this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Active === "true") {
2336 document.getElementById("Active" + filter_count).checked = true;
2338 else {
2339 document.getElementById("Active" + filter_count).checked = false;
2341 document.getElementById("Pattern" + filter_count).value =
2342 this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Regex;
2343 document.getElementById("Replacement" + filter_count).value =
2344 this.setting_items.word_replace_settings.Text_Filter_List[filter_count].Replacement;
2347 return SettingsWindow;
2348 }(FeatureInterface));
2349 var Main = /** @class */ (function (_super) {
2350 __extends(Main, _super);
2351 function Main() {
2352 var _this = _super.call(this) || this;
2353 _this.features = {}; /*;any bypasses dot notation issues on objects*/
2354 _this.settings = {};
2355 if (!Generics.storageAvailable('localStorage')) {
2356 alert("4F-FSE: local storage error");
2357 return _this;
2359 else
2360 _this.activate();
2361 _this.retrieveStates();
2362 _this.init();
2363 _this.decideAction(document.getElementById('delform'));
2364 _this.observeEvents();
2365 return _this;
2367 Main.prototype.retrieveStates = function () {
2368 var top_bar = new TopBar();
2369 top_bar.build();
2370 this.settings = top_bar.getSettingsArr();
2372 Main.prototype.init = function () {
2373 if (this.settings.image_hiding_settings.Active === "true") {
2374 this.features.image_hider = new ImageHider();
2376 if (this.settings.word_replace_settings.Active === "true") {
2377 this.features.text_replacer = new TextReplacer();
2379 if (this.settings.image_adder_settings.Active === "true") {
2380 this.features.danbooru_image_adder = new DanbooruImageAdder();
2382 if (this.settings.thread_rebuild_settings.Active === "true") {
2383 this.features.thread_rebuilder = new ThreadRebuilder();
2385 if (this.settings.character_inserter_settings.Yen_Active === "true" || this.settings.character_inserter_settings.Kita_Active === "true") {
2386 this.features.character_inserter = new CharacterInserter(this.settings.character_inserter_settings.Yen_Active === "true", this.settings.character_inserter_settings.Kita_Active === "true");
2388 if (this.settings.password_settings == 'true') {
2389 this.features.password_viewer = new PasswordViewer();
2391 for (var feature_key in this.features)
2392 this.features[feature_key].retrieveStates();
2394 Main.prototype.activate = function () { console.log("4F-FSE Starting"); };
2395 Main.prototype.storeStates = function () { };
2396 Main.prototype.observeEvents = function () {
2397 var _this = this;
2398 var document_changes = new MutationObserver(function (mutations) {
2399 mutations.forEach(function (mutation) {
2400 [].forEach.call(mutation.addedNodes, function (node) { return _this.decideAction(node); });
2402 }).observe(document.body, { childList: true, subtree: true });
2404 Main.prototype.decideAction = function (node) {
2405 if (node == undefined || node.tagName == undefined)
2406 return;
2407 var start = node;
2408 var itterator = document.createNodeIterator(start, NodeFilter.SHOW_ELEMENT);
2409 var node;
2410 while ((node = itterator.nextNode())) {
2411 if (node.tagName !== "BLOCKQUOTE" && node.tagName !== "IMG" && node.tagName !== "VIDEO")
2412 continue;
2413 for (var feature_key in this.features) {
2414 this.features[feature_key].decideAction(node);
2418 return Main;
2419 }(FeatureInterface));
2420 document.addEventListener('4chanXInitFinished', function () { new Main(); });