老司机传说(新)

为支持度盘标准码而重写的老司机传说,与原版完全是两个不同的东西,砍掉了很多功能。安装前请务必阅读脚本介绍。有问题建议欢迎到反馈页提出。

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        老司机传说(新)
// @namespace   http://www.ocrosoft.com/
// @version     0.129
// @description 为支持度盘标准码而重写的老司机传说,与原版完全是两个不同的东西,砍掉了很多功能。安装前请务必阅读脚本介绍。有问题建议欢迎到反馈页提出。
// @author      ocrosoft
// @match       *://www.liuli.app/*
// @match       *://www.liuli.cat/*
// @match       *://www.hacg.cat/*
// @match       *://blog.reimu.net/*
// @match       *://www.kkgal.com/*
// @match       *://pan.baidu.com/s/*
// @match       *://pan.baidu.com/disk/main*
// @match       *://pan.baidu.com/share/init?surl=*
// @require     https://greasyfork.org/scripts/417761-ilog/code/iLog.js?version=876248
// @require     https://greasyfork.org/scripts/417760-checkjquery/code/checkJQuery.js?version=876220
// @icon        https://www.hacg.cat/favicon.ico
// @grant       unsafeWindow
// @grant       GM_openInTab
// ==/UserScript==

iLog.prefix = '[老司机传说] ';
iLog.setLogLevel(iLog.LogLevel.Warning);

// Cookie
let COOKIES = {
    set: function(name, value, days) {
        if (days == null) {
            alert('days 不允许为空。');
            return;
        }
        let exp = new Date();
        exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000);
        var str = JSON.stringify(value);
        document.cookie = name + "=" + str + ";expires=" + exp.toGMTString() + ';path=\/';
    },
    get: function(name) {
        var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
        if (arr = document.cookie.match(reg)) {
            //return unescape(arr[2]);
            return JSON.parse(arr[2]);
        }
        else {
            return null;
        }
    },
    del: function(name) {
        let exp = new Date();
        exp.setTime(exp.getTime() - 1000);
        document.cookie = name + "=;expires=" + exp.toGMTString() + ';path=\/';
    },
}

// 窗口大小发生改变的调用方法
let resize_functions = {};
// 按下按键时的调用方法
let keydown_functions = {};
// 上一次按键事件
let last_keydown_event = null;
// 查找字符串所在的元素
// root为jQ对象,返回值为jQ对象数组
function FindElementByText(root, text) {
    let result = [];
    let found_in_children = false;
    $.each(root.children(), function(i, child) {
        let _this = $(child);
        if (_this.text().indexOf(text) != -1) {
            let e = FindElementByText(_this, text);
            if (e.length > 0) {
                found_in_children = true;
                result = result.concat(e);
            }
        }
    });
    if (!found_in_children && root.length > 0) {
        result.push(root);
    }
    return result;
}
// 分析提取码
function FindCodes(content, keys) {
    let codes = [];
    $.each(keys, function(i, key) {
        let split = content.split(key);
        if (split.length < 2) {
            iLog.w('找不到对应的提取码:' + key);
            codes.push('');
            return;
        }
        let content_to_match = split[1];
        let match = content_to_match.match(/[^a-zA-Z0-9]([a-zA-Z0-9]{4})([^a-zA-Z0-9]|$)/);
        if (match) {
            codes.push(match[1]);
        } else {
            iLog.w('找不到对应的提取码:' + key);
        }
    });
    let match = [];
    return codes;
}
// 是否可输入元素,输入为裸元素
function IsInputElement(element) {
    let e = element;
    let tag_name = e.tagName.toLowerCase();
    if (tag_name == 'input') {
        if (e.type.toLowerCase() == 'text' ||
            e.type.toLowerCase() == 'password') {
            return true;
        }
    } else if (tag_name == 'textarea') {
        return true;
    }
    return false;
}
// 隐藏所有图片
function HideAllImages(root) {
    if (root == null) {
        root = $(document);
    }
    let images = root.find('img');
    $.each(images, function(i, img) {
        img = $(img);
        if (img.attr('display') != 'none') {
            img.addClass('od_safe_mode_hidden').hide();
        }
    });

}
// 显示所有被上面函数隐藏的图片
function ShowAllHiddenImages(root) {
    if (root == null) {
        root = $(document);
    }
    let images = root.find('.od_safe_mode_hidden');
    images.removeClass('od_safe_mode_hidden').show();
}

