f95zone watched filter

f95zone filter only the watched threads.

Versión del día 08/09/2024. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name        f95zone watched filter
// @namespace   f95zone watched filter
// @description f95zone filter only the watched threads.
// @author       C. Gauthier
// @license     MIT
// @icon        https://www.google.com/s2/favicons?domain=f95zone.to
// @match       https://f95zone.to/sam/latest_alpha/
// @version     1.0.0
// @require     https://cdn.jsdelivr.net/combine/npm/@violentmonkey/dom@2,npm/@violentmonkey/[email protected]
// @require     https://cdn.jsdelivr.net/npm/@violentmonkey/dom@2/dist/solid.js
// @require     https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js
// @require     https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js
// @grant       GM_addStyle
// @grant       GM_getValue
// @grant       GM_setValue
// ==/UserScript==

(function (web, lodash, solidJs) {
    'use strict';
    $(function(b) {
        var css_248z$1 = ".customTags{border-radius:2px;box-shadow:0 0 0 0 transparent,0 1px 1px 0 rgba(0,0,0,.15),0 1px 2px 0 rgba(0,0,0,.15);display:inline-block;font-size:.8em;line-height:1.8em;margin:4px 4px 0 0;padding:0 6px;text-shadow:1px 1px 2px rgba(0,0,0,.75)}.selected-tags-wrap span:hover{background-color:#ba4545}.selected-tags-wrap span{background-color:#181a1d;border-radius:3px;cursor:pointer;display:inline-block;font-size:.9em;line-height:24px;margin:4px 4px 0 0;padding:0 7px;transition:.2s}.input-tag{left:0;opacity:1;position:relative;width:127px}.border-gradient{border:3px solid;border-image-slice:1}.flxgrow{flex-grow:1}.solid-select-multi-value{background-color:#181a1d;border-radius:3px;display:inline-block;font-size:.9em;gap:5px;line-height:24px;margin:4px 4px 0 0;padding:0 7px;transition:.2s}.solid-select-multi-value-remove{background-color:#ba4545;background-color:#953737;border:none;border-radius:2px;cursor:pointer}.solid-select-list{background:#181a1b;z-index:2}.select-likes.select-likes{border:1px solid grey;margin-bottom:5px;padding:5px}";

        var css_248z = ".solid-select-container[data-disabled=true]{pointer-events:none}.solid-select-container{position:relative}.solid-select-control[data-disabled=true]{--tw-bg-opacity:1;--tw-border-opacity:1;background-color:rgba(243,244,246,var(--tw-bg-opacity));border-color:rgba(209,213,219,var(--tw-border-opacity))}.solid-select-control{--tw-border-opacity:1;border-color:rgba(229,231,235,var(--tw-border-opacity));border-radius:.25rem;border-width:1px;display:-ms-grid;display:grid;grid-template-columns:repeat(1,minmax(0,1fr));line-height:1.5;padding:.25rem .5rem}.solid-select-control[data-multiple=true][data-has-value=true]{-webkit-box-align:stretch;-ms-flex-align:stretch;grid-gap:.25rem;-webkit-align-items:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;gap:.25rem}.solid-select-control:focus-within{--tw-outline-opacity:1;outline-color:rgba(209,213,219,var(--tw-outline-opacity))}.solid-select-placeholder{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity))}.solid-select-placeholder,.solid-select-single-value{grid-column-start:1;grid-row-start:1}.solid-select-multi-value{--tw-bg-opacity:1;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;background-color:rgba(243,244,246,var(--tw-bg-opacity));border-radius:.25rem;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;font-size:85%;line-height:1;line-height:inherit;padding-left:4px;padding-right:4px}.solid-select-multi-value-remove{padding-left:.25rem;padding-right:.25rem}.solid-select-multi-value-remove:hover{text-shadow:1px 1px 3px rgba(0,0,0,.29),2px 4px 7px rgba(73,64,125,.35)}.solid-select-input{-webkit-box-flex:1;background-color:initial;border-width:0;caret-color:transparent;-ms-flex:1 1 0%;-webkit-flex:1 1 0%;flex:1 1 0%;font:inherit;grid-column-start:1;grid-row-start:1;margin:0;outline:2px solid transparent;outline-offset:2px;padding:0}.solid-select-input:read-only{cursor:default}.solid-select-input[data-is-active=true],.solid-select-input[data-multiple=true]{caret-color:currentColor}.solid-select-list{--tw-shadow:0 10px 15px -3px rgb(0 0 0/0.1),0 4px 6px -4px rgb(0 0 0/0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);background-color:inherit;border-radius:.125rem;-webkit-box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);margin-top:.25rem;max-height:50vh;min-width:100%;overflow-y:auto;padding:.5rem;position:absolute;white-space:nowrap;z-index:1}.solid-select-option:hover{--tw-bg-opacity:1;background-color:rgba(229,231,235,var(--tw-bg-opacity))}.solid-select-option[data-focused=true]{--tw-bg-opacity:1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.solid-select-option>mark{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgba(unset,var(--tw-bg-opacity));color:rgba(unset,var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline}.solid-select-option{cursor:default;padding:.5rem 1rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.solid-select-option[data-disabled=true]{--tw-text-opacity:1;color:rgba(156,163,175,var(--tw-text-opacity));pointer-events:none}.solid-select-list-placeholder{cursor:default;padding:.5rem 1rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}";
        var SelectCss = css_248z;


        var thread_data = GM_getValue('thread_data', []);
        var test = [];


        console.log(GM_getValue("thread_data", []));
        //GM_setValue("thread_data", []);


        // ==/ajaxSetup==
        b.ajaxSetup({
            method: "GET",
            cache: !1,
            dataType: "json",
            timeout: 1E4
        });

        //var redirectXHR = GM_getValue('watchedFilter', false);

        // Save the original send method
        const originalSend = XMLHttpRequest.prototype.send;

        // Override the send method
        XMLHttpRequest.prototype.send = function(body) {
            // Store the reference to the current XHR object
            const xhr = this;
            //console.log('ready to intercept request to:', xhr.responseURL);

            // Attach an event listener to capture the response
            xhr.addEventListener('readystatechange', function() {
                if (xhr.readyState === XMLHttpRequest.DONE && xhr.responseURL.includes('latest_data.php?cmd=list') && GM_getValue('watchedFilter', false)) {

                    // Here you can modify the response before it's processed by the application
                    const filtered = filterThreadData(xhr.responseURL);
                    const threads = filtered[0];
                    const searchParams = new URLSearchParams(xhr.responseURL); const page = Number(searchParams.get("page"));
                    const pTotal = filtered[1];
                    const count = filtered[2];
                    let customData = JSON.stringify({ "status": "ok", "msg": { "data": threads, "pagination": { "page": page, "total": pTotal }, "count": count }}); // Your custom JSON data

                    // Override the responseText property to return your custom data
                    Object.defineProperty(xhr, 'responseText', { value: customData });
                }
            });

            // Call the original send method to continue with the request
            originalSend.apply(this, arguments);
        };

        function sortArrayByKey(arr, key, ascending = false) {
            return arr.sort((a, b) => {
                if (typeof a[key] === 'string') {
                    return ascending ? a[key].localeCompare(b[key]) : b[key].localeCompare(a[key]);
                } else {
                    return ascending ? a[key] - b[key] : b[key] - a[key];
                }
            });
        }

        function calculateWeightedRating(threads, m = 3.5, C = 100000) {
            // C is the minimum number of views required to be considered
            // m is the average rating across all threads

            m = threads.reduce((accumulator, currentValue) => accumulator + currentValue.rating, 0,)/threads.length;

            return threads.map(thread => {
                const { rating, views } = thread;

                // Calculate the weighted rating using the Bayesian formula
                const weightedRating = (views*rating + m*C) / (views+C)
                //console.log(thread.title, "weightedRating :", weightedRating);

                return {
                    ...thread,
                    weightedRating: weightedRating.toFixed(2) // round to 2 decimal places
                };
            });
        }

        function filterThreadData(url){
            var tmp_thread_data = GM_getValue('thread_data', []);
            //var tmp_thread_data = thread_data.map((x) => x);
            const searchParams = new URLSearchParams(url);

            //sort
            if(searchParams.has("sort")){
                let key = searchParams.get("sort"); let ascending = key == "title";
                switch(searchParams.get("sort")) {
                    case "date":
                        break;
                    case "rating":
                        tmp_thread_data = calculateWeightedRating(tmp_thread_data);
                        console.log(thread_data);
                        console.log(tmp_thread_data[0].title, "date :", tmp_thread_data[0].date, "weightedRating :", tmp_thread_data[0].weightedRating);
                        sortArrayByKey(tmp_thread_data, "weightedRating", ascending);
                        break;
                    default:
                        sortArrayByKey(tmp_thread_data, key, ascending);
                }
                /*let key = searchParams.get("sort"); var ascending = key == "title";
                sortArrayByKey(tmp_thread_data, key, ascending);*/
            }

            //date
            if(searchParams.has("date")){
                let key = Number(searchParams.get("date"));
                //console.log("data :", tmp_thread_data);
                tmp_thread_data = tmp_thread_data.filter(thread => {
                    const timeDifference = new Date() - new Date(thread.date);
                    const daysDifference = timeDifference / (1000 * 60 * 60 * 24);
                    return daysDifference < key
                });
                //tmp_thread_data = tmp_thread_data.filter(thread => thread.date.includes(key));
            }

            //tags (and/or)
            if(searchParams.has("tags[]")){
                let key = searchParams.getAll("tags[]").map(Number);
                tmp_thread_data = tmp_thread_data.filter(thread => {
                    if(searchParams.has("tagtype")){
                        // Return true if at least one of the tags in key is found in the thread's tags array
                        return key.some(tag => thread.tags.includes(tag));
                    }else{
                        // Check if every tag in keys is present in item.tags
                        return key.every(tag => thread.tags.includes(tag));
                    }
                });
            }

            //notags
            if(searchParams.has("notags[]")){
                let key = searchParams.getAll("notags[]").map(Number);
                tmp_thread_data = tmp_thread_data.filter(thread => {
                    // Return true if none of thetags in key are found in the thread's tags array
                    return !key.some(tag => thread.tags.includes(tag));
                });
            }

            //prefixes
            if(searchParams.has("prefixes[]")){
                let key = searchParams.getAll("prefixes[]").map(Number);
                tmp_thread_data = tmp_thread_data.filter(thread => {
                    // Return true if all of the prefixes in key are found in the thread's prefixes array
                    return key.every(tag => thread.prefixes.includes(tag));
                });
            }

            //noprefixes
            if(searchParams.has("noprefixes[]")){
                let key = searchParams.getAll("noprefixes[]").map(Number);
                tmp_thread_data = tmp_thread_data.filter(thread => {
                    // Return true if none of the prefixes in key are found in the thread's prefixes array
                    return !key.some(tag => thread.prefixes.includes(tag));
                });
            }

            //search
            if(searchParams.has("search")){
                let key = searchParams.get("search").toLowerCase();
                tmp_thread_data = tmp_thread_data.filter(thread => thread.title.toLowerCase().includes(key));
            }

            //creator
            if(searchParams.has("creator")){
                let key = searchParams.get("creator").toLowerCase();
                tmp_thread_data = tmp_thread_data.filter(thread => thread.creator.toLowerCase().includes(key));
            }

            //page and rows
            let page = [];
            let rows = 30; if(searchParams.has("rows")){rows = Number(searchParams.get("rows"));}
            if(searchParams.has("page")){
                let key = Number(searchParams.get("page"));
                for(let id = rows*(key-1); id < Math.min(rows*key, tmp_thread_data.length); id++){
                    page.push(tmp_thread_data[id]);
                }
            }

            //Date() to String ( Date() => "x mins / hrs / days / weeks / months / years" )
            //console.log(page);
            page.forEach(thread => {
                let d = timeSince(Date.parse(thread.date));
                thread.date = String(d[0]) + " "+ d[1];
            });


            return [page, Math.ceil(tmp_thread_data.length/rows), tmp_thread_data.length];
        }



        function subtractTime(date, input) {
            const [amount, unit] = (() => {
                const parts = input.split(' ');
                if (parts.length === 2) {
                    return [parseInt(parts[0]), parts[1]];
                } else if (input.toLowerCase() === "yesterday") {
                    return [1, "days"];
                } else {
                    return [null, null];
                }
            })();

            if (amount === null || unit === null) {
                return date;
            }

            const newDate = new Date(date);

            switch (unit) {
                case 'min':
                case 'mins':
                    newDate.setMinutes(newDate.getMinutes() - amount);
                    break;
                case 'hr':
                case 'hrs':
                    newDate.setHours(newDate.getHours() - amount);
                    break;
                case 'days':
                    newDate.setDate(newDate.getDate() - amount);
                    break;
                case 'week':
                case 'weeks':
                    newDate.setDate(newDate.getDate() - (amount * 7));
                    break;
                case 'month':
                case 'months':
                    newDate.setMonth(newDate.getMonth() - amount);
                    break;
                case 'year':
                case 'years':
                    newDate.setFullYear(newDate.getFullYear() - amount);
                    break;
                default:
                    throw new Error('Invalid time unit');
            }

            return newDate;
        }

        function timeSince(date) {
            const now = new Date();
            const diffInMs = now - date;

            const minutes = Math.floor(diffInMs / (1000 * 60));
            const hours = Math.floor(diffInMs / (1000 * 60 * 60));
            const days = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
            const weeks = Math.floor(days / 7);
            const months = Math.floor(days / 30);
            const years = Math.floor(days / 365);

            if (minutes < 1) {
                return [0, "min"];
            } else if (minutes === 1) {
                return [1, "min"];
            } else if (minutes < 60) {
                return [minutes, "mins"];
            } else if (hours === 1) {
                return [1, "hr"];
            } else if (hours < 24) {
                return [hours, "hrs"];
            } else if (days === 1) {
                return ["", "yesterday"];
            } else if (days < 7) {
                return [days, "days"];
            } else if (weeks === 1) {
                return [1, "week"];
            } else if (weeks < 4) {
                return [weeks, "weeks"];
            } else if (months === 1) {
                return [1, "month"];
            } else if (months < 12) {
                return [months, "months"];
            } else if (years === 1) {
                return [1, "year"];
            } else {
                return [years, "years"];
            }
        }

        function splitString(input) {
            const parts = input.split(' ');

            if (parts.length === 2) {
                if(parts[1] == "hours"){return [parts[0], "hrs"];}
                return [parts[0], parts[1]];
            } else {
                return ["", parts[0]];
            }
        }

        function uniqByKeepFirst(data, key) {
            const seen = new Set();
            return data.filter(obj => {
                const keyValue = obj[key];
                if (seen.has(keyValue)) {
                    return false;
                } else {
                    seen.add(keyValue);
                    return true;
                }
            });
        }



        const prefixes = {"23":{"id":23,"name":"SiteRip","class":"label--lightGreen"},"19":{"id":19,"name":"Collection","class":"label--gray"},"13":{"id":13,"name":"VN","class":"label--red"},"14":{"id":14,"name":"Others","class":"label--lightGreen"},"5":{"id":5,"name":"RAGS","class":"label--orange"},"2":{"id":2,"name":"RPGM","class":"label--blue"},"47":{"id":47,"name":"WebGL","class":"pre-webgl"},"3":{"id":3,"name":"Unity","class":"pre-unity"},"4":{"id":4,"name":"HTML","class":"label--olive"},"1":{"id":1,"name":"QSP","class":"label--red"},"6":{"id":6,"name":"Java","class":"pre-java"},"7":{"id":7,"name":"Ren\u0026#039;Py","class":"pre-renpy"},"31":{"id":31,"name":"UnrealEngine","class":"label--royalBlue"},"30":{"id":30,"name":"WolfRPG","class":"label--green"},"8":{"id":8,"name":"Flash","class":"label--gray"},"12":{"id":12,"name":"ADRIFT","class":"label--blue"},"17":{"id":17,"name":"Tads","class":"label--blue"},"18":{"id":18,"name":"Completed","class":"label--blue"},"20":{"id":20,"name":"Onhold","class":"label--skyBlue"},"22":{"id":22,"name":"Abandoned","class":"label--orange"}};



        function MarkFilter() {
            const isChecked = GM_getValue('watchedFilter', false);

            //console.log(isChecked, typeof isChecked);
            /*for (let i = 0; i < element.length; i++) {
                if (isChecked) {
                    element[i].setAttribute('isOriginal', 'true');
                }else{
                    if(element[i].getAttribute('isOriginal') === 'false'){
                        element[i].remove();
                        //i--;
                    }else{
                        element[i].setAttribute('isOriginal', 'false');
                    }
                }
            }
            if(isChecked){AlternateFilter(); } */
        }


        /*
        function AlternateFilter(){
            const element = document.querySelectorAll('.resource-tile');
            const data = GM_getValue("thread_data",[]);
            const parent = document.querySelector('.grid-selected');

            for(var i = 0; i < Math.max(data.length, 300); i++){
                const e = data[i];
                if(e.watched == true){
                    const newDiv = document.createElement("div");

                    var views = e.views;
                    if (999 < e.views && e.views <= 999999) {views = String(Math.floor(e.views/1000)); if(views.length==1){views+="."+String(Math.floor(e.views/100)-Number(views)*10);} views+="K";}
                    else if (e.views > 999999) {views = String(Math.floor(e.views/1000000)); if(views.length==1){views+="."+String(Math.floor(e.views/100000)-Number(views)*10);} views+="M";}

                    var ratingStars = Math.floor(e.rating/5*100); //the % of the 5 rating stars of the thread needing to be filled

                    var tags = e.tags[0]; for(var j0 = 1; j0 < e.tags.length; j0++){tags += "," + e.tags[j0];} //the list of tags of the thread

                    var images = e.screens[0]; for(var j1 = 1; j1 < e.screens.length; j1++){images += "," + e.screens[j1];} //the urls of preview pictures of the thread

                    var eDate = Date.parse(e.date); //the aproximate date since creation of the thread
                    var date_type = timeSince(eDate)[1];
                    var date = String(timeSince(eDate)[0]);


                    var p = e.prefixes;
                    var prefixes_left = ''; var prefixes_right = '';
                    p.forEach((id) => {
                        var temp = '<div class="'+prefixes[id]["class"]+'">'+prefixes[id]["name"]+'</div>';
                        if(id == 18 || id == 20 || id == 22){
                            prefixes_right += temp;
                        }else{
                            prefixes_left += temp;
                            }
                    });


                    // Set the class attribute
                    newDiv.className = 'resource-tile resource-tile_update border-gradient';

                    // Set the style attribute (even if it's empty here)
                    newDiv.style.cssText = '';

                    // Set the custom data attributes
                    newDiv.setAttribute('data-thread-id', e.thread_id);
                    newDiv.setAttribute('data-tags', tags);
                    newDiv.setAttribute('data-images', images);

                    // Set the other attributes
                    newDiv.setAttribute('isdisplay', e.watched);
                    newDiv.setAttribute('isignore', e.ignored);
                    newDiv.setAttribute('isOriginal', 'false');

                    newDiv.innerHTML = '<a href="https://f95zone.to/threads/'+e.thread_id+'/" class="resource-tile_link" rel="noopener" target="_blank" title=""><div class="resource-tile_thumb-wrap"><div class="resource-tile_thumb" style="background-image:url('+e.cover+')"></div></div><div class="resource-tile_body" style="position: relative; top: auto; width: 100%; left: auto; height: auto;"><div class="resource-tile_label-wrap"><div class="resource-tile_label-wrap_left">'+prefixes_left+'</div><div class="resource-tile_label-wrap_right">'+prefixes_right+'<div class="resource-tile_label-version">'+e.version+'</div></div></div><div class="resource-tile_info"><header class="resource-tile_info-header"><div class="header_title-wrap"><h2 class="resource-tile_info-header_title" style="text-overflow: ellipsis; text-indent: 0px; transition: text-indent 0.2s linear;">'+e.title+'</h2></div><div class="header_title-ver">'+e.version+'</div><div class="resource-tile_dev fas fa-user">'+e.creator+'</div></header><div class="resource-tile_info-meta"><div class="resource-tile_info-meta_time"><span class="tile-date_'+date_type+'">'+date+'</span></div><div class="resource-tile_info-meta_likes">'+e.likes+'</div><div class="resource-tile_info-meta_views">'+views+'</div><div class="resource-tile_info-meta_rating">'+e.rating+'</div><div class="resource-tile_rating"><span style="width:'+ratingStars+'%"></span></div></div></div></div></a>'
                    parent.appendChild(newDiv);
                }

            };
        }
        */

        async function getPagesData(){


            function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
            var page_number = GM_getValue('pages_to_filter', 1);
            console.log("data is loading, pages searched : " + page_number);
            //page_number = document.querySelector("#sub-nav_inner > div.sub-nav_paging > div").lastChild.getAttribute("data-page");// need to find something else to not use the "item per page" slider
            //page_number = 1;

            // Create the overlay div
            var overlay = document.createElement('div');

            // Apply styles to the overlay div
            overlay.style.position = 'fixed'; overlay.style.top = '0';overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; //style
            overlay.style.zIndex = '9999'; // ensure it's on top of all other elements

            // Create the message element
            var message = document.createElement('div');
            message.innerText = 'Please wait, loading...'; // Your custom message
            message.style.color = 'white';message.style.fontSize = '24px';message.style.fontFamily = 'Arial, sans-serif';message.style.textAlign = 'center';message.style.padding = '20px';message.style.backgroundColor = 'rgba(0, 0, 0, 0.75)';message.style.borderRadius = '10px';

            // Append the message to the overlay
            overlay.appendChild(message);

            // Add the overlay to the document body
            document.body.appendChild(overlay);

            for (let i = 1; i <= page_number; i++) {
                console.log("page "+i+" ...");
                await b.ajax({
                    url: "latest_data.php?cmd=list&cat=games&page="+i+"&sort=date&rows=90&_=1710376207895", //only works if the "item per page" slider is on 90
                    success: function(f) {
                        f.msg.data.forEach(function(l) {if(l.watched){

                            var newDate = subtractTime(new Date(), l.date); // change the l.date string as a Date object aproximating the creation date instead of a string of the time since creation
                            l.date = String(newDate);

                            test.push(l);
                        }});
                    }
                });
            }

            if (overlay) {
                overlay.parentNode.removeChild(overlay);
            }
            var concat = test.concat(thread_data);
            thread_data = uniqByKeepFirst(concat, "thread_id");
            GM_setValue("thread_data", thread_data);
            await sleep(500);
            console.log("your watched threads data :", GM_getValue("thread_data", "data not found"));

        }

        function init() {
            const element = document.querySelectorAll('.resource-tile');
            const elementLength = element.length;
            if (element[0]) {
                for (let i = 0; i < 3; i++) {
                    MarkFilter();
                    const filtered = _.filter(document.querySelectorAll('.resource-tile'), e => {
                        return e.getAttribute('isDisplay') === 'true';
                    });
                    console.debug('Filtered', filtered);
                    if (filtered.length < elementLength) {
                        break;
                    }
                }
            } else {
                setTimeout(init, 100);
            }
        }

        const _tmpl$$7 = /*#__PURE__*/web.template(`<div class=filter-block><div class=filter-block_button-wrap><span class="filter-block_title flxgrow">Filter watched threads:</span><input type=checkbox id=filter-mark>`);
        function FilterMark() {
            const onChange = event => {
                GM_setValue('watchedFilter', event.target.checked);
                //window.location.reload();
                MarkFilter();
            };
            return (() => {
                const _el$ = _tmpl$$7(),
                      _el$2 = _el$.firstChild,
                      _el$3 = _el$2.firstChild,
                      _el$4 = _el$3.nextSibling;
                _el$2.style.setProperty("display", "flex");
                _el$4.addEventListener("change", onChange);
                web.effect(() => _el$4.checked = GM_getValue('watchedFilter', false));
                return _el$;
            })();
        }

        const _tmpl$$8 = /*#__PURE__*/web.template(`<div class=filter-block><div class=filter-block_button-wrap><span class="filter-block_title flxgrow">Thread scrapper:</span><input type="number" id="pages-to-filter" name="quantity" min="1" max="300"><input type=button id=get-pages value="get data">`);
        function GetPagesDataButton() {
            const onPages = event => {
                GM_setValue('pages_to_filter', event.target.value);
            };
            return (() => {
                const _el$ = _tmpl$$8(),
                      _el$2 = _el$.firstChild,
                      _el$3 = _el$2.firstChild,
                      _el$4 = _el$3.nextSibling,
                      _el$5 = _el$4.nextSibling;
                _el$2.style.setProperty("display", "flex");
                _el$4.addEventListener("change", onPages);
                _el$5.addEventListener("click", getPagesData);
                web.effect(() => _el$4.value = GM_getValue('pages_to_filter', 1));
                return _el$;
            })();
        }

        const _tmpl$ = /*#__PURE__*/web.template(`<style>`);
        function mainFilter() {
            solidJs.createEffect(() => {
                init();

                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                window.history.onpushstate = function () {
                    setTimeout(init, 200);
                };
                (function (history) {
                    const pushState = history.pushState;
                    history.pushState = function (state) {
                        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                        // @ts-ignore
                        if (typeof history.onpushstate === 'function') {
                            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                            // @ts-ignore
                            history.onpushstate({
                                state
                            });
                        }
                        return pushState.apply(history, arguments);
                    };
                })(window.history);
            }, [window.history]);
            return [web.createComponent(FilterMark, {}), web.createComponent(GetPagesDataButton, {}), (() => {
                const _el$ = _tmpl$();
                web.insert(_el$, SelectCss);
                return _el$;
            })(), (() => {
                const _el$2 = _tmpl$();
                web.insert(_el$2, css_248z$1);
                return _el$2;
            })()];
        }

        web.render(mainFilter, document.querySelector('.content-block_filter'));
    });

})(VM.solid.web, _, VM.solid);