Sleazy Fork is available in English.

98图片预览助手

浏览帖子列表时自动加载内部前三张(可配置)图片供预览。如需支持其他免翻地址,请使用@match自行添加连接,如果某个版块不希望预览,请使用@exclude自行添加要排除的版块链接

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name         98图片预览助手
// @namespace    98imgloader
// @version      1.7.1
// @description  浏览帖子列表时自动加载内部前三张(可配置)图片供预览。如需支持其他免翻地址,请使用@match自行添加连接,如果某个版块不希望预览,请使用@exclude自行添加要排除的版块链接
// @author       sehuatang_chen
// @license      MIT

// @match        https://www.sehuatang.org/*
// @match        https://www.sehuatang.net/*
// @match        https://rgkm7.cs33u.com/*
// @match        https://he2w0.0lr3i.com/*
// @match        https://https://vsgo.k3ut8.com/*

// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/jquery_lazyload/1.9.7/jquery.lazyload.min.js
// @require      https://greasyfork.org/scripts/475748-zip%E8%A7%A3%E5%8E%8B%E5%B7%A5%E5%85%B7/code/zip%E8%A7%A3%E5%8E%8B%E5%B7%A5%E5%85%B7.js
// @require      https://greasyfork.org/scripts/475896-115%E6%8E%A8%E9%80%81%E5%B7%A5%E5%85%B7/code/115%E6%8E%A8%E9%80%81%E5%B7%A5%E5%85%B7.js

// ==/UserScript==

/* global $ */
$(document).ready(() => {
    console.log("98imgloader ready")
    GM_script.init_styles();
    GM_script.init_variables();
    GM_script.add_config_menu();

    var url = window.location.href;
    if (/^.*forum\.php\?.*mod=forumdisplay.*$/g.test(url)){
        normalthread.init()
    } else if (/^.*home\.php\?.*do=favorite.*$/g.test(url)) {
        favorite.init()
    } else if (/^((?!type=reply).)*(home\.php\?.*do=thread)((?!type=reply).)*$/g.test(url)) {
        userspace.init()
    } else {
        console.log("url not matched.")
    }

});
const globalpage = {
    set_width: () => {
        if (GM_getValue("reset_width") == 1) {
            $(".wp").css("width",GM_getValue("reset_width_px") + "px")
            $("#nv").css("width",GM_getValue("reset_width_px") + "px")
        }
    }
}
const normalthread = {
    init: () => {
        normalthread.remove_ads();
        normalthread.add_one_key_btn();
        normalthread.add_column();
        globalpage.set_width();
        var $next_btn = $("#autopbn");
        $next_btn.on("click",function(){
            console.log("next_btn click!!!")
            //点击下一页后延迟page_thread_delayed秒再次触发图片加载。
            setTimeout(() => {
                normalthread.each_thread_list()
            }, parseInt(GM_getValue("page_thread_delayed")));
        });
        normalthread.each_thread_list();
    },
    add_one_key_btn: () => {
        var $load_img_btn = $("<a />");
        $load_img_btn.append($('<div>一键加载图片</div>'))
        $load_img_btn.on("click", function(){
            normalthread.each_thread_list(1)
        });
        $("#scrolltop").append($("<span />").append($load_img_btn));
        $load_img_btn.css("background","None");
        $load_img_btn.css("height","35px");
    },
    add_column: () => {
        $("#threadlist > div.th > table tr:eq(0)").append($('<td style="width:40px">操作</td>'))
    },
    remove_ads: () => {
        $("tbody[id*='stick']").remove();
        $("div.show-text2").parent().parent().parent().remove();
        $("tbody[id='separatorline']").remove();
    },
    each_thread_list: (isonekeyload) => {
        var count = 0
        var block_user = 0
        var hide = 0
        $("#threadlist table[id='threadlisttableid'] > tbody:not([id])").each(function(index) {
            var $_tbody=$(this);
            if ($_tbody.find('td[id^="noid_"]').length == 0) {
                $_tbody.find("tr").append($('<td id="noid_1_'+index+'" style="width:20px"></td>'));
                $_tbody.find("tr").append($('<td id="noid_2_'+index+'" style="width:20px"></td>'));
            }
        })
        $("#threadlist table[id='threadlisttableid'] > tbody[id*='normalthread']").each(function(index) {
            var $tbody=$(this);
            var thread_id = $tbody.attr("id").split("_")[1];
            var info_id = "info_" + thread_id;
            var load_btn_id = "load_" + thread_id;
            var rm_btn_id = "rm_" + thread_id;
            var black_btn_id = "black_" + thread_id;
            var $author_a = $tbody.find("td.by:eq(0) a")
            var userid = $author_a.attr("href").match(/(?<=uid=)\d*/g)[0];
            var username = $author_a.text()

            if (GM_getValue("author_control") == 1) {
                var arr = JSON.parse(GM_getValue("author_list"))
                if (arr.findIndex((user) => user["id"] == userid) >= 0) {
                    $tbody.remove();
                    $("#"+info_id).remove();
                    block_user++
                    return;
                }
            }

            var removed_ids = GM_getValue("removed_ids").split(",")
            var removed = removed_ids.includes(thread_id)
            if (removed) {
                if (GM_getValue("hideorgray") == "gray") {
                    $tbody.css("background-color", "rgb(197 179 179)")
                } else {
                    $tbody.remove();
                    $("#"+info_id).remove();
                    hide++
                    return ;
                }
            }

            if ($tbody.find("#"+black_btn_id).length == 0) {
                var $black_btn = $('<span title="7天内不看此作者" id="'+black_btn_id+'" uid="'+userid+'">'+imgs.hideuser_svg+'</span>')

                $black_btn.click(function(){
                    tools.add_user_id($(this).attr("uid"),username)
                    tools.tip("操作成功")
                })
                $author_a.after($black_btn)
            }

            if ($tbody.find("#"+load_btn_id).length == 0) {
                var $load_btn = $('<span title="查看帖内图片" >'+imgs.expand_svg+'</span>')
                $load_btn.on("click", function(){
                    normalthread.load_thread_info($tbody)
                })
                $tbody.find("tr").append($('<td id="'+load_btn_id+'" style="width:20px"></td>').append($load_btn))
            }

            if (GM_getValue("show_hide_btn") == 1 && $tbody.find("#"+rm_btn_id).length == 0) {
                var $rm_btn = $('<span title="隐藏此贴" >'+imgs.hide_svg+'</span>')
                $rm_btn.on("click", function(){
                    tools.add_removed_id(thread_id)
                    $tbody.remove();
                    $("#"+info_id).remove();
                })
                $tbody.find("tr").append($('<td id="'+rm_btn_id+'" style="width:20px"></td>').append($rm_btn));
            }

            if (GM_getValue("switch_autoload") == 1 || isonekeyload == 1) {
                if ($("#"+info_id).length == 0 && !removed) {
                    if (GM_getValue("load_thread_delayed") == 0) {
                        normalthread.load_thread_info($tbody)
                    } else {
                        count++;
                        setTimeout(() => {
                            normalthread.load_thread_info($tbody)
                        }, GM_getValue("load_thread_delayed") * count)
                    }
                }
            }
        })

        if (!isonekeyload) {
            if (GM_getValue("author_control") == 1 && GM_getValue("hideorgray") == "hide") {
                tools.tip(`已隐藏屏蔽用户帖子${block_user}条,隐藏标记帖子${hide}条`)
            }else if (GM_getValue("author_control") == 1) {
                tools.tip(`已隐藏屏蔽用户帖子${block_user}条`)
            }else if (GM_getValue("hideorgray") == "hide") {
                tools.tip(`已隐藏标记帖子${hide}条`)
            }
        }
    },
    load_thread_info: ($thread_tbody) => {
        var tbody_clone_id = "info_" + $thread_tbody.attr("id").split("_")[1];
        if ($("#"+tbody_clone_id).length != 0) {
            return ;
        }

        var $tbody_clone = $thread_tbody.clone();
        $tbody_clone.attr("id", tbody_clone_id);
        $tbody_clone.find("td,th").remove();
        var $tag_td = $('<td colspan="'+(GM_getValue("show_hide_btn") == 1 ? 7 : 6)+'"></td>');
        $tbody_clone.find("tr:eq(0)").append($tag_td);

        var url = "/" + $thread_tbody.find(".icn > a").attr("href");
        tools.request_and_parse_thread(url, $tag_td)
        $thread_tbody.after($tbody_clone);
    }
}