let sites = [{
    name: '琉璃神社',
    pattern: /https:\/\/www\.(liuli|hacg)\.[a-z]+\/wp\//,
    process: function() {
        // 是否主页
        function IsMainPage() {
            return location.href.match(/https:\/\/www\.(liuli|hacg)\.[a-z]+\/wp\/?$/) ||
                location.href.match(/https:\/\/www\.(liuli|hacg)\.[a-z]+\/wp\/page\/\d+/);
        }
        // 是否文章页
        function IsArticlePage() {
            return location.href.match(/https:\/\/www\.(liuli|hacg)\.[a-z]+\/wp\/\d+\.html/);
        }
        // 处理磁力链(仅正文)
        function ProcessMagnetInContent() {
            // 提取 HASH
            function GetHashFromMagnet(magnet) {
                return magnet.toLowerCase().replace('magnet:?xt=urn:btih:', '').toUpperCase();
            }
            // 增加一个跳转下载链接的气泡
            function AddBubble(hash_match) {
                // 元素
                let comment_bubble_wrapper = $('#wpd-bubble-wrapper');
                let link_bubble_wrapper = comment_bubble_wrapper.clone();
                link_bubble_wrapper.find('#wpd-bubble-all-comments-count').text(hash_match.length).addClass('od_link_count');
                let link_bubble = link_bubble_wrapper.find('#wpd-bubble-count');
                let svg = $('<svg height="512pt" viewBox="0 -61 512 512" width="512pt" xmlns="http://www.w3.org/2000/svg"><path d="m377 0h-121l-30 37.5 30 37.5h121c33.085938 0 60 26.914062 60 60s-26.914062 60-60 60h-121l-30 37.5 30 37.5h121c74.4375 0 135-60.5625 135-135s-60.5625-135-135-135zm0 0" fill="#18e0ff"></path><path d="m256 120-30 37.5 30 37.5c33.085938 0 60 26.914062 60 60s-26.914062 60-60 60l-30 37.5 30 37.5c74.4375 0 135-60.5625 135-135s-60.5625-135-135-135zm0 0" fill="#13bdf7"></path><path d="m135 195h121v-75h-121c-74.4375 0-135 60.5625-135 135s60.5625 135 135 135h121v-75h-121c-33.085938 0-60-26.914062-60-60s26.914062-60 60-60zm0 0" fill="#18e0ff"></path><path d="m256 75v-75c-74.4375 0-135 60.5625-135 135s60.5625 135 135 135v-75c-33.085938 0-60-26.914062-60-60s26.914062-60 60-60zm0 0" fill="#13bdf7"></path></svg>');
                link_bubble.children('svg').remove();
                link_bubble.append(svg);
                link_bubble_wrapper.css({
                    'left': comment_bubble_wrapper.css('left'),
                    'bottom': parseInt(comment_bubble_wrapper.css('bottom')) + 100 + 'px',
                });
                resize_functions.liuli_resize_bubble_position = function() {
                    link_bubble_wrapper.css('left', comment_bubble_wrapper.css('left'));
                };
                // 链接
                let bubble_message = link_bubble_wrapper.find('#wpd-bubble-add-message').addClass('od_link_message');
                bubble_message.empty().css({'display': 'block', 'text-align': 'left', 'width': 'max-content', 'height': 'auto', 'max-height': '360px', 'overflow-y': 'auto'});
                $.each(hash_match, function(index, hash) {
                    if (index > 0) {
                        bubble_message.append('<br>');
                    }
                    let link_jump = $('<a id="od_bubble_jump_' + (index + 1) + '" style="color:#fff;">定位到链接</a>');
                    let hash_only = GetHashFromMagnet(hash);
                    let link_download = $('<a id="od_bubble_link_' + (index + 1) + '" href="magnet:?xt=urn:btih:' + hash_only + '" style="color:#fff; margin-left: 10px;">' + hash_only + '</a>');
                    link_jump.click(function(e) {
                        let selector = '#od_link_' + hash_only;
                        // 目标在 toggle 里面
                        if ($('.toggle-box').find(selector).length > 0) {
                            let parent = $(selector).parent();
                            while (parent.length > 0) {
                                if (parent.hasClass('toggle-box')) {
                                    if (parent.css('display') == 'none') {
                                        parent.prev().click();
                                    }
                                    break;
                                }
                                parent = parent.parent();
                            }
                        }
                        $('body, html').animate({scrollTop: $(selector).offset().top}, 500);
                        e.stopPropagation();
                    });
                    link_download.click(function(e) {
                        e.stopPropagation();
                    });
                    let span = $('<span></span>');
                    span.append(link_jump).append(link_download);
                    bubble_message.append(span).click(function(e) {
                        e.stopPropagation();
                    });
                });
                // 事件
                link_bubble_wrapper.find('#wpd-bubble-count').click(function(event) {
                    let wrapper = $(this).parent();
                    wrapper.addClass('wpd-bubble-hover');
                });
                link_bubble_wrapper.find('#wpd-bubble').find('svg').css('-webkit-transform', 'rotate(45deg)');
                // 关闭只点 SVG,点弹出的链接就不会关闭了
                link_bubble_wrapper.find('#wpd-bubble').find('svg').click(function(event) {
                    let wrapper = $(this).parent().parent();
                    wrapper.removeClass('wpd-bubble-hover');
                    event.stopPropagation();
                });
                comment_bubble_wrapper.after(link_bubble_wrapper);
                // 找到了链接,主动打开一下
                if (hash_match.length > 0) {
                    link_bubble_wrapper.find('#wpd-bubble-count').click();
                }
            }
            // 过滤无效的HASH
            function FilterHash(content, hash_match_raw) {
                let hash_match = [];
                let hash_set = {};

                function IsFound(content, regex) {
                    let match = content.match(regex);
                    if (match && match.length > 0) {
                        return true;
                    }
                    return false;
                }
                $.each(hash_match_raw, function(index, hash) {
                    // 包含前缀,不检查
                    if (IsFound(content, 'magnet:\\?xt=urn:btih:' + hash)) {
                        if (hash_match.indexOf('magnet:?xt=urn:btih:' + hash) == -1) {
                            hash_match.push('magnet:?xt=urn:btih:' + hash);
                        }
                        return;
                    }
                    let regexs = [
                        '\/' + hash, // 前面跟了一个斜杠,可能是目录名
                        hash + '\/', // 后面跟了一个斜杠,可能是目录名
                        hash + '\.', // 后面一个点,可能是文件名
                    ];
                    let is_valid = true;
                    $.each(regexs, function(index_, regex) {
                        if (IsFound(content, regex)) {
                            is_valid = false;
                            return false;
                        }
                    });
                    if (is_valid && hash_match.indexOf(hash) == -1) {
                        hash_match.push(hash);
                    }
                });

                return hash_match;
            }

            let e_content = $('.entry-content');
            let content = e_content.text();
            let hash_match_raw = content.match(/([a-zA-Z0-9]{40})|([a-zA-Z0-9]{32})/g);
            iLog.d(hash_match_raw);
            if (!hash_match_raw) {
                iLog.i('找不到任何磁力链接。');
                return;
            }
            let hash_match = FilterHash(content, hash_match_raw);
            iLog.d(hash_match);
            if (!hash_match) {
                iLog.i('找不到有效的磁力链接。');
                return;
            }

            // HASH 替换成老司机链接
            $.each(hash_match, function(index, hash) {
                let replace_text = '';
                let hash_only = GetHashFromMagnet(hash);
                replace_text = '<br><a id="od_link_' + hash_only + '" href="magnet:?xt=urn:btih:' + hash + '">老司机链接</a>(' + hash_only + ')<br>';
                // 不能修改整个 content,会导致 toggle 展不开
                let elements = FindElementByText(e_content, hash);
                $.each(elements, function(i, element) {
                    element.get(0).innerHTML = element.get(0).innerHTML.replace(hash, replace_text);
                });
            });

            AddBubble(hash_match);
        }
        // 处理百度链接(仅评论区,新版链接)
        function ProcessBaiduNetdiskInComment() {
            // 从链接取出提取链接
            function GetKeyFromBaiduNetdiskLink(link) {
                if (link.indexOf('/s/') != -1) return link.replace('/s/', '');
                if (link.indexOf('s/') != -1) return link.replace('s/', '');
                return link;
            }
            // 过滤无效的提取链接
            function FilterCommentsKey(e_comments_raw) {
                let e_comments = [];

                $.each(e_comments_raw, function(i, comments) {
                    let e = comments.e;
                    let text = e.text();
                    let match = comments.key_match;
                    let keys = [];
                    $.each(match, function(i, key) {
                        // 前后有数字或字母
                        if (text.match('[0-9a-zA-Z]' + key) ||
                            text.match(key + '[0-9a-zA-Z]')) {
                            return;
                        }
                        // /s/***
                        if (text.match('\/s\/' + key)) {
                            keys.push('/s/' + key);
                            return;
                        }
                        // s/***
                        if (text.match('s\/' + key)) {
                            keys.push('s\/' + key);
                            return;
                        }
                        if (key.length == 22) {
                            key = '1' + key;
                        }
                        // 其他的不管
                        keys.push(key);
                    });
                    let codes = FindCodes(text, keys);
                    e_comments.push({
                        e: e,
                        keys: keys,
                        codes: codes,
                    });
                });

                return e_comments;
            }
            // 追加到气泡
            function AppendToBubble(e_comments) {
                let e_link_count = $('.od_link_count');
                let e_link_message = $('.od_link_message');
                let link_count_now = parseInt(e_link_count.text());
                $.each(e_comments, function(i, comment) {
                    let e = comment.e;
                    let keys = comment.keys;
                    let codes = comment.codes;

                    for (let key_id = 0; key_id < keys.length; ++key_id) {
                        if (link_count_now > 0) {
                            e_link_message.append('<br>');
                        }
                        let key = keys[key_id];
                        let span = $('<span></span>');
                        let link_jump = $('<a id="od_bubble_jump_' + (link_count_now + 1) + '" style="color:#fff;">定位到评论</a>');
                        let key_only = GetKeyFromBaiduNetdiskLink(key);
                        let code_text = (codes.length == 0 ? '(无提取码)' : '(' + codes[key_id] + ')');
                        let code_in_href = (codes.length == 0 ? '' : '#tq=' + codes[key_id]);
                        let link_download = $('<a id="od_bubble_link_' + (link_count_now + 1) + '" target="_blank" href="https://pan.baidu.com/s/' + key_only + code_in_href + '" style="color:#fff; margin-left: 10px;">' + key_only + code_text + '</a>');
                        link_jump.click(function() {
                            $('body, html').animate({scrollTop: e.offset().top}, 500);
                        });
                        span.append(link_jump).append(link_download);
                        e_link_message.append(span);
                        link_count_now += 1;
                    }
                    e_link_count.text(link_count_now);
                });
            }

            let comment_count = parseInt($('#wpd-threads').find('.wpd-thread-info ').find('.wpdtc').text());
            if (comment_count == 0) {
                return;
            }
            let itv = setInterval(function() {
                let e_comment_text = $('.wpd_comment_level-1');
                let e_comments_raw = [];
                if (e_comment_text.length == 0) return;
                clearInterval(itv);
                $.each(e_comment_text, function(i, e_comment) {
                    let e_content = $(e_comment).find('.wpd-comment-text:first');
                    // 貌似 22 长度的是 surl= 版本的,前面加个 1 就能用 /s/
                    let key_match = e_content.text().match(/[a-zA-Z0-9-_]{22,23}/g);
                    if (key_match && key_match.length > 0) {
                        e_comments_raw.push({e: e_content, key_match: key_match});
                    }
                });
                iLog.d(e_comments_raw);
                let e_comments = FilterCommentsKey(e_comments_raw);
                iLog.d(e_comments);

                $.each(e_comments, function(i, comment) {
                    let e_comment = comment.e;
                    let keys = comment.keys;
                    let codes = comment.codes;

                    for (let key_id = 0; key_id < keys.length; ++key_id) {
                        let e = e_comment.get(0);
                        let key = keys[key_id];
                        let code = codes[i];
                        let code_in_href = (code == null ? '' : '#tq=' + code);
                        let key_only = GetKeyFromBaiduNetdiskLink(key);
                        let replace_html = '<a target="_blank" style="padding-left: 5px;" href="https://pan.baidu.com/s/' + key_only + code_in_href + '">前往百度网盘</a>'
                        e.innerHTML = e.innerHTML.replace(key, key + replace_html);
                    }
                });

                AppendToBubble(e_comments);
            }, 100);
        }
        // 快捷键
        function AddQuickKeyboardActions() {
            keydown_functions.liuli_keydown = function(event, last_event) {
                let double_click = (last_event && last_event.keyCode == event.keyCode && (event.timeStamp - last_event.timeStamp) < 300);
                let handled = false;
                if ((event.keyCode >= 49 && event.keyCode <= 57) ||
                    event.keyCode >= 97 && event.keyCode <= 105) {
                    let num = 9;
                    if (event.keyCode <= 57) {
                        num -= (57 - event.keyCode);
                    } else {
                        num -= (105 - event.keyCode);
                    }
                    if (event.ctrlKey) {
                        $('#od_bubble_jump_' + num).click();
                        handled = true;
                    } else if (event.altKey) {
                        let link = $('#od_bubble_link_' + num);
                        if (link.length > 0) {
                            let href = link.attr('href');
                            window.open(href);
                            handled = true;
                        }
                    }
                }
                switch(event.keyCode) {
                    case 17: // ctrl
                        if (double_click) {
                            $('#od_bubble_jump_1').click();
                            handled = true;
                        }
                        break;
                    case 37: // left
                        if (IsInputElement(event.target)) {
                            break;
                        }
                        if (IsMainPage()) { // 上一页
                            let a = $('li.active_page').prev().children('a');
                            if (a.length > 0) {
                                location.href = a.attr('href');
                                handled = true;
                            }
                        } else if (IsArticlePage()) { // 上一篇
                            let a = $('.nav-previous').children('a');
                            if (a.length > 0) {
                                location.href = a.attr('href');
                                handled = true;
                            }
                        }
                        break;
                    case 38: // up
                        if (event.ctrlKey) { // 顶部
                            $('body, html').animate({scrollTop: 0}, 500);
                            handled = true;
                        }
                        break;
                    case 39: // right
                        if (IsInputElement(event.target)) {
                            break;
                        }
                        if (IsMainPage()) { // 下一页
                            let a = $('li.active_page').next().children('a');
                            if (a.length > 0) {
                                location.href = a.attr('href');
                                handled = true;
                            }
                        } else if (IsArticlePage()) { // 下一篇
                            let a = $('.nav-next').children('a');
                            if (a.length > 0) {
                                location.href = a.attr('href');
                                handled = true;
                            }
                        }
                        break;
                    case 40: // down
                        if (event.ctrlKey) { // 底部
                            $('body, html').animate({scrollTop: $('footer:last').offset().top}, 500);
                            handled = true;
                        }
                        break;
                }
                if (handled) {
                    event.preventDefault();
                }
            };
        }

        if (IsArticlePage()) {
            ProcessMagnetInContent();
            ProcessBaiduNetdiskInComment();
        }

        AddQuickKeyboardActions();
    },
}, {
    name: '灵梦御所',
    pattern: /https:\/\/blog.reimu.net/,
    process: function() {
        function IsMainPage() {
            return location.href.match(/https:\/\/blog\.reimu\.net\/?$/) ||
                location.href.match(/https:\/\/blog\.reimu\.net\/page\//);
        }
        function IsArticlePage() {
            return location.href.match(/https:\/\/blog\.reimu\.net\/archives\/\d+/);
        }
        function AddJumpToClass(element) {
            if ($('.od_jump_to').length == 0) {
                element.addClass('od_jump_to');
            }
        }
        // 展开隐藏内容
        function ExpandHideContent() {
            function ResetBtnPosition() {
                let btn = $('#od_link_btn');
                let margin_right = parseInt($('#main').children('article').css('margin-right'));
                let left = $('#main').offset().left + parseInt($('#main').css('width')) - margin_right;
                if (margin_right == 0) {
                    left -= parseInt($('#main').children('article').children('header').css('padding-right'));
                }
                let top = parseInt($('#main').css('padding-top'));
                if ($('.secondary-toggle').css('display') == 'block') {
                    top += parseInt($('.sidebar').css('height'));
                }
                btn.css({
                    'left': left + 'px',
                    'top': top + 'px',
                });
            }

            let btn = $('<button id="od_link_btn" style="position: fixed; top: 0px; left: 0px; display: none;">看见这个说明有问题</button>');
            btn.click(function() {
                let e_hide_content = $('.entry-content').find('pre');
                if (e_hide_content.length > 0) {
                    e_hide_content.css('display', 'block');
                    $('body, html').animate({scrollTop: $(e_hide_content).offset().top}, 500);
                } else if ($('.od_jump_to').length > 0) {
                    $('body, html').animate({scrollTop: $('.od_jump_to:first').offset().top - 70}, 500);
                }
            });
            $('body').append(btn);
            ResetBtnPosition();

            resize_functions.reimu_resize_btn_position = ResetBtnPosition;
        }
        // 磁力链接
        function ProcessMagnetInContent() {
            let e_content = $('.entry-content');
            let content = e_content.text();
            let match = content.match(/magnet:\?xt=urn:btih:([a-zA-Z0-9]{40}|[a-zA-Z0-9]{32})/g);
            if (!match || match.length == 0) {
                iLog.w('找不到磁力链接,可能已经是链接状态。');
                return 0;
            }

            $.each(match, function(i, magnet) {
                let replace_html = '<a href="' + magnet + '">' + magnet + '</a>';
                let replace_node = FindElementByText(e_content, magnet);
                if (replace_node.length > 0) {
                    replace_node = replace_node[0];
                    replace_node.get(0).innerHTML = replace_node.get(0).innerHTML.replace(magnet, replace_html);
                    AddJumpToClass(replace_node);
                }
            });

            return match.length;
        }
        // 秒传链接
        function ProcessFastLinkInContent() {
            let e_content = $('.entry-content');
            let content = e_content.text();
            let link_match = content.match(/([0-9A-F]{32}#[0-9A-F]{32}#\d+#.*\n)|(bdpan:\/\/[0-9a-zA-Z+=]+)/g);
            iLog.d(link_match);
            if (!link_match) {
                iLog.i('没有秒传链接');
                return 0;
            }

            let link_all = '';
            let first_replace_element = null;
            $.each(link_match, function(i, link) {
                link = link.trim();
                let e = FindElementByText(e_content, link);
                if (e.length == 0) {
                    iLog.w('找不到所在元素。');
                    return;
                }
                e = e[0];
                if (first_replace_element == null) {
                    first_replace_element = e;
                }
                let encoded = encodeURIComponent(link + '\n');
                let replace_html = '<a target="_blank" style="color: #55c3dc;" href="https://pan.baidu.com/disk/main#/index?category=all&mc=' + encoded + '">前往百度网盘</a>' + link + '<br>';
                e.get(0).innerHTML = e.get(0).innerHTML.replace(link, replace_html);
                link_all += encoded;
                AddJumpToClass(e);
            });

            // 超过两个秒传链接,添加一个批量转存的链接
            if (link_match.length < 2) {
                return link_match.length;
            }
            let href = 'https://pan.baidu.com/disk/main#/index?category=all&mc=' + link_all;
            if (href.length > 8182) {
                iLog.e('秒传链接过多,无法批量添加。');
                return link_match.length;
            }
            let save_all_link = $('<a target="_blank" style="color: #55c3dc;" href=' + href + '>批量添加' + link_match.length + '个秒传链接</a>');
            if (e_content.find('pre').length > 0) {
                e_content.find('pre:first').prepend('<br><br>').prepend(save_all_link);
            } else if (first_replace_element != null) {
                $(first_replace_element).before(save_all_link);
                $(first_replace_element).before('<br>');
            }

            return link_match.length;
        }
        // 百度链接附加提取码
        function ProcessBaiduNetDiskCode() {
            // 御所都是完整的百度网盘链接,不需要找
            let e_content = $('.entry-content');
            let e_links = e_content.find('a');

            let found_valid_element = false;
            $.each(e_links, function(i, e_link) {
                let _this = $(e_link);
                let link_href = _this.attr('href');
                if (!link_href) {
                    return;
                }
                let match = link_href.match(/https:\/\/pan\.baidu\.com\/s\/[a-zA-Z0-9-_]{23}/);
                if (match) {
                    let temp_span = $('<span style="display: none;">' + match[0] + '</span>');
                    _this.after(temp_span);
                    let codes = FindCodes(e_content.text(), match);
                    if (codes.length > 0) {
                        _this.attr('href', link_href + '#tq=' + codes[0]);
                    } else {
                        iLog.w('找不到对应的提取码:' + link_href);
                    }
                    temp_span.remove();
                    found_valid_element = true;
                    AddJumpToClass(_this);
                }
            });
            if (!found_valid_element) {
                iLog.i('找不到百度网盘链接。');
                return 0;
            }

            return 1;
        }
        // 快捷键
        function AddQuickKeyboardActions() {
            keydown_functions.reimu_keydown = function(event, last_event) {
                let double_click = (last_event && last_event.keyCode == event.keyCode && (event.timeStamp - last_event.timeStamp) < 300);
                switch(event.keyCode) {
                    case 17: // ctrl
                        if (double_click ) { // 双击前往隐藏内容
                            $('#od_link_btn').click();
                        }
                        break;
                    case 37: // left
                        if (IsInputElement(event.target)) {
                            break;
                        }
                        if (IsMainPage()) { // 上一页
                            $('span.current').prev().click();
                        } else if (IsArticlePage()) { // 上一篇
                            $('.nav-previous').children('a').click();
                        }
                        break;
                    case 38: // up
                        if (event.ctrlKey) { // 顶部
                            $('body, html').animate({scrollTop: 0}, 500);
                        }
                        break;
                    case 39: // right
                        if (IsInputElement(event.target)) {
                            break;
                        }
                        if (IsMainPage()) { // 下一页
                            $('span.current').next().click();
                        } else if (IsArticlePage()) { // 下一篇
                            $('.nav-next').children('a').click();
                        }
                        break;
                    case 40: // down
                        if (event.ctrlKey) { // 底部
                            $('body, html').animate({scrollTop: $('footer:last').offset().top}, 500);
                        } else if (double_click) {
                            $('#od_link_btn').click();
                        }
                        break;
                }
            }
        }

        ExpandHideContent();
        AddQuickKeyboardActions();

        let current_href = '';
        let processed = false;
        // 御所是不刷新的
        setInterval(function() {
            let processed = $('.entry-content').hasClass('od_processed');
            if (!processed) {
                $('.entry-content').addClass('od_processed');
                let link_count = 0;
                link_count += ProcessBaiduNetDiskCode();
                link_count += ProcessMagnetInContent();
                link_count += ProcessFastLinkInContent();
                iLog.i(link_count);
                if ($('.entry-content').find('pre').length > 0) {
                    $('#od_link_btn').text('显示并前往隐藏内容').show();
                } else if (link_count > 0) {
                    $('#od_link_btn').text('前往下载内容').show();
                } else {
                    $('#od_link_btn').hide();
                }
            }
        }, 100);
    },
}, {
    name: '忧郁的loli',
    pattern: /https:\/\/www\.kkgal\.com\/.*\.html/,
    process: function() {
        // 中国线路保存30天(无法保证线路有效)
        function ProcessChineseLink() {
            let id_keys = COOKIES.get('kkgal_id_keys');
            if (id_keys == null) {
                id_keys = {};
            }

            let onedrive_panel = FindElementByText($('.panel-primary'), 'Onedrive');
            if (onedrive_panel.length == 0) {
                iLog.e('没有找到OneDrive下载链接。');
                return;
            }
            onedrive_panel = onedrive_panel[0].parent();
            let span = FindElementByText(onedrive_panel, '资源编号');
            if (span.length == 0) {
                iLog.e('无法解析资源编号。');
                return;
            }
            let id = span[0].children('span:first').text();
            if (onedrive_panel.find('input[value="购买"]').length > 0) {
                iLog.i('中国线路需要购买,正在查询30天内是否购买过。');
            } else {
                // 保存
                let btns = onedrive_panel.find('button');
                $.each(btns, function(i, btn) {
                    btn = $(btn);
                    let link = btn.attr('onclick');
                    if (link.indexOf('odcn.') != -1) {
                        let match = link.match(id + '_(.*)_');
                        if (match) {
                            id_keys[id] = match[1];
                            iLog.i('已保存中国线路:' + id + '-' + match[1]);
                            COOKIES.set('kkgal_id_keys', id_keys, 30);
                            return;
                        }
                    }
                });
                return;
            }
            // 查找并替换链接
            if (id_keys[id] == null) {
                iLog.i('找不到购买记录,需要购买后查看中国线路。');
                return;
            }
            let btn_internaltional = onedrive_panel.find('button:first');
            if (btn_internaltional.length == 0) {
                iLog.e('找不到国际线路。');
                return;
            }
            let link = btn_internaltional.attr('onclick').replace('window.open(\'', '').replace('\')', '');
            if (link.indexOf('od.') == -1) {
                iLog.e('链接格式不正确,需要更新。');
                return;
            }
            link = link.replace('od.', 'odcn.');
            link = link.replace(':8080/', ':8080/' + id + '_' + id_keys[id] + '_');
            iLog.d(link);
            let body = onedrive_panel.find('.panel-body');
            body.prepend('<a class="hint--right" data-hint="下载前请务必看一下新人必读和解压必读"><button type="button" class="btn btn-danger" onclick="window.open(\'' + link + '\')"><font color="#ffffff">链接</font></button></a>');
            body.prepend('<b><span style="font-size: 10pt;">中国线路(本地保存):</span></b>');
        }
        // 快捷键
        function AddQuickKeyboardActions() {
            keydown_functions.kkgal_keydown = function(event, last_event) {
                let double_click = (last_event && last_event.keyCode == event.keyCode && (event.timeStamp - last_event.timeStamp) < 300);
                let handled = false;
                switch(event.keyCode) {
                    case 17: // ctrl
                        if (double_click ) { // 双击前往下载位置
                            $('body, html').animate({scrollTop: $('.panel-primary:first').offset().top}, 500);
                        }
                        break;
                    case 38: // up
                        if (event.ctrlKey) { // 顶部
                            $('body, html').animate({scrollTop: 0}, 500);
                        }
                        break;
                    case 40: // down
                        if (event.ctrlKey) { // 底部
                            $('body, html').animate({scrollTop: $('footer:last').offset().top}, 500);
                        } else if (double_click) {
                            $('#od_link_btn').click();
                        }
                        break;
                }
            };
        }

        ProcessChineseLink();
        AddQuickKeyboardActions();
    },
}, {
    name: '百度网盘-主页-秒传',
    pattern: /https:\/\/pan\.baidu\.com\/disk\/main.*&mc=/,
    process: function() {
        // 加载秒传链接
        function LoadFastLink() {
            let detect_count = 0;
            let itv = setInterval(function() {
                let href = location.href;
                let match = href.match(/&mc=([^&#]+)/);
                if (!match) {
                    clearInterval(itv);
                    iLog.e('找不到秒传链接!');
                    return;
                }
                let fast_link = decodeURIComponent(match[1]);
                let btn = $('#bdlink_btn');
                if (btn.length == 0) {
                    if (++detect_count >= 50) {
                        iLog.e('未安装秒传插件,即将退出。');
                        iLog.i('需要安装:https://greasyfork.org/zh-CN/scripts/424574');
                        let go = confirm('未安装秒传插件,点击确定前往安装。');
                        if (go) {
                            GM_openInTab('https://greasyfork.org/zh-CN/scripts/424574', false);
                        }
                        clearInterval(itv);
                        return;
                    }
                    if (detect_count % 10 == 0) {
                        iLog.w('未安装秒传插件,剩余尝试次数:' + (50 - detect_count));
                    }
                    return;
                }
                clearInterval(itv);
                itv = setInterval(function() {
                    iLog.i('点击秒传按钮。');
                    btn.children('span').click();
                    setTimeout(function() {
                        if ($('.swal2-textarea').length > 0) {
                            clearInterval(itv);
                        }
                        iLog.i('填写秒传链接。');
                        $('.swal2-textarea').val(fast_link);
                    }, 100);
                }, 200);
            }, 100);
        }

        LoadFastLink();
    },
}, {
    name: '百度网盘-分享',
    pattern: /https:\/\/pan\.baidu\.com\/s\/.*#tq=|https:\/\/pan\.baidu\.com\/share\/init\?surl=.*#tq=/,
    process: function() {
        let code_match = location.href.match(/#tq=([^&]+)/);
        if (!code_match) {
            iLog.e('找不到提取码。');
            return;
        }
        let code = code_match[1];
        let input = [];
        let dt = FindElementByText($('.verify-input'), '请输入提取码');
        if (dt.length == 0) {
            iLog.w('找不到输入框,尝试其他方式。');
        } else {
            input = dt[0].next().find('input');
            if (input.length == 0) {
                iLog.w('找不到输入框,尝试其他方式。');
                input = $('input[tabindex="1"]');
            }
        }
        if (input.length == 0) {
            iLog.e('找不到输入框,请手动填写。');
            return;
        }
        input.val(code);
        let btn = $('#submitBtn');
        btn.click();
    },
}, {
    name: '通用',
    pattern: /.*/,
    process: function() {
        function TryHideImages() {
            let safe_mode_cookie = COOKIES.get('all_safe_mode');
            if (safe_mode_cookie != null && safe_mode_cookie.enable) {
                HideAllImages();
            }
        }

        if (location.href.match(/https:\/\/pan.baidu.com\//)) {
            return;
        }

        TryHideImages();
        setInterval(TryHideImages, 100);

        keydown_functions.general_keydown = function(event, last_event) {
            if (event.ctrlKey && event.shiftKey && event.keyCode == 83) {
                let safe_mode_cookie = COOKIES.get('all_safe_mode');
                if (safe_mode_cookie && safe_mode_cookie.enable) {
                    COOKIES.del('all_safe_mode');
                    ShowAllHiddenImages();
                    iLog.i('安全模式关闭');
                } else {
                    COOKIES.set('all_safe_mode', {enable: true}, 365);
                    HideAllImages();
                    iLog.i('安全模式开启');
                }
                event.preventDefault();
            }
        };
    }
}];

checkJQuery().then(function(success) {
    if (!success) {
        return;
    }

    let url = location.href;
    $.each(sites, function(index, site) {
        if (!url.match(site.pattern)) {
            return;
        }
        iLog.i(site.name);
        site.process();
    });

    $(window).resize(function() {
        $.each(resize_functions, function(name, func) {
            func();
        });
    });

    $(window).keydown(function(event) {
        $.each(keydown_functions, function(name, func) {
            func(event, last_keydown_event);
        });
        last_keydown_event = event;
    });
});