// ==UserScript== // @name Bilibili Popups // @namespace sheep-realms // @version 1.4.2 // @description B站内链助手 // @author Sheep-realms // @match *://*.bilibili.com/* // @require http://libs.baidu.com/jquery/2.0.0/jquery.min.js // @license CC BY-NC-SA 3.0 // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_openInTab // @grant GM_setClipborad // @run-at document-body // @downloadURL none // ==/UserScript== if (GM_getValue("popups") == undefined) { GM_setValue("popups", { dataVersion: 1, config: { useSkin: "Classic" } }); }; function Popups() { this.id = "popups"; this.$sel = "#" + this.id; this.state = 0; this.timer = 0; this.disable = false; this.deactivate = false; this.posX = 0; this.posY = 0; this.skin = []; this.getConfig = function(name) { let cfg = GM_getValue("popups"); return cfg.config[name]; } this.setConfig = function(name, value) { let cfg = GM_getValue("popups"); cfg.config[name] = value; GM_setValue("popups", cfg); } this.resetView = function(title="missingno") { $(this.$sel).html('

'+title+'



'); } this.load = function() { $("body").append('
'); this.resetView(); } this.pushSkin = function(skinObj) { this.skin.push(skinObj); } this.loadSkin = function() { let skinName = this.getConfig("useSkin"); let style = this.skin.find(function(obj) { return obj.name == skinName; }); if (style != undefined) { GM_addStyle(style.getStyle()); } } this.switchSkin = function(skinName) { let style = this.skin.find(function(obj) { return obj.name == skinName; }); if (style != undefined) { this.setConfig("useSkin", skinName); location.reload(); } } this.setTitle = function(str) { $(this.$sel + " .title").text(str); } this.setSubtitle = function(str) { $(this.$sel + " .subtitle").html(str); } this.add = function(str) { $(this.$sel + " .content").append(str); } this.move = function(top=this.posX+5, left=this.posY+5) { $(this.$sel).css("left", top).css("top", left); } this.show = function() { if (!this.disable && !this.deactivate) { $(this.$sel).removeClass('hide'); this.state = 1; } } this.hide = function() { $(this.$sel).addClass('hide'); this.state = 0; } this.setImage = function(url) { $(this.$sel + " .right-image").attr('src', url); $(this.$sel + " .right-image-box").attr('href', url); if (url != "") { $(this.$sel + " .right-image-box").removeClass('hide'); } else { $(this.$sel + " .right-image-box").addClass('hide'); } } this.error = function(title="出错啦!", message="") { this.resetView(title); $(this.$sel).append('

'+message+'

'); } this.stop = function() { this.deactivate = true; this.hide(); clearTimeout(this.timer); } } let pop = new Popups(); function PopupsFactory() { this.id = "popups"; this.$sel = "#" + this.id; this.url = function(subdomain="www", path="") { return "https://"+subdomain+".bilibili.com/"+path; } this.link = function(url="", text="", strClass="") { return ''+text+''; } this.userinfo = function(uid="", username="") { return '

作者:'+this.link(this.url("space", uid), username)+' ['+this.link(this.url("message", "#whisper/mid"+uid), "私信")+'] ('+this.link(this.url("space", uid+"/dynamic"), "动态")+' | '+this.link(this.url("space", uid+"/video"), "投稿")+' | '+this.link(this.url("space", uid+"/channel/series"), "列表")+')