const favorite = {
    init: () => {
        favorite.add_one_key_btn();
        favorite.each_thread_list();
    },
    add_one_key_btn: () => {
        var $delete_select_btn = $("button[name='delsubmit']");
        var $load_img_btn = $("<a />");
        $load_img_btn.text("一键加载图片");
        $load_img_btn.on("click", function(){
            favorite.each_thread_list(1)
        });
        $load_img_btn.appendTo($delete_select_btn.parent())
    },
    each_thread_list: (isonekeyload) => {
        var count = 0
        $("div.bm > form:eq(0) > ul[id='favorite_ul'] > li[id*='fav_']").each(function(index) {
            var $li=$(this);
            var thread_id = $li.attr("id").split("_")[1];
            var info_id = "info_" + thread_id;
            var load_btn_id = "load_" + thread_id;

            if ($li.find("#"+load_btn_id).length == 0) {
                var $load_btn = $("<a />");
                $load_btn.text("加载");
                $load_btn.attr("id", load_btn_id);
                $load_btn.addClass("y")
                $load_btn.css("margin","0 5px")
                $load_btn.on("click", function(){
                    favorite.load_thread_info($li)
                })
                $li.find("#a_delete_"+thread_id).after($load_btn)
            }

            if (GM_getValue("switch_autoload") == 1 || isonekeyload == 1) {
                if ($("#"+info_id).length == 0) {
                    if (GM_getValue("load_thread_delayed") == 0) {
                        favorite.load_thread_info($li)
                    } else {
                        count++;
                        setTimeout(() => {
                            favorite.load_thread_info($li)
                        }, GM_getValue("load_thread_delayed") * count)
                    }
                }
            }
        })
    },
    load_thread_info: ($thread_li) => {
        var info_id = "info_" + $thread_li.attr("id").split("_")[1];
        if ($("#"+info_id).length != 0) {
            return ;
        }

        var $li_clone = $thread_li.clone();
        $li_clone.attr("id", info_id);
        $li_clone.children("*").remove();

        var url = "/" + $thread_li.find("a:not([id]):eq(0)").attr("href");
        tools.request_and_parse_thread(url, $li_clone)
        $thread_li.after($li_clone);
    }
}

const userspace = {
    init: () => {
        userspace.add_one_key_btn();
        userspace.add_column();
        userspace.each_thread_list();
    },
    add_one_key_btn: () => {
        var $load_img_btn = $("<a />");
        $load_img_btn.append($('<div>一键加载图片</div>'))
        $load_img_btn.on("click", function(){
            userspace.each_thread_list(1)
        });
        $("#scrolltop").append($("<span />").append($load_img_btn));
        $load_img_btn.css("background","None");
        $load_img_btn.css("height","35px");
    },
    add_column: () => {
        $("#ct div.tl table:eq(0) > tbody:eq(0) > tr:eq(0)").append($('<td style="width:30px">展开</td>'))
    },
    each_thread_list: (isonekeyload) => {
        var count = 0
        $("#ct div.tl table:eq(0) > tbody:eq(0) > tr:not([id]):gt(0)").each(function(index) {
            var $tr=$(this);
            var thread_id = $tr.find("th:eq(0) > a").attr("href").match(/(?<=tid=)\d*/g)[0];
            var info_id = "info_" + thread_id;
            var load_btn_id = "load_" + thread_id;

            if ($tr.find("#"+load_btn_id).length == 0) {
                var $load_btn = $('<span title="查看帖内图片" >'+imgs.expand_svg+'</span>')
                $load_btn.on("click", function(){
                    userspace.load_thread_info($tr, info_id)
                })
                $tr.append($('<td id="'+load_btn_id+'" style="width:20px"></td>').append($load_btn))
            }

            if (GM_getValue("switch_autoload") == 1 || isonekeyload == 1) {
                if ($tr.find(":contains('求片问答悬赏区')").length == 0 && $("#"+info_id).length == 0) {
                    if (GM_getValue("load_thread_delayed") == 0) {
                        userspace.load_thread_info($tr, info_id)
                    } else {
                        count++;
                        setTimeout(() => {
                            userspace.load_thread_info($tr, info_id)
                        }, GM_getValue("load_thread_delayed") * count)
                    }
                }
            }
        })
    },
    load_thread_info: ($thread_tr, info_id) => {
        if ($("#"+info_id).length != 0) {
            return ;
        }

        var $tr_clone = $thread_tr.clone();
        $tr_clone.attr("id", info_id);
        $tr_clone.children("*").remove();

        var $tag_td = $('<td colspan="6"></td>');
        $tag_td.appendTo($tr_clone)

        var url = "/" + $thread_tr.find("th:eq(0) > a").attr("href")
        tools.request_and_parse_thread(url, $tag_td)
        $thread_tr.after($tr_clone);
    }
}

const imgs = {
    load_img_data: "data:image/gif;base64,R0lGODlhEAAQAPQAAP///2FhYfv7+729vdbW1q2trbe3t/Dw8OHh4bKystHR0czMzPX19dzc3Ovr68LCwsfHxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/h1CdWlsdCB3aXRoIEdJRiBNb3ZpZSBHZWFyIDQuMAAh/hVNYWRlIGJ5IEFqYXhMb2FkLmluZm8AIfkECQoAAAAsAAAAABAAEAAABVAgII5kaZ6lMBRsISqEYKqtmBTGkRo1gPAG2YiAW40EPAJphVCREIUBiYWijqwpLIBJWviiJGLwukiSkDiEqDUmHXiJNWsgPBMU8nkdxe+PQgAh+QQJCgAAACwAAAAAEAAQAAAFaCAgikfSjGgqGsXgqKhAJEV9wMDB1sUCCIyUgGVoFBIMwcAgQBEKTMCA8GNRR4MCQrTltlA1mCA8qjVVZFG2K+givqNnlDCoFq6ioY9BaxDPI0EACzxQNzAHPAkEgDAOWQY4Kg0JhyMhACH5BAkKAAAALAAAAAAQABAAAAVgICCOI/OQKNoUSCoKxFAUCS2khzHvM4EKOkPLMUu0SISC4QZILpgk2bF5AAgQvtHMBdhqCy6BV0RA3A5ZAKIwSAkWhSwwjkLUCo5rEErm7QxVPzV3AwR8JGsNXCkPDIshACH5BAkKAAAALAAAAAAQABAAAAVSICCOZGmegCCUAjEUxUCog0MeBqwXxmuLgpwBIULkYD8AgbcCvpAjRYI4ekJRWIBju22idgsSIqEg6cKjYIFghg1VRqYZctwZDqVw6ynzZv+AIQAh+QQJCgAAACwAAAAAEAAQAAAFYCAgjmRpnqhADEUxEMLJGG1dGMe5GEiM0IbYKAcQigQ0AiDnKCwYpkYhYUgAWFOYCIFtNaS1AWJESLQGAKq5YWIsCo4lgHAzFmPEI7An+A3sIgc0NjdQJipYL4AojI0kIQAh+QQJCgAAACwAAAAAEAAQAAAFXyAgjmRpnqhIFMVACKZANADCssZBIkmRCLCaoWAIPm6FBUkwJIgYjR5LN7INSCwHwYktdIMqgoNFGhQQpMMt0WCoiGDAAvkQMYkIGLCXQI8OQzdoCC8xBGYFXCmLjCYhADsAAAAAAAAAAAA=",
    expand_svg  : '<svg viewBox="0 0 1024 1024" width="16px" style="cursor:pointer" xmlns="http://www.w3.org/2000/svg" ><path fill="currentColor" d="M128 192h768v128H128V192zm0 256h512v128H128V448zm0 256h768v128H128V704zm576-352 192 160-192 128V352z"></path></svg>',
    hide_svg    : '<svg viewBox="0 0 1024 1024" width="16px" style="cursor:pointer" xmlns="http://www.w3.org/2000/svg" ><path d="M876.8 156.8c0-9.6-3.2-16-9.6-22.4-6.4-6.4-12.8-9.6-22.4-9.6-9.6 0-16 3.2-22.4 9.6L736 220.8c-64-32-137.6-51.2-224-60.8-160 16-288 73.6-377.6 176C44.8 438.4 0 496 0 512s48 73.6 134.4 176c22.4 25.6 44.8 48 73.6 67.2l-86.4 89.6c-6.4 6.4-9.6 12.8-9.6 22.4 0 9.6 3.2 16 9.6 22.4 6.4 6.4 12.8 9.6 22.4 9.6 9.6 0 16-3.2 22.4-9.6l704-710.4c3.2-6.4 6.4-12.8 6.4-22.4Zm-646.4 528c-76.8-70.4-128-128-153.6-172.8 28.8-48 80-105.6 153.6-172.8C304 272 400 230.4 512 224c64 3.2 124.8 19.2 176 44.8l-54.4 54.4C598.4 300.8 560 288 512 288c-64 0-115.2 22.4-160 64s-64 96-64 160c0 48 12.8 89.6 35.2 124.8L256 707.2c-9.6-6.4-19.2-16-25.6-22.4Zm140.8-96c-12.8-22.4-19.2-48-19.2-76.8 0-44.8 16-83.2 48-112 32-28.8 67.2-48 112-48 28.8 0 54.4 6.4 73.6 19.2L371.2 588.8ZM889.599 336c-12.8-16-28.8-28.8-41.6-41.6l-48 48c73.6 67.2 124.8 124.8 150.4 169.6-28.8 48-80 105.6-153.6 172.8-73.6 67.2-172.8 108.8-284.8 115.2-51.2-3.2-99.2-12.8-140.8-28.8l-48 48c57.6 22.4 118.4 38.4 188.8 44.8 160-16 288-73.6 377.6-176C979.199 585.6 1024 528 1024 512s-48.001-73.6-134.401-176Z" fill="currentColor"></path><path d="M511.998 672c-12.8 0-25.6-3.2-38.4-6.4l-51.2 51.2c28.8 12.8 57.6 19.2 89.6 19.2 64 0 115.2-22.4 160-64 41.6-41.6 64-96 64-160 0-32-6.4-64-19.2-89.6l-51.2 51.2c3.2 12.8 6.4 25.6 6.4 38.4 0 44.8-16 83.2-48 112-32 28.8-67.2 48-112 48Z" fill="currentColor"></path></svg>',
    close_svg   : '<svg viewBox="0 0 1024 1024" width="16px" style="cursor:pointer" xmlns="http://www.w3.org/2000/svg" ><path fill="currentColor" d="M764.288 214.592 512 466.88 259.712 214.592a31.936 31.936 0 0 0-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1 0 45.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0 0 45.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 1 0-45.12-45.184z"></path></svg>',
    upload_svg  : '<svg viewBox="0 0 1024 1024" width="16px" style="cursor:pointer" xmlns="http://www.w3.org/2000/svg" ><path fill="currentColor" d="M544 864V672h128L512 480 352 672h128v192H320v-1.6c-5.376.32-10.496 1.6-16 1.6A240 240 0 0 1 64 624c0-123.136 93.12-223.488 212.608-237.248A239.808 239.808 0 0 1 512 192a239.872 239.872 0 0 1 235.456 194.752c119.488 13.76 212.48 114.112 212.48 237.248a240 240 0 0 1-240 240c-5.376 0-10.56-1.28-16-1.6v1.6H544z"></path></svg>',
    hideuser_svg: '<svg viewBox="0 0 1024 1024" width="16px" style="cursor:pointer" xmlns="http://www.w3.org/2000/svg" ><path d="M730.614 612.961c-27.79 14.626-52.036 35.076-71.115 59.728C615.725 648.664 565.459 635 512 635c-169.551 0-307 137.449-307 307 0 24.3-19.7 44-44 44s-44-19.7-44-44c0-163.047 98.787-303.02 239.774-363.332C279.812 528.088 229 440.978 229 342c0-156.297 126.703-283 283-283s283 126.703 283 283c0 98.978-50.812 186.088-127.774 236.668a394.09 394.09 0 0 1 63.388 34.293zM512 537c107.696 0 195-87.304 195-195s-87.304-195-195-195-195 87.304-195 195 87.304 195 195 195z m252.887 268.8l-64.974-64.973c-17.183-17.183-17.183-45.043 0-62.226s45.043-17.183 62.226 0l64.974 64.974 64.974-64.974c17.183-17.183 45.042-17.183 62.225 0s17.183 45.043 0 62.226L889.338 805.8l64.974 64.974c17.183 17.183 17.183 45.042 0 62.225s-45.042 17.183-62.225 0l-64.974-64.974L762.139 933c-17.183 17.183-45.043 17.183-62.226 0s-17.183-45.042 0-62.225l64.974-64.974z" fill="#000000" p-id="4945"></path></svg>'
}
const tools = {
    base_selector: "#postlist > div[id^=post_]:eq(0) ",
    headers: {
        'User-agent': navigator.userAgent,
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    },
    request_and_parse_thread: (url, $tag) => {
        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            headers: tools.headers,
            onload: (result) => {
                if (result.status != 200) {
                    if (result.status == 404) {
                        $tag.append("此贴不存在或已被删除或正在被审核")
                    }
                    return ;
                }
                var doc = result.responseText;
                var $pre_search_doc = $(doc).find(tools.base_selector)
                tools.load_img($pre_search_doc, $tag)
                // tools.load_download_link($pre_search_doc, $tag)
            }
        });
    },
    load_img: ($from_con, $to_con) => {
        var $tag_div = $('<div ></div>');
        $tag_div.css({
            "width"         :"100%",
            "margin-bottom" :"5px",
            "overflow-x"    :"auto",
            "max-height"    :(GM_getValue("img_max_height")+10) + "px",
        });
        $to_con.append($tag_div);
        var $inner_tag_div = $('<div style="display: flex;align-items: center;"></div>');
        //有些帖子里含有一些分隔符形式的图片,在html特征上与正常的资源图片完全一致,无法过滤
        //仅能将资源地址为站内地址的图片忽略掉,这种图片基本都是无意义的静态资源。
        //剩下的从图床下载,与正经资源图片别无二致的分隔符形式图片只能将其视为普通图片显示出来
        //除非在脚本中进行资源预加载,判断其高度是否过低。但这样资源浪费过于严重。
        //点名批评forum.php?mod=viewthread&tid=1526548帖中那个welcome的动态图(逃
        var $imgs = $from_con.find('img.zoom[file^="http"]:not([file*="static/image"])')
        if ($imgs.length >= parseInt(GM_getValue("img_max_count"))) {
            $inner_tag_div.append('<span style="writing-mode: vertical-lr;">共'+$imgs.length+'张图</span>')
        }
        $imgs.slice(0, parseInt(GM_getValue("img_max_count")))
            .each(function(){
                var pic_url = $(this).attr( "zoomfile" ) || $(this).attr( "file" ) || $(this).attr( "src" );
                if (pic_url != undefined && pic_url != null && pic_url != '') {
                    var $tag_img = $('<img />');
                    $tag_img.attr({
                        "data-original" : pic_url,
                        "src"           : GM_getValue("switch_lazy_load_img") == 1 ? imgs.load_img_data : pic_url,
                        "onclick"       :"zoom(this, this.src, 0, 0, 0)",
                    })
                    $tag_img.css({
                        "max-width"    :GM_getValue("img_max_width") + "px",
                        "max-height"   :GM_getValue("img_max_height") + "px",
                        "cursor"       :"pointer",
                        "margin-right" :"3px",
                        "float"        :"left"
                    });
                    $inner_tag_div.append($tag_img);
                    if (GM_getValue("switch_lazy_load_img") == 1) {
                        $tag_img.lazyload({threshold:50});
                    }
                }
            });
        if ($inner_tag_div.children().length == 0) {
            $tag_div.append("未识别到图片")
        } else {
            $tag_div.append($inner_tag_div)
        }
    },
    //为防止拿到资源地址后不点进帖子导致不评分评论收藏等,损害创作者权益,默认关闭此功能
    //开启方式自己找,别来问,别宣传
    load_download_link: ($from_con, $to_con) => {
        var $tag_div = $('<div></div>');
        $from_con.find("span[id*='attach_']")
            .each(function(){
                var $attach = $(this);
                if ($attach.find("a").length > 0){
                    $tag_div.append($attach.parent().clone());
                    tools.handleZipOrTxt($tag_div,$attach);
                }
            });
        $from_con.find("dl.tattl")
            .each(function(){
                var $attach = $(this);
                if ($attach.find("p.attnm").length > 0){
                    $tag_div.append($attach.parent().clone());
                    tools.handleZipOrTxt($tag_div,$attach);
                }
            });
        var links = [];
        $from_con.find("div.blockcode")
            .each(function(){
                var $codediv = $(this)
                $codediv.find("li").each(function(){
                    var link = $(this).text()
                    if (tools.check_link(link)) {
                        links.push(link)
                    }
                })
            });
        $from_con.find("a[href]")
            .each(function(){
                var $a_tag = $(this)
                var link = $a_tag.attr("href")
                if (tools.check_link(link)) {
                    links.push(link)
                }
            });
        $from_con.find(tools._get_custom_selector())
            .each(function(){
                var text = $(this).text() + ' ';
                if (text.trim() != '') {
                    var _links = tools.match_link(text)
                    links.push(..._links);
                }
            });

        Array.from(new Set(links.map(link => link.trim()))).map((link,index,arr) => tools.append_link(link,$tag_div))

        if ($tag_div.children().length == 0) {
            $tag_div.append("未识别到资源连接")
        } else {
            var $115btn = $('<button type=button>一键推送</button>')
            $115btn.on('click',function(){
                var arrlink = []
                $(this).parent().parent().find('a[dlflag="1"]').each(function(){
                    var _115link = $(this).attr('href')
                    if (tools.check_link_can115(_115link)) {
                        arrlink.push(_115link)
                    }
                })
                if (arrlink.length == 0) {
                    tools.tip("没有找到ed2k或磁力链接!");
                    return
                }
                call115.push_urls(arrlink).then( result => {
                    if (Array.isArray(result)) {
                        let succ = 0;
                        let error = 0;
                        let errortext = "";
                        result.map((item,index,arr) => {
                            if (item.state) {
                                succ++
                            } else {
                                error++;
                                errortext += (item.error_msg + ":" + item.url + '<br/>')
                            }
                        })
                        if (error == 0) {
                            tools.tip(`成功推送${succ}条链接`)
                        } else {
                            tools.tip(`共推送${result.length}条链接,成功${succ}条,失败${error}条:<br/> ${errortext}`,1000*10)
                        }
                    }
                }).catch( msg => tools.tip(msg))
            })
            $tag_div.prepend($("<div></div>").append($115btn))
            $tag_div.prepend($('<div style="color:red">喜欢本贴的话别忘了点进去评分评论收藏哦!</div>'))
        }
        $to_con.append($tag_div);
    },
    append_link: (link,$tag_div) => {
        link = link.trim()
        var $linkdiv = $(`<div><a href="${link}" dlflag="1" target="_blank">${link}</a></div>`)
        if (tools.check_link_can115(link)) {
            var $uploadbtn = $(`<span link="${link}" title="推送到115(需要当前浏览器已登录)" style="margin-left: 10px">${imgs.upload_svg}</span>`)
            $uploadbtn.on("click",function(){
                call115.push_urls($(this).attr("link")).then( result => {
                    if (result[0].state) tools.tip("推送成功")
                    else tools.tip(result[0].error_msg)
                }).catch( msg => tools.tip(msg))
            })
            $uploadbtn.appendTo($linkdiv)
        }
        $tag_div.append($linkdiv)
    },
    handleZipOrTxt: ($tag_div, $attach) => {
        var $a_tag = $attach.find('a:eq(0)')
        if ($a_tag.text().toLowerCase().endsWith('.zip')){
            var $btn = $('<button type=button>解析压缩包</button>')
            var zipdownloadlink = $a_tag.attr("href")
            $btn.on('click',function(){
                readfirsttxtfileinzip(zipdownloadlink).then( text => {
                    text.split('\n').map((text,index,arr) => tools.append_link(text,$tag_div))
                }).catch( error => {
                    console.log(error)
                    if (error.message == 'Encrypted zip are not supported') {
                        tools.tip('暂不支持加密压缩包')
                    }else if (error == 'download err.'){
                        tools.tip("压缩包文件下载失败")
                    }
                })
            })
            $tag_div.append($btn)
        } else if ($a_tag.text().toLowerCase().endsWith('.txt')) {
            var $btn1 = $('<button type=button>加载文档</button>')
            var txtdownloadlink = $a_tag.attr("href")
            $btn1.on('click',function(){
                let _header = {
                    ...headers,
                    'Referer':txtdownloadlink
                }
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: txtdownloadlink,
                    headers: _header,
                    responseType: 'blob',
                    onload: (result) => {
                        if (result.status === 200 || result.status === 304) {
                            var reader = new FileReader();
                                reader.readAsText(result.response, 'utf-8');
                                reader.onload = function (e) {
                                    var text = reader.result
                                    text.split('\n').map((text,index,arr) => tools.append_link(text,$tag_div))
                                }
                        }else{
                            tools.tip("文件下载失败")
                        }
                    }
                });
            })
            $tag_div.append($btn1)
        }
    },
    link_head: {
        can115: ["magnet:?xt=","ed2k://"],
        other: ["115://","https://pan.quark","https://pan.baidu"],
    },
    check_link: (linkstr) => tools._check_link(linkstr, [...tools.link_head.can115, ...tools.link_head.other ]),
    check_link_can115: (linkstr) => tools._check_link(linkstr,tools.link_head.can115),
    _check_link: (linkstr, heads) => heads.some( (head) => linkstr.startsWith(head) ),
    regExps:[],
    match_link: (text) => {
        if (tools.regExps.length == 0) {
            let all_link_head = [...tools.link_head.can115, ...tools.link_head.other ];
            all_link_head.map((currentValue,index,arr) => {
                var key = currentValue.replaceAll("?","\\?")
                if (currentValue == "ed2k://") {
                    tools.regExps.push(new RegExp(`(${key})(.+?)(\\|/|复制代码)`, 'g'))
                }else{
                    tools.regExps.push(new RegExp(`(${key})(.+?)(?=\\s|复制代码)`, 'g'))
                }
            })
        }
        var result = []
        tools.regExps.map((regExp,index,arr) => {
            var _link = text.match(regExp);
            if (_link != null) {
                result.push(..._link);
            }
        })
        return result;
    },
    _get_custom_selector: () => {
        var custom_selector = '';
        let all_link_head = [...tools.link_head.can115, ...tools.link_head.other ];
        for(let i = 0; i < all_link_head.length; i++){
            var _selector = ':contains('+all_link_head[i]+')';
            custom_selector = custom_selector + _selector;
            if ( i != all_link_head.length-1 ) {
                custom_selector = custom_selector + ",";
            }
        }
        return custom_selector;
    },
    add_removed_id: (thread_id) => {
        var max_length = parseInt(GM_getValue("max_hide_history"))
        var removed_ids = GM_getValue("removed_ids").split(",")
        if (max_length == 0) {
            GM_setValue("removed_ids", "")
            return ;
        }
        if (!removed_ids.includes(thread_id)) {
            removed_ids.push(thread_id);
        }
        if (removed_ids.length > max_length) {
            removed_ids = removed_ids.slice(0 - max_length)
        }
        GM_setValue("removed_ids", removed_ids.join(","))
    },
    add_user_id: (userid, userName) => {
        var arr = JSON.parse(GM_getValue("author_list"))
        if (arr.findIndex((user) => user["id"] == userid) < 0) {
            arr.push({
                "id":userid,
                "name":userName,
                "date":parseInt(+new Date()/1000)
            })
            GM_setValue("author_list", JSON.stringify(arr))
        }
    },
    _tipTimerId:null,
    tip: (content,time) => {
        $("#msg").remove();
        clearTimeout(tools._tipTimerId);
        let $tipcon = $(`
            <div id="msg" style="opacity:0;transition: all 0.5s;position:fixed;top: 10%;left: 50%;transform: translate(-50%,-50%);background: #000;color: #fff;border-radius: 4px;text-align: center;padding: 10px 20px;">
                ${content}
            </div>
        `)
        $("body").append($tipcon);
        setTimeout( () => {
            $tipcon.css("opacity", 0.8)
        })
        tools._tipTimerId = setTimeout( () => {
            $tipcon.css("opacity", 0)
            $tipcon.on("transitionend", function() {
                $("#msg").remove();
            })
        }, time?time:2000);
    }
}

const GM_script = {
    init_styles: () => {
        GM_addStyle(`
            .setting-remark{
                color: gray;
                font-style: italic;
            }
       `);
    },
    init_variables: () => {
        GM_script.set_default_value("switch_autoload", 0);
        GM_script.set_default_value("page_thread_delayed", 1000);
        GM_script.set_default_value("switch_lazy_load_img", 1);
        GM_script.set_default_value("load_thread_delayed", 500);
        GM_script.set_default_value("img_max_height", 300);
        GM_script.set_default_value("img_max_width", 300);
        GM_script.set_default_value("img_max_count", 3);
        GM_script.set_default_value("show_hide_btn", 1);
        GM_script.set_default_value("reset_width", 0);
        GM_script.set_default_value("reset_width_px", 1500);
        GM_script.set_default_value("removed_ids", "");
        GM_script.set_default_value("max_hide_history", 500);
        GM_script.set_default_value("hideorgray", "gray");
        GM_script.set_default_value("author_control", 0);
        GM_script.set_default_value("author_list", "[]");
        var max_length = parseInt(GM_getValue("max_hide_history"));
        if (max_length == 0) {
            GM_setValue("removed_ids", "");
        } else {
            var removed_ids = GM_getValue("removed_ids").split(",");
            if (removed_ids.length > max_length) {
                removed_ids = removed_ids.slice(0 - max_length);
                GM_setValue("removed_ids", removed_ids.join(","));
            }
        }
        var now = parseInt(+new Date()/1000)
        var arr = JSON.parse(GM_getValue("author_list"))
        var newarr = arr.filter(user => (now - user["date"]) < 60*60*24*7 )
        GM_setValue("author_list", JSON.stringify(newarr))
    },
    set_default_value: (key, value) => {
        if ( GM_getValue(key) == undefined) {
            GM_setValue(key, value);
        }
    },
    add_config_menu: () => {
        GM_registerMenuCommand("设置", function() {
            var $config_madel = $('<div />');
            $config_madel.css({
                "width": "100%",
                "height": "100%",
                "background": "rgba(0, 0, 0, 0.4)",
                "position": "fixed",
                "top": "0",
                "left": "0",
                "visibility": "hidden",
                "opacity": "0",
                "z-index": "999",
                "transition": "all 0.3s",
            })
            $config_madel.on("click", function() {
                $config_madel.remove();
            })
            $config_madel.keyup(function(e){
                var key = e.which || e.keyCode;
                if(key == 27){
                    $config_madel.remove();
                }
            });

            var $config_window = $('<div />');
            $config_window.css({
                "position": "fixed",
                "top": "50%",
                "left": "50%",
                "padding"       : "10px 20px",
                "background-color": "#fff",
                "border-radius": "10px",
                "transform": "translate(-50%,-50%)",
            });
            $config_window.on("click", function(event) {
                event.stopPropagation()
            })
            $config_window.appendTo($config_madel)

            var $config_title = $(`
                <div>
                    <span style="font-weight: bold">设置 -- 98图片浏览助手</span>
                    <span id="close_cfg_window" title="关闭设置窗口" >${imgs.close_svg}</span>
                </div>
            `);
            $config_title.css({
                "border-bottom": "1px solid gray",
                "font-size": "20px",
                "display": "flex",
                "justify-content": "space-between"
            });
            $config_title.find("#close_cfg_window").on("click", function(){
                $config_madel.remove();
            })
            $config_title.appendTo($config_window)

            var $form = $(`
                <form style="padding: 10px 20px; max-height=600px; overflow-y: auto;">
                    <div>
                        <input type="checkbox" id="reset_width" name="reset_width" />
                        <label for="reset_width">适应宽屏,将内容宽度设置为</label>
                        <input type="number" id="reset_width_px" name="reset_width_px" min="500" max="5000"/>
                        <label for="reset_width_px">px</label>
                        <div class="setting-remark">* 勾选后将会把内容区域的宽度设置为给定值。取值范围500-5000</div>
                    </div>
                    <div>
                        <input type="checkbox" id="show_hide_btn" name="show_hide_btn" />
                        <label for="show_hide_btn">显示隐藏按钮,最多纪录</label>
                        <input type="number" id="max_hide_history" name="max_hide_history" min="0" max="5000"/>
                        <label for="max_hide_history">条隐藏历史 -- 当前已记录 ${GM_getValue("removed_ids").split(",").length} 条 </label>
                        <button id="clear_hide" type=button>清空</button>
                        <div class="setting-remark">* 按钮点击后可以暂时隐藏帖子,并记录此贴ID。取值范围0-5000</div>
                        <div style="margin-left:24px">
                            <span>刷新页面后,自动</span>
                            <input type="radio" id="hide" name="hideorgray" value="hide" />
                            <label for="hide">隐藏</label>
                            <input type="radio" id="gray" name="hideorgray" value="gray" />
                            <label for="gray">置灰</label>
                            <span>标记过的帖子</span>
                        </div>
                    </div>
                    <div>
                        <input type="checkbox" id="switch_autoload" name="switch_autoload" />
                        <label for="switch_autoload">开启自动加载</label>
                        <div class="setting-remark">* 进入帖子列表或翻页后,自动加载所有未加载过的帖子</div>
                    </div>
                    <div>
                        <label for="load_thread_delayed">帖子列表遍历延迟</label>
                        <input type="number" id="load_thread_delayed" name="load_thread_delayed" min="0" max="5000"/>
                        <label for="load_thread_delayed">毫秒</label>
                        <div class="setting-remark">* 间隔多少毫秒加载下个帖子。0为不设延迟,取值范围0-5000</div>
                    </div>
                    <div>
                        <label for="page_thread_delayed">点击下一页后延迟</label>
                        <input type="number" id="page_thread_delayed" name="page_thread_delayed" min="500" max="5000"/>
                        <label for="page_thread_delayed">毫秒再次触发加载</label>
                        <div class="setting-remark">* 在开启自动加载的前提下,点击下一页后如果没有自动加载新出的帖子,可以适当调大该值。取值范围500-5000</div>
                    </div>
                    <div>
                        <input type="checkbox" id="switch_lazy_load_img" name="switch_lazy_load_img" />
                        <label for="switch_lazy_load_img">开启图片懒加载</label>
                        <div class="setting-remark">* 只有图片将要进入显示区时才会下载</div>
                    </div>
                    <div>
                        <label for="img_max_count">每个帖子最多加载</label>
                        <input type="number" id="img_max_count" name="img_max_count" min="0" max="10"/>
                        <label for="img_max_count">张图片</label>
                        <div class="setting-remark">* 取值范围0-10</div>
                    </div>
                    <div>
                        <label for="img_max_width">每行图片最宽占用</label>
                        <input type="number" id="img_max_width" name="img_max_width" min="200" max="1000"/>
                        <label for="img_max_width">像素</label>
                        <div class="setting-remark">* 图片最宽占用多少空间。单位像素,取值范围200-1000</div>
                    </div>
                    <div>
                        <label for="img_max_height">每行图片最高占用</label>
                        <input type="number" id="img_max_height" name="img_max_height" min="200" max="1000"/>
                        <label for="img_max_height">像素</label>
                        <div class="setting-remark">* 图片最高占用多少空间。单位像素,取值范围200-1000</div>
                    </div>
                    <div>
                        <input type="checkbox" id="author_control" name="author_control" />
                        <label for="author_control">开启作者筛选  --  当前小黑屋 ${JSON.parse(GM_getValue("author_list")).length} 人</label>
                        <button id="clear_black" type=button>清空小黑屋</button>
                        <div class="setting-remark">* 点击帖子作者后方的图标即可在7天内自动隐藏此人的帖子</div>
                    </div>
                </form>
            `);
            $form.appendTo($config_window);
            var $clear_hide_btn = $form.find("#clear_hide");
            $clear_hide_btn.click(function() {
                GM_setValue("removed_ids", "");
                tools.tip("清理成功");
            });
            var $clear_blackbtn = $form.find("#clear_black");
            $clear_blackbtn.click(function() {
                GM_setValue("author_list", "[]");
                tools.tip("清理成功");
            });

            var $btns = $(`
                <div>
                    <button id="confirm_btn">确认</button>
                    <button id="cancel_btn">取消</button>
                </div>
            `);
            $btns.css({
                "display": "flex",
                "justify-content": "flex-end",
            })
            var css_btn = {
                "margin-right": "10px",
                "border-radius": "4px",
                "border": "none",
                "min-height": "1em",
                "padding": "6px 12px",
                "cursor": "pointer"
            }
            var $confirm_btn = $btns.find("#confirm_btn")
            var $cancel_btn = $btns.find("#cancel_btn")
            $confirm_btn.css(css_btn);
            $confirm_btn.css({
                "color": "#FFF",
                "background-color": "#2ecc71",
            });
            $cancel_btn.css(css_btn);
            $cancel_btn.css({
                "color": "#000",
                "background-color": "#ecf0f1",
            });

            $confirm_btn.click(function(){
                console.log("config value:");
                console.log("show_hide_btn", $form.find("#show_hide_btn").prop("checked"));
                GM_setValue("show_hide_btn", $form.find("#show_hide_btn").prop("checked") ? 1 : 0);
                console.log("max_hide_history", $form.find("#max_hide_history").val());
                GM_setValue("max_hide_history", $form.find("#max_hide_history").val());
                console.log("hideorgray", $form.find("input[name='hideorgray']:checked").val());
                GM_setValue("hideorgray", $form.find("input[name='hideorgray']:checked").val());
                console.log("reset_width", $form.find("#reset_width").prop("checked"));
                GM_setValue("reset_width", $form.find("#reset_width").prop("checked") ? 1 : 0);
                console.log("reset_width_px", $form.find("#reset_width_px").val());
                GM_setValue("reset_width_px", $form.find("#reset_width_px").val());
                console.log("switch_autoload", $form.find("#switch_autoload").prop("checked"));
                GM_setValue("switch_autoload", $form.find("#switch_autoload").prop("checked") ? 1 : 0);
                console.log("author_control", $form.find("#author_control").prop("checked"));
                GM_setValue("author_control", $form.find("#author_control").prop("checked") ? 1 : 0);
                console.log("switch_lazy_load_img", $form.find("#switch_lazy_load_img").prop("checked"));
                GM_setValue("switch_lazy_load_img", $form.find("#switch_lazy_load_img").prop("checked") ? 1 : 0);
                console.log("load_thread_delayed", $form.find("#load_thread_delayed").val());
                GM_setValue("load_thread_delayed", $form.find("#load_thread_delayed").val());
                console.log("page_thread_delayed", $form.find("#page_thread_delayed").val());
                GM_setValue("page_thread_delayed", $form.find("#page_thread_delayed").val());
                console.log("img_max_height", $form.find("#img_max_height").val());
                GM_setValue("img_max_height", $form.find("#img_max_height").val());
                console.log("img_max_width", $form.find("#img_max_width").val());
                GM_setValue("img_max_width", $form.find("#img_max_width").val());
                console.log("img_max_count", $form.find("#img_max_count").val());
                GM_setValue("img_max_count", $form.find("#img_max_count").val());
                tools.tip("保存成功")
                $config_madel.remove();
            });

            $cancel_btn.click(function(){
                tools.tip("已取消")
                $config_madel.remove()
            });
            $btns.appendTo($config_window)

            $form.find("#show_hide_btn").prop("checked",GM_getValue("show_hide_btn") == 1);
            $form.find("#max_hide_history").val(GM_getValue("max_hide_history"));
            $form.find("#reset_width").prop("checked",GM_getValue("reset_width") == 1);
            $form.find("#reset_width_px").val(GM_getValue("reset_width_px"));
            $form.find("#switch_autoload").prop("checked",GM_getValue("switch_autoload") == 1);
            $form.find("#author_control").prop("checked",GM_getValue("author_control") == 1);
            $form.find("#switch_lazy_load_img").prop("checked",GM_getValue("switch_lazy_load_img") == 1 );
            $form.find("#load_thread_delayed").val(GM_getValue("load_thread_delayed"));
            $form.find("#page_thread_delayed").val(GM_getValue("page_thread_delayed"));
            $form.find("#img_max_height").val(GM_getValue("img_max_height"));
            $form.find("#img_max_width").val(GM_getValue("img_max_width"));
            $form.find("#img_max_count").val(GM_getValue("img_max_count"));
            $form.find("input[id='"+GM_getValue("hideorgray")+"']").attr('checked', 'true');

            $config_madel.appendTo($("body"));
            $config_madel.css('visibility', 'visible');
            $config_madel.css('opacity', '1');
            $config_madel.css('transform', 'scale(1)');
        })
    }
}