Greasy Fork is available in English.

BilibiliCover

B站显示视频封面

اعتبارا من 23-03-2018. شاهد أحدث إصدار.

// ==UserScript==
// @name         BilibiliCover
// @version      3.0.1
// @description  B站显示视频封面
// @author       AnnAngela
// @namespace    https://greasyfork.org/users/129402
// @mainpage     https://greasyfork.org/zh-CN/scripts/33411-bilibilicover
// @supportURL   https://greasyfork.org/zh-CN/scripts/33411-bilibilicover/feedback
// @license      GNU General Public License v3.0 or later
// @compatible   chrome
// @compatible   firefox
// @compatible   opera
// @compatible   safari
// @match        *://www.bilibili.com/video/av*
// @match        *://www.bilibili.com/watchlater*
// @match        *://www.bilibili.com/bangumi/play/*
// @match        *://live.bilibili.com/*
// @run-at       document-start
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @noframes
// @icon         data:image/png;base64,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
// @icon64       data:image/png;base64,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
// ==/UserScript==
unsafeWindow.addEventListener("load", function() {
    var LF = String.fromCharCode(10),
        XX = String.fromCharCode(47);
    var helper = {
        Uri: (function() {
            var class2type = {
                "[object Boolean]": "boolean",
                "[object Number]": "number",
                "[object String]": "string",
                "[object Function]": "function",
                "[object Array]": "array",
                "[object Date]": "date",
                "[object RegExp]": "regexp",
                "[object Object]": "object",
                "[object Error]": "error"
            };
            var toString = class2type.toString;

            var $ = {
                type: function(obj) {
                    if (obj == null) { // jshint ignore:line
                        return obj + "";
                    }
                    return typeof obj === "object" || typeof obj === "function" ?
                        class2type[toString.call(obj)] || "object" :
                        typeof obj;
                }
            };

            function isArraylike(obj) {
                var length = "length" in obj && obj.length,
                    type = $.type(obj);
                if (type === "function" || $.isWindow(obj)) {
                    return false;
                }
                if (obj.nodeType === 1 && length) {
                    return true;
                }
                return type === "array" || length === 0 ||
                    typeof length === "number" && length > 0 && (length - 1) in obj;
            }

            function encode(s) {
                return encodeURIComponent(s)
                    .replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28')
                    .replace(/\)/g, '%29').replace(/\*/g, '%2A')
                    .replace(/%20/g, '+');
            }

            function cat(pre, val, post, raw) {
                if (val === undefined || val === null || val === '') {
                    return '';
                }
                return pre + (raw ? val : encode(val)) + post;
            }
            Object.assign($, {
                isWindow: function(obj) {
                    return obj != null && obj == obj.window; // jshint ignore:line
                },
                isPlainObject: function(obj) {
                    var key;
                    if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) {
                        return false;
                    }
                    try {
                        if (obj.constructor &&
                            !hasOwn.call(obj, "constructor") &&
                            !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
                            return false;
                        }
                    } catch (e) {
                        return false;
                    }
                    if (support.ownLast) {
                        for (key in obj) {
                            return hasOwn.call(obj, key);
                        }
                    }
                    for (key in obj) {}
                    return key === undefined || hasOwn.call(obj, key);
                },
                each: function(obj, callback, args) {
                    var value,
                        i = 0,
                        length = obj.length,
                        isArray = isArraylike(obj);
                    if (args) {
                        if (isArray) {
                            for (; i < length; i++) {
                                value = callback.apply(obj[i], args);
                                if (value === false) {
                                    break;
                                }
                            }
                        } else {
                            for (i in obj) {
                                value = callback.apply(obj[i], args);
                                if (value === false) {
                                    break;
                                }
                            }
                        }
                    } else {
                        if (isArray) {
                            for (; i < length; i++) {
                                value = callback.call(obj[i], i, obj[i]);
                                if (value === false) {
                                    break;
                                }
                            }
                        } else {
                            for (i in obj) {
                                value = callback.call(obj[i], i, obj[i]);
                                if (value === false) {
                                    break;
                                }
                            }
                        }
                    }
                    return obj;
                }
            });
            var parser = {
                    strict: /^(?:([^:\/?#]+):)?(?:\/\/(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?)?((?:[^?#\/]*\/)*[^?#]*)(?:\?([^#]*))?(?:\#(.*))?/,
                    loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?(?:(?:([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?([^:\/?#]*)(?::(\d*))?((?:\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?[^?#\/]*)(?:\?([^#]*))?(?:\#(.*))?/
                },
                properties = ['protocol', 'user', 'password', 'host', 'port', 'path', 'query', 'fragment'];
            var UriRelative = function(documentLocation) {
                var getDefaultUri = (function() {
                    var href, uri;
                    return function() {
                        var hrefCur = typeof documentLocation === 'string' ? documentLocation : documentLocation();
                        if (href === hrefCur) {
                            return uri;
                        }
                        href = hrefCur;
                        uri = new Uri(href);
                        return uri;
                    };
                }());

                function Uri(uri, options) {
                    var prop, defaultUri = getDefaultUri();
                    options = typeof options === 'object' ? options : {
                        strictMode: !!options
                    };
                    Object.assign(options, {
                        strictMode: false,
                        overrideKeys: false
                    });
                    if (uri !== undefined && uri !== null && uri !== '') {
                        if (typeof uri === 'string') {
                            this.parse(uri, options);
                        } else if (typeof uri === 'object') {
                            for (prop in uri) {
                                if (uri.hasOwnProperty(prop)) {
                                    if (Array.isArray(uri[prop]) || $.isPlainObject(uri[prop])) {
                                        this[prop] = $.extend(true, {}, uri[prop]);
                                    } else {
                                        this[prop] = uri[prop];
                                    }
                                }
                            }
                            if (!this.query) {
                                this.query = {};
                            }
                        }
                    } else {
                        return defaultUri.clone();
                    }
                    if (!this.protocol) {
                        this.protocol = defaultUri.protocol;
                    }
                    if (!this.host) {
                        this.host = defaultUri.host;
                        if (!this.port) {
                            this.port = defaultUri.port;
                        }
                    }
                    if (this.path && this.path[0] !== '/') {
                        //console.error('Bad constructor arguments', JSON.stringify(uri), JSON.stringify(options), new Error().stack);
                    }
                    if (!(this.protocol && this.host && this.path)) {
                        //console.error('Bad constructor arguments', JSON.stringify(uri), JSON.stringify(options), new Error().stack);
                    }
                }
                Uri.encode = function(s) {
                    return encodeURIComponent(s).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
                };
                Uri.decode = function(s) {
                    return decodeURIComponent(s.replace(/\+/g, '%20'));
                };
                Uri.prototype = {
                    parse: function(str, options) {
                        var q, matches, uri = this,
                            hasOwn = Object.prototype.hasOwnProperty;
                        matches = parser[options.strictMode ? 'strict' : 'loose'].exec(str);
                        $.each(properties, function(i, property) {
                            uri[property] = matches[i + 1];
                        });
                        q = {};
                        if (uri.query) {
                            uri.query.replace(/(?:^|&)([^&=]*)(?:(=)([^&]*))?/g, function($0, $1, $2, $3) {
                                var k, v;
                                if ($1) {
                                    k = Uri.decode($1);
                                    v = ($2 === '' || $2 === undefined) ? null : Uri.decode($3);
                                    if (options.overrideKeys || !hasOwn.call(q, k)) {
                                        q[k] = v;
                                    } else {
                                        if (typeof q[k] === 'string') {
                                            q[k] = [q[k]];
                                        }
                                        if (Array.isArray(q[k])) {
                                            q[k].push(v);
                                        }
                                    }
                                }
                            });
                        }
                        uri.query = q;
                    },
                    getUserInfo: function() {
                        return cat('', this.user, cat(':', this.password, ''));
                    },
                    getHostPort: function() {
                        return this.host + cat(':', this.port, '');
                    },
                    getAuthority: function() {
                        return cat('', this.getUserInfo(), '@') + this.getHostPort();
                    },
                    getQueryString: function() {
                        var args = [];
                        $.each(this.query, function(key, val) {
                            var k = Uri.encode(key),
                                vals = Array.isArray(val) ? val : [val];
                            $.each(vals, function(i, v) {
                                if (v === null) {
                                    args.push(k);
                                } else {
                                    args.push(k + '=' + Uri.encode(v));
                                }
                            });
                        });
                        return args.join('&');
                    },
                    getRelativePath: function() {
                        return this.path + cat('?', this.getQueryString(), '', true) + cat('#', this.fragment, '');
                    },
                    toString: function() {
                        return this.protocol + '://' + this.getAuthority() + this.getRelativePath();
                    },
                    clone: function() {
                        return new Uri(this);
                    },
                    extend: function(parameters) {
                        $.extend(this.query, parameters);
                        return this;
                    }
                };
                return Uri;
            };
            return UriRelative(function() {
                return location.href;
            });
        })(),
        coverImage: function coverImage(url) {
            /* 本函数来自 https://greasyfork.org/zh-CN/scripts/30714-获取哔哩哔哩视频的封面图片-get-bilibili-cover-image/code?version=202372 特此感谢*/
            var coverImageBigUrl = url;
            // 去除url中的裁剪标识
            if (url.indexOf("@") > -1) {
                //处理以@做裁剪标识的url
                coverImageBigUrl = url.split("@")[0];
            }
            if (url.indexOf("jpg_") > -1) {
                //处理以_做裁剪标识的url
                coverImageBigUrl = url.split("jpg_")[0] + "jpg";
            }
            if (url.indexOf("png_") > -1) {
                //处理以_做裁剪标识的url
                coverImageBigUrl = url.split("png_")[0] + "png";
            }
            if (url.indexOf("/320_200/") > -1) {
                //有时裁剪标识是在后缀名之前的 目前主要发现的是“番剧”板块的列表里有,但尚不清楚其他地方的情况
                coverImageBigUrl = url.replace("/320_200", "");
            }
            if (coverImageBigUrl.substring(0, 2) === XX + XX) coverImageBigUrl = "https:" + coverImageBigUrl;
            else if (coverImageBigUrl.substring(0, 5) === "http:") coverImageBigUrl = coverImageBigUrl.replace("http:", "https:");
            return coverImageBigUrl;
        },
        window: undefined,
        openWin: function(win, src) {
            if (this.window) this.setImg(src);
            else {
                var self = this,
                    doc = win.document;
                var w = win.innerWidth || doc.docElement.clientWidth || doc.body.clientWidth,
                    h = win.innerHeight || doc.docElement.clientHeight || doc.body.clientHeight;
                self.window = window.open("about:blank", "bilibiliCover", "location=1,scrollbars=1,channelmode=1,width=" + w * .8 + ",height=" + h * .95 + ",left=" + w * .1 + ",top=" + h * .1);
                setTimeout(function() {
                    self.window.document.title = "BilibiliCover - 封面获取窗口";
                    self.window.document.body.innerHTML = '<div style="text-align: start;">视频封面地址:</div><textarea readonly="readonly" style="width: 100%; height: 1.1em; font-size: 24px; box-sizing: content-box; overflow: hidden; background-color: white; color: initial;"></textarea><hr><img src="' + src + '" style="max-width: 100%; height: auto;"><p id="realsize" style="text-align: center;"></p>';
                    self.window.document.body.innerHTML += "<style> a { cursor: pointer; background-position: center right;background-repeat: no-repeat;background-image: -webkit-linear-gradient(transparent, transparent), url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%3E%3Cg%20transform%3D%22translate%28-826.429%20-698.791%29%22%3E%3Crect%20width%3D%225.982%22%20height%3D%225.982%22%20x%3D%22826.929%22%20y%3D%22702.309%22%20fill%3D%22%23fff%22%20stroke%3D%22%2306c%22%2F%3E%3Cg%3E%3Cpath%20d%3D%22M831.194%20698.791h5.234v5.391l-1.571%201.545-1.31-1.31-2.725%202.725-2.689-2.689%202.808-2.808-1.311-1.311z%22%20fill%3D%22%2306f%22%2F%3E%3Cpath%20d%3D%22M835.424%20699.795l.022%204.885-1.817-1.817-2.881%202.881-1.228-1.228%202.881-2.881-1.851-1.851z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E); background-image: linear-gradient(transparent, transparent), url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%3E%3Cg%20transform%3D%22translate%28-826.429%20-698.791%29%22%3E%3Crect%20width%3D%225.982%22%20height%3D%225.982%22%20x%3D%22826.929%22%20y%3D%22702.309%22%20fill%3D%22%23fff%22%20stroke%3D%22%2306c%22%2F%3E%3Cg%3E%3Cpath%20d%3D%22M831.194%20698.791h5.234v5.391l-1.571%201.545-1.31-1.31-2.725%202.725-2.689-2.689%202.808-2.808-1.311-1.311z%22%20fill%3D%22%2306f%22%2F%3E%3Cpath%20d%3D%22M835.424%20699.795l.022%204.885-1.817-1.817-2.881%202.881-1.228-1.228%202.881-2.881-1.851-1.851z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E); padding-right: 13px; } </style>";
                    self.window.document.body.innerHTML += '<p style="display: flex; flex-wrap: nowrap; justify-content: space-around;"><a target="_blank" data-href="https://image.baidu.com/pcdutu?queryImageUrl=%s">Baidu识图搜索</a><a target="_blank" data-href="https://www.google.com/searchbyimage?image_url=%s&encoded_image=&image_content=&filename=&hl=zh-CN">Google识图搜索</a></p>';
                    self.window.document.body.style.textAlign = "center";
                    self.setImg(src);
                    var t = self.window.document.querySelector("textarea");
                    t.addEventListener("mouseup", function(e) {
                        if (e.which !== 1) return;
                        var selection = self.window.getSelection();
                        if (selection.toString() !== "") return;
                        this.focus();
                        this.select();
                    });
                    Array.from(self.window.document.querySelectorAll("a")).forEach(function(ele) {
                        ele.addEventListener("click", function() {
                            window.open(ele.dataset.href.replace("%s", encodeURIComponent(self.window.document.querySelector("textarea").value)), "_blank").focus();
                        });
                    });
                    self.window.addEventListener("beforeunload", function() {
                        self.window = undefined;
                    });
                    self.window.focus();
                }, 0);
            }
        },
        setImg: function setImg(src) {
            if (!this.window) return;
            var img = this.window.document.querySelector("img");
            this.window.document.querySelector("img").src = src;
            this.window.document.querySelector("textarea").value = src;
            this.setNaturalSize(img, this.window.document.querySelector("#realsize"));
            this.window.focus();
        },
        setNaturalSize: function setNaturalSize(img, node) {
            var self = this;
            if (img.naturalWidth > 0 && img.naturalHeight > 0) node.innerText = "(" + img.naturalWidth + "×" + img.naturalHeight + ")";
            else setTimeout(function() {
                self.setNaturalSize(img, node);
            }, 100);
        },
        closeWin: function focusWin() {
            if (this.window) this.window.close();
        }
    };
    var body = unsafeWindow.document.body,
        html = unsafeWindow.document.documentElement;
    var innerWidth = unsafeWindow.innerWidth;
    var scrollbarWidth = 0;
    switch ("scroll") {
        case getComputedStyle(body).overflowY:
            scrollbarWidth = innerWidth - body.clientWidth;
            break;

        case getComputedStyle(html).overflowY:
            scrollbarWidth = innerWidth - html.clientWidth;
            break;

        default:
            var backup = body.style.overflowY;
            body.style.overflowY = "scroll";
            scrollbarWidth = unsafeWindow.innerWidth - body.clientWidth;
            body.style.overflowY = backup;
    }
    var url = new helper.Uri();
    if (unsafeWindow.location.host.includes("www.bilibili.com"))(function loop() {
        var IS_ORIGIN_VIDEO = true;
        var aid = (url.path.match(/\/video\/av(\d+)/) || [0, -1])[1];
        if (aid === -1) IS_ORIGIN_VIDEO = false;
        var doc = unsafeWindow.document;
        var plw = doc.querySelector(".player-box, .bangumi-player");
        if (!plw) return setTimeout(loop, 100);
        var img = doc.createElement("img");
        if (IS_ORIGIN_VIDEO) GM_xmlhttpRequest({
            url: "https://search.bilibili.com/api/search?search_type=video&keyword=" + aid,
            method: "GET",
            onerror: function() {
                var args = Array.from(arguments);
                args.unshift('BilibiliCover');
                args.unshift('NetworkError');
                console.error.apply(console, args)
            },
            onload: function(res) {
                console.info('BilibiliCover', 'NetworkResponse', res);
                try {
                    response = JSON.parse(res.responseText);
                } catch (e) {
                    response = false;
                }
                if (!response) console.info('BilibiliCover', 'NetworkError', 'Unable to parse response');
                var data = response.result;
                var cover;
                data.forEach(function(info) {
                    if (info.id === +aid && info.pic) cover = helper.coverImage(info.pic);
                });
                if (cover) {
                    img.src = cover;
                } else console.info('BilibiliCover', 'NetworkError', 'Unable to get the cover picture url');
            }
        });
        else {
            var loop_code = setInterval(function() {
                try {
                    img.src = helper.coverImage(doc.querySelector(".bilibili-player-auxiliary-area .bilibili-player-watchlater-item[data-state-play=true] .bilibili-player-watchlater-cover-cell img, .bangumi-info-wrapper .info-cover img").src);
                    clearInterval(loop_code);
                } catch (_) {
                    console.info("bilibiliCover", "no img");
                }
            }, 1e3);
        }
        img.id = "cover_img";
        var sbw = scrollbarWidth;
        plw.appendChild(img);
        img.style.display = "block";
        img.style.position = "absolute";
        img.style.cursor = "pointer";

        function calc() {
            var flag = true;
            var bsn = Array.from(plw.children).filter(function(ele, i) {
                return plw.children[i - 1] && ele.nodeName !== "IMG" && (/_{2}?bofqi/i.test(plw.children[i - 1].id) || /scontent|player-content|bangumi-player/i.test(plw.children[i - 1].classList.value));
            })[0];
            if (!bsn) {
                bsn = plw.querySelector(".scontent, .player-content, .bangumi-player");
                flag = false;
            }
            var ofs = getComputedStyle(bsn);
            var ofl = parseInt(ofs.width) + parseInt(ofs.marginLeft) + parseInt(ofs.paddingLeft) + parseInt(ofs.borderLeftWidth),
                ofb = flag ? parseInt(ofs.height) + parseInt(ofs.marginTop) + parseInt(ofs.paddingTop) + parseInt(ofs.borderTopWidth) : parseInt(getComputedStyle(doc.querySelector("#bofqi")).marginBottom),
                wdt = ofs.width;
            var w = window.innerWidth || doc.docElement.clientWidth || doc.body.clientWidth;
            img.style.left = "calc(" + ofl + "px + 1em)";
            img.style.bottom = "calc(" + ofb + "px + 1em)";
            img.style.width = "calc(" + w + "px / 2 - " + wdt + " / 2 - 2em - " + sbw / 2 + "px)";
        }
        calc();
        img.title = "此处是本视频封面大图!" + LF + LF + "右键菜单可复制图片大图地址," + LF + "左键单击可在新窗口查看大图!";
        window.addEventListener("resize", function() {
            calc();
        });
        img.addEventListener("click", function() {
            var src = this.src;
            if (src) helper.openWin(window, src);
        });
    })();
    else if (unsafeWindow.location.host.includes("live.bilibili.com"))(function loop() {
        var container = unsafeWindow.document.querySelector(".seeds-wrap");
        if (!container) return setTimeout(loop, 100);
        var link = unsafeWindow.document.createElement("div");
        link.style.display = "inline-block";
        link.style.marginRight = "1em";
        link.innerHTML = '<a href="javascript:void(0);" style="color: #23ade5;">查看封面</a>';
        container.insertBefore(link, container.firstChild);
        var error = function() {
            link.innerHTML = '<span style="color: red">封面获取失败=。=</span>';
            var args = Array.from(arguments);
            args.unshift('BilibiliCover');
            args.unshift('NetworkError');
            console.error.apply(console, args)
        };
        link.querySelector("a").addEventListener("click", function() {
            var roomid = unsafeWindow.location.pathname.match(/^\/(\d+)/)[1];
            if (roomid) {
                GM_xmlhttpRequest({
                    url: "https://search.bilibili.com/api/search?search_type=live&keyword=" + roomid + "&from_source=livetop_search",
                    method: "GET",
                    onerror: error,
                    onload: function(res) {
                        console.info('BilibiliCover', 'NetworkResponse', res);
                        try {
                            response = JSON.parse(res.responseText);
                        } catch (e) {
                            response = false;
                        }
                        if (!response) error('Unable to parse response');
                        var data = response.result.live_room;
                        var cover;
                        data.forEach(function(info) {
                            if (info.roomid === +roomid && info.user_cover) cover = helper.coverImage(info.user_cover);
                        });
                        if (cover) {
                            helper.openWin(unsafeWindow, cover);
                        } else error('Unable to get the cover picture url');
                    }
                });
            }
        });
    })();
    window.addEventListener("beforeunload", function() {
        helper.closeWin();
    });
});