'; } } let popf = new PopupsFactory(); function PopupsSkin(name="Example Popups Skin", style=[]) { this.name = name; this.styleSheets = style; this.getStyle = function() { return this.styleSheets.join(" "); } this.loadStyle = function() { GM_addStyle(this.getStyle()); } } let popSkin = new PopupsSkin("Classic", [ "#popups {max-width: 350px; min-width: 200px; font-size: 12px; position: absolute; background-color: #FFF; border: #BBB 1px solid; box-shadow: rgb(50 50 50 / 35%) 0 3px 8px; z-index: 12000; padding: 10px; color: #222;}", "#popups.hide, #popups .hide {display: none;}", "#popups table {font-size: 12px;}", "#popups .video-stat tr td:first-child {padding-right: 1.5em;}", "#popups .video-stat tr td {line-height: 1.5em;}", "#popups h4 {font-size: 14px; margin-bottom: 5px; font-weight: bold;}", "#popups p {color: #222; font-size: 12px; line-height: 1.5em;}", "#popups a {color: #00a1d6;}", "#popups hr {border: none; background-color: #BBB; height: 1px; margin: 3px 0; clear: both;}", "#popups .video-desc {max-width: 330px; max-height: 150px; padding: 5px; background-color: #F4F4F4; overflow: hidden;}", "#popups .right-image-box {float: right; line-height: 0;}", "#popups img.right-image {max-width: 120px; max-height: 50px;}", ]); let vanillaSkin = new PopupsSkin("Vanilla", [ "#popups {display: flex; flex-direction: row-reverse; width: 450px; height: 240px; font-size: 13px; position: absolute; background-color: #FFF; border: none; border-radius: 2px; box-shadow: 0 30px 90px -20px rgb(0 0 0 / 30%), 0 0 1px 1px rgb(0 0 0 / 5%); z-index: 12000; color: #222; overflow: hidden;}", "#popups.hide, #popups .hide {display: none;}", "#popups .text-box {padding: 20px; height: calc(100% - 40px); overflow-y: scroll; width: 230px; box-sizing: content-box;}", "#popups .text-box::-webkit-scrollbar {width: 5px; background: transparent;}", "#popups .text-box::-webkit-scrollbar-thumb {background: rgb(0 0 0 / 15%); border-radius: 2.5px;}", "#popups table {font-size: 13px;}", "#popups .video-stat tr td:first-child {padding-right: 1.2em;}", "#popups .video-stat tr td {line-height: 1.5em;}", "#popups h4 {font-size: 16px; margin-bottom: 5px; font-weight: bold;}", "#popups p {color: #222; font-size: 13px; line-height: 1.5em;}", "#popups a {color: #00a1d6;}", "#popups hr {border: none; background-color: #BBB; height: 1px; margin: 3px 0;}", "#popups .video-desc {max-width: 230px; max-height: 150px; padding: 5px; font-size: 12px; background-color: #F4F4F4; overflow: hidden;}", "#popups .right-image-box {float: right; line-height: 0; display: flex; align-items: center; background: #F4F4F4; width: 180px;}", "#popups img.right-image {max-width: 180px; max-height: 240px;}", ]); //popSkin.loadStyle(); pop.pushSkin(popSkin); pop.pushSkin(vanillaSkin); pop.loadSkin(); let bangumiType = ["", "番剧", "电影", "纪录片", "国创", "电视剧", "", "综艺"]; let ctrlKey = false; let altKey = false; let shiftKey = false; $(document).mousemove(function(e){ pop.posX = e.pageX; pop.posY = e.pageY; }); $(document).keydown(function(e) { pop.disable = e.altKey; ctrlKey = e.ctrlKey; altKey = e.altKey; shiftKey = e.shiftKey; }) $(document).keyup(function(e) { pop.disable = e.altKey; ctrlKey = e.ctrlKey; altKey = e.altKey; shiftKey = e.shiftKey; }) $(document).ready(function() { pop.load(); $("#popups").mouseenter(function() { // console.log(">> mouseover #popups"); clearTimeout(pop.timer); }); $("#popups").mouseleave(function() { // console.log("<< mouseleave #popups"); clearTimeout(pop.timer); pop.timer = setTimeout(function() { pop.hide(); }, 500) }); }); $(document).on("click", "#popups-skin", function() { if (pop.getConfig("useSkin") == "Classic") { if (confirm("您确定要使用 Vanilla 皮肤吗?")) { pop.switchSkin("Vanilla"); } } else if (pop.getConfig("useSkin") == "Vanilla") { if (confirm("您确定要使用 Classic 皮肤吗?")) { pop.switchSkin("Classic"); } } }); //反爬虫追踪 $(document).on("click", "#popups a", function(e) { if ($(this).data("url")) { if (ctrlKey) { GM_openInTab($(this).data("url")); return false; } else { GM_openInTab($(this).data("url"), {active: true}); return false; } } }); $(document).on("mouseenter", "a:not(#popups a)", function() { // console.log(">> mouseover a"); if (pop.disable || pop.deactivate) return false; let a = $(this).offset(); let $that = $(this); clearTimeout(pop.timer); let mode = ""; let url = $(this).attr("href"); let path = getUrlPath($(this).attr("href")); let qid; if (path.search(/\/video\/av/) != -1) { mode = "av"; qid = path.slice(9).replace("/",""); } else if (path.search(/\/audio\/au/) != -1) { mode = "au"; qid = path.slice(9).replace("/",""); } else if (path.search(/\/video\/BV/) != -1) { mode = "bv"; qid = path.slice(7).replace("/",""); } else if (path.search(/\/read\/cv/) != -1) { mode = "cv"; qid = path.slice(8).replace("/",""); } else if (path.search(/\/bangumi\/play\/ep/) != -1) { mode = "ep"; qid = path.slice(16).replace("/",""); } else if (path.search(/\/bangumi\/play\/ss/) != -1) { mode = "ss"; qid = path.slice(16).replace("/",""); } else if (url.search(/space.bilibili.com/) != -1) { mode = "user"; if (path == "space.bilibili.com" || path == "/") return false; if (path.search(/\/[a-z]/) != -1) { qid = path.slice(1,path.search(/\/[a-z]/)); } else { if (path.slice(-1) == "/") { qid = path.slice(1, -1); } else { qid = path.slice(1); } } } else { return false; } pop.timer = setTimeout(function() { $(".popups-focus").removeClass("popups-focus"); $that.addClass("popups-focus"); pop.resetView("加载中..."); if (mode == "av") { getVideoInfoAV(qid); } if (mode == "au") { getAudioInfo(qid); } if (mode == "bv") { getVideoInfoBV(qid); } if (mode == "cv") { getArticleInfo(qid); } if (mode == "ss" || mode == "ep") { getBangumiInfo(qid, mode); } if (mode == "user") { getUserInfo(qid); } pop.move(); pop.show(); }, 500) }); $(document).on("mouseleave", "a:not(#popups a)", function() { // console.log("<< mouseleave a"); let $that = $(this); if ($that.hasClass("popups-focus")) { clearTimeout(pop.timer); pop.timer = setTimeout(function() { pop.hide(); $that.removeClass("popups-focus"); }, 500) } else { pop.hide(); clearTimeout(pop.timer); } }); function getUrlPath(url){ var arrUrl = url.split("//"); var start = arrUrl[arrUrl.length - 1].indexOf("/"); var relUrl = arrUrl[arrUrl.length - 1].substring(start); if(relUrl.indexOf("?") != -1){ relUrl = relUrl.split("?")[0]; } return relUrl; } function getJSONInfo(url) { $.getJSON(url, function (ajson) { console.log(ajson); }); } function getVideoInfoAV(aid) { $.getJSON("https://api.bilibili.com/x/web-interface/view?aid=" + aid, function (ajson) { if (ajson.code == 0) { factoryVideoInfo(ajson.data); } else { pop.error("出错啦!", "未能获取视频信息,可能是网络问题,或是视频已被删除。又或者是作者写了个BUG!"); } }); } function getVideoInfoBV(bvid) { $.getJSON("https://api.bilibili.com/x/web-interface/view?bvid=" + bvid, function (ajson) { if (ajson.code == 0) { factoryVideoInfo(ajson.data); } else { pop.error("出错啦!", "未能获取视频信息,可能是网络问题,或是视频已被删除。又或者是作者写了个BUG!"); } }); } function factoryVideoInfo(obj) { pop.resetView(obj.title); pop.setSubtitle('

'+popf.link(popf.url('www','video/av'+obj.aid), 'av'+obj.aid)+' | '+popf.link(popf.url('www','video/'+obj.bvid), obj.bvid)+'

'); pop.add(popf.userinfo(obj.owner.mid, obj.owner.name)); pop.add('

分区:'+obj.tname+'

'); pop.add('

发布时间:'+getDateTime(obj.pubdate)+'

'); pop.add('

播放:'+obj.stat.view+'

'); pop.add('
'); $("#popups .video-stat").append('点赞:'+obj.stat.like+'投币:'+obj.stat.coin+''); $("#popups .video-stat").append('弹幕:'+obj.stat.danmaku+'评论:'+obj.stat.reply+''); $("#popups .video-stat").append('收藏:'+obj.stat.favorite+'分享:'+obj.stat.share+''); //pop.add('

时长:'+obj.duration+'

'); pop.add('
'); pop.add('

BiliPlus

'); pop.add('

查看视频封面

'); pop.setImage(obj.pic); pop.add('
'); pop.add('

简介:

'); pop.add('

'+obj.desc+'

'); } function getArticleInfo(cvid) { $.getJSON("https://api.bilibili.com/x/article/viewinfo?id="+cvid, function (ajson) { if (ajson.code == 0) { let obj = ajson.data; pop.resetView(obj.title); pop.setSubtitle('

cv'+cvid+'

'); pop.add(popf.userinfo(obj.mid, obj.author_name)); pop.add('

阅读:'+obj.stats.view+'

'); pop.add('
'); $("#popups .video-stat").append('点赞:'+obj.stats.like+'投币:'+obj.stats.coin+''); $("#popups .video-stat").append('收藏:'+obj.stats.favorite+'分享:'+obj.stats.share+''); $("#popups .video-stat").append('评论:'+obj.stats.reply+'动态转发:'+obj.stats.dynamic+''); pop.add('
'); pop.add('

查看文章头图

'); pop.setImage(obj.banner_url); } else { pop.error("出错啦!", "未能获取专栏信息,可能是网络问题,或是专栏已被删除。又或者是作者写了个BUG!"); } }); } function getAudioInfo(auid) { $.getJSON("https://www.bilibili.com/audio/music-service-c/web/song/info?sid="+auid, function (ajson) { if (ajson.code == 0) { let obj = ajson.data; pop.resetView(obj.title); pop.setSubtitle('

'+popf.link(popf.url("www","audio/au"+auid), "au"+auid)+'

'); pop.add(popf.userinfo(obj.uid, obj.uname)); pop.add('

发布时间:'+getDateTime(obj.passtime)+'

'); pop.add('

播放:'+obj.statistic.play+'

'); pop.add('
'); $("#popups .video-stat").append('投币:'+obj.coin_num+'收藏:'+obj.statistic.collect+''); $("#popups .video-stat").append('评论:'+obj.statistic.comment+'分享:'+obj.statistic.share+''); pop.add('
'); pop.add('

查看音频封面

'); pop.setImage(obj.cover); pop.add('
'); pop.add('

简介:

'); pop.add('

'+obj.intro+'

'); } else { pop.error("出错啦!", "未能获取音频信息,可能是网络问题,或是音频已被删除。又或者是作者写了个BUG!"); } }); } function getBangumiInfo(ssid, type) { let geturl; if (type == "ep") { geturl = "https://api.bilibili.com/pgc/view/web/season?ep_id="; } else { geturl = "https://api.bilibili.com/pgc/view/web/season?season_id="; } $.getJSON(geturl+ssid, function (ajson) { if (ajson.code == 0) { let obj = ajson.result; pop.resetView(obj.season_title); if (type == "ep") { pop.setSubtitle('

'+popf.link(popf.url("www","bangumi/play/ep"+ssid), "ep"+ssid)+'

'); } else { pop.setSubtitle('

'+popf.link(popf.url("www","bangumi/play/ss"+ssid), "ss"+ssid)+'

'); } //pop.add(popf.userinfo(obj.uid, obj.uname)); pop.add('

'+obj.new_ep.desc+'

'); pop.add('

类型:'+bangumiType[obj.type]+'

'); pop.add('

发布时间:'+obj.publish.pub_time+'

'); pop.add('

总集数:'+(obj.total != -1 ? obj.total : "未知")+'

'); pop.add('

播放:'+obj.stat.views+'

'); pop.add('
'); $("#popups .video-stat").append('投币:'+obj.stat.coins+'收藏:'+obj.stat.favorites+''); $("#popups .video-stat").append('弹幕:'+obj.stat.danmakus+'评论:'+obj.stat.reply+''); $("#popups .video-stat").append('分享:'+obj.stat.share+''); pop.add('
'); pop.add('

查看剧集简介

'); pop.add('

查看剧集封面

'); pop.setImage(obj.cover); pop.add('

查询萌娘百科

'); pop.add('
'); pop.add('

简介:

'); pop.add('

'+obj.evaluate+'

'); } else { pop.error("出错啦!", "未能获取音频信息,可能是网络问题,或是音频已被删除。又或者是作者写了个BUG!"); } }); } function getUserInfo(uid) { pop.resetView("获取用户信息..."); pop.setSubtitle('

UID:'+popf.link(popf.url("space", uid, "user-uid"), uid)+'

'); pop.add('

关注:'+popf.link(popf.url("space", uid+"/fans/follow"), "...", "user-friend")+' | 粉丝:'+popf.link(popf.url("space", uid+"/fans/fans"), "...", "user-fans")+'

'); $.getJSON("https://api.bilibili.com/x/space/acc/info?mid="+uid, function (ajson) { if (ajson.code == 0) { let obj = ajson.data; pop.setTitle(obj.name); $("#popups .user-uid").text(obj.mid); pop.add('

等级:Lv'+obj.level+'

'); pop.add('
'); pop.add('

私信 | 动态 | 投稿 | 列表

'); pop.add('

查看头像

'); pop.add('

查看主页头图

'); pop.setImage(obj.face); } }); $.getJSON("https://api.bilibili.com/x/web-interface/card?mid="+uid, function (ajson) { if (ajson.code == 0) { let obj = ajson.data.card; $("#popups .user-friend ").text(obj.friend); $("#popups .user-fans").text(obj.fans); } }); } function getDateTime(stamp) { let t = new Date(stamp * 1000); return t.getFullYear() + '-' + (t.getMonth() + 1) + '-' + t.getDate() + ' ' + timeZero(t.getHours()) + ':' + timeZero(t.getMinutes()) + ':' + timeZero(t.getSeconds()); } function timeZero(value) { return value < 10 ? "0" + value : value }