Widget:BilibiliVideo:修订间差异
跳到导航
跳到搜索
imported>=海豚= 无编辑摘要 |
imported>=海豚= 无编辑摘要 |
||
| 第110行: | 第110行: | ||
} | } | ||
</style><script> | </style><script> | ||
"use strict"; | "use strict"; | ||
window.RLQ.push( | window.RLQ.push(() => { | ||
if (mw.config.get("AnnTools-BilibiliVideo-running", false)) { | |||
return; | |||
return; | } | ||
mw.config.set("AnnTools-BilibiliVideo-running", true); | |||
const isNaN = Number.isNaN || window.isNaN; | |||
const temp = new Set(); | |||
const cssLengthUnitValidator = (length, defaultValue, callback) => { | |||
if (typeof length !== "string" || length.length === 0) { | |||
callback(false); | |||
return defaultValue; | |||
} | } | ||
const parsedNumber = parseFloat(length.replace(/[a-z]+/i, "")); | |||
if (isNaN(parsedNumber) || parsedNumber <= 0) { | |||
callback(false); | callback(false); | ||
return defaultValue; | return defaultValue; | ||
}; | } | ||
class Converter { | if (/^(?:\d+|\d*\.\d+)(?:em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|Q|in|pc|pt|px|%)$/.test(length)) { | ||
callback(true); | |||
return length; | |||
} | |||
if (/^(?:\d+|\d*\.\d+)$/.test(length)) { | |||
callback(true); | |||
return `${length}px`; | |||
} | |||
callback(false); | |||
return defaultValue; | |||
}; | |||
class Converter { | |||
constructor() { | |||
this._base58Table = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF"; | |||
this._digitMap = [11, 10, 3, 8, 4, 6]; | |||
this._xor = 177451812; | |||
this._add = 8728348608; | |||
this._aidRegExp = /(?:av)\d{1,9}/ig; | |||
this._bvidRegExp = /(?:[bB][vV])?1?[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/g; | |||
this._bvidTemplate = ["B", "V", "1", "", "", "4", "", "1", "", "7", "", ""]; | |||
} | |||
_bvTobvid(bv) { | |||
if (bv.length === 12) { | |||
return bv; | |||
} else if (bv.length === 10) { | |||
return `BV${bv}`; | |||
} else if (bv.length === 9) { | |||
return `BV1${bv}`; | |||
} | } | ||
throw new Error("BV's length must be 9, 10 or 12"); | |||
} | |||
_bvidToAid(bvid) { | |||
let r = 0; | |||
for (let i = 0; i < 6; i++) { | |||
r += this._base58Table.indexOf(bvid[this._digitMap[i]]) * 58 ** i; | |||
} | } | ||
return `av${r - this._add ^ this._xor}`; | |||
} | |||
bvidToAid(str) { | |||
return str.replace(this._bvidRegExp, (bv) => { | |||
return this._bvidToAid(this._bvTobvid(bv)); | |||
}); | |||
} | |||
_avToAid(av) { | |||
if (/^av/i.test(av)) { | |||
return av; | |||
} | } | ||
return `av${av}`; | |||
} | |||
_aidToBvid(aid) { | |||
const av = (+aid.replace(/^av/g, "") ^ this._xor) + this._add; | |||
const bvidClone = Array.from(this._bvidTemplate); | |||
for (let i = 0; i < 6; i++) { | |||
bvidClone[this._digitMap[i]] = this._base58Table[Math.floor(av / 58 ** i) % 58]; | |||
} | } | ||
_avToAid(av) { | return bvidClone.join(""); | ||
if (/^av/i.test(av)) { | } | ||
aidToBvid(str) { | |||
return str.replace(this._aidRegExp, (av) => { | |||
return this._aidToBvid(this._avToAid(av)); | |||
}); | |||
} | |||
} | |||
const converter = new Converter(); | |||
if (mw.config.get("skin") === "minerva") { | |||
$(".bilibili-video-container:not(.bilibili-video-initialized)").each(function () { | |||
const element = $(this), | |||
dataset = this.dataset; | |||
element.addClass("bilibili-video-initialized"); | |||
const _id = dataset.id, | |||
id = _id.replace(/^[ab]v/i, ""), | |||
title = dataset.title, | |||
pagename = dataset.pagename, | |||
t = parseInt(dataset.t), | |||
tIsInvalid = isNaN(t) || t <= 0, | |||
subtitle = dataset.subtitle === "true" ? true : false; | |||
let page = parseInt(dataset.page); | |||
if (isNaN(page) || page < 1) { page = 1; } | |||
let prefix; | |||
let decode = null; | |||
if (/^(?:av)?\d{1,9}$/i.test(_id)) { | |||
prefix = { | |||
href: "av", | |||
iframe: "aid", | |||
}; | |||
} else if (/^(?:bv)?[\da-z]{10}$/i.test(_id)) { | |||
prefix = { | |||
href: "BV", | |||
iframe: "bvid", | |||
}; | |||
if (!converter._bvidRegExp.test(_id)) { | |||
temp.add(_id); | |||
} else { | |||
decode = converter.bvidToAid(_id); | |||
} | } | ||
} else { | |||
if (/^(?:av)?\d{10,}$/i.test(_id)) { | |||
} | temp.add(_id); | ||
} | } | ||
return | return this.outerHTML = "<i>id错误</i>"; | ||
} | } | ||
$.ajax({ | |||
url: `https://mgwbcprd.azureedge.net/BilibiliMeta/Index/${encodeURIComponent(typeof decode === "string" ? decode : prefix.href + id)}`, | |||
type: "GET", | |||
timeout: 10000, | |||
success: function (data) { | |||
const list = data.VideoEntities | |||
.map((e, i) => { | |||
e.page = i + 1; | |||
e.title = e.Title.replace(/^\d+、/, ""); | |||
return e; | |||
}); | |||
let _page = 1; | |||
const name = title || (data.Title ? data.Title : prefix.href + id); | |||
let index; | |||
let length; | |||
if (pagename) { | |||
for (index = 0, length = list.length; index < length; index++) { | |||
if (list[index].Title !== pagename && list[index].title !== pagename) { continue; } | |||
_page = list[index].page; | |||
break; | |||
} | |||
} else { _page = page; } | |||
index = _page - 1; | |||
let sec = `${t % 60}`; | |||
if (sec.length === 1) { sec = `0${sec}`; } | |||
const time = `${Math.floor(t / 60)}:${sec}`; | |||
const button = $("<a/>").addClass("bilibili-video-button").attr("rel", "nofollow noreferrer noopener").attr("href", `https://www.bilibili.com/video/${prefix.href}${id}?p=${_page}${tIsInvalid ? "" : `&t=${t}`}`).text(`${name} [${_page}/${list.length}]${tIsInvalid ? "" : `[跳转至${time}]`}`); | |||
if (list[index] !== undefined && list[index].VideoCid !== undefined && subtitle) { | |||
button.append(`<br> (${_page}、${list[index].Title})`); | |||
} | |||
element.before(button).remove(); | |||
}, | |||
error: function () { | |||
element.before($("<a/>").addClass("bilibili-video-button").attr("rel", "nofollow noreferrer noopener").attr("href", `https://www.bilibili.com/video/${prefix.href}${id}?p=${page}${tIsInvalid ? "" : `&t=${t}`}`).text((title || prefix.href + id) + ([0, 1].indexOf(page) !== -1 && !isNaN(page) ? ` (P${page})` : ""))).remove(); | |||
}, | |||
}); | |||
}); | |||
} | |||
else { | |||
const global_element = $("#mw-content-text"); | |||
let lazyLoadObserver; | |||
if ("IntersectionObserver" in window && | |||
"IntersectionObserverEntry" in window && | |||
"intersectionRatio" in window.IntersectionObserverEntry.prototype && | |||
"isIntersecting" in window.IntersectionObserverEntry.prototype) { | |||
lazyLoadObserver = new IntersectionObserver((entries) => { | |||
entries.forEach((entry) => { | |||
if (entry.isIntersecting) { | |||
entry.target.src = entry.target.dataset.src; | |||
lazyLoadObserver.unobserve(entry.target); | |||
} | |||
}); | }); | ||
} | }); | ||
} else { | |||
lazyLoadObserver = { | |||
observe: (target) => { | |||
target.src = target.dataset.src; | |||
}, | |||
}; | |||
} | } | ||
const | const iframe_href_base = "https://www.bilibili.com/blackboard/newplayer.html?playlist=true&playlist_order=sequential&musth5=1&noEndPanel=1&crossDomain=1&autoplay=0&"; | ||
const EPSILON = 2.220446049250313e-16, | |||
rememberWH = function rememberWH(ele) { | |||
const | ele.data({ width: ele.width(), height: ele.height() }); | ||
}, | |||
setTureHeight = function setTureHeight(ele) { | |||
const barHeight = ele.data("height") - ele.data("width") * 9 / 16; //计算标题和播放器控制栏高度 | |||
ele.height(ele.width() * 9 / 16 + barHeight); | |||
}, | |||
setWH = function setWH(ele) { | |||
ele.css({ width: "100%", height: "100%" }); | |||
}, | |||
recallWH = function recallWH(ele) { | |||
ele.width(ele.data("width")).height(ele.data("height")); | |||
}, | |||
setMaxHeight = function setMaxHeight(container, target) { | |||
const h = container.outerHeight(true); | |||
let t = 0; | |||
container.children().each(function () { | |||
t += $(this).outerHeight(true); | |||
}); | |||
target.css("max-height", `calc(100% - ${parseInt(t - h + 2 - (Number.EPSILON || EPSILON))}px)`); | |||
}; | |||
$(".bilibili-video-container").addClass("exec").each(function () { | |||
const dataset = this.dataset, | |||
_id = dataset.id, | |||
id = _id.replace(/^[ab]v/i, ""), | |||
selfbox = $(this); | |||
let prefix; | |||
let decode = null; | |||
if (/^(?:av)?\d{1,9}$/i.test(_id)) { | |||
prefix = { | |||
href: "av", | |||
iframe: "aid", | |||
}; | |||
} else if (/^(?:bv)?[\da-z]{10}$/i.test(_id)) { | |||
prefix = { | |||
href: "BV", | |||
iframe: "bvid", | |||
}; | |||
if (!converter._bvidRegExp.test(_id)) { | |||
temp.add(_id); | |||
} else { | } else { | ||
if (/^(?:av)?\d{10,}$/i.test(_id)) { | decode = converter.bvidToAid(_id); | ||
} | |||
} else { | |||
if (/^(?:av)?\d{10,}$/i.test(_id)) { | |||
temp.add(_id); | |||
} | } | ||
return this.outerHTML = "<i>id错误</i>"; | |||
} | |||
let page = parseInt(+(dataset.page || 1)); | |||
if (isNaN(page) || page < 1) { page = 1; } | |||
const pagename = dataset.pagename; | |||
const title = dataset.title; | |||
const height = cssLengthUnitValidator(dataset.height, "441px", (isValidated) => isValidated || $(this).removeAttr("data-height")); | |||
const width = cssLengthUnitValidator(dataset.width, "665px", (isValidated) => isValidated || $(this).removeAttr("data-width")); | |||
const maxHeight = cssLengthUnitValidator(dataset.maxHeight, undefined, (isValidated) => isValidated || $(this).removeAttr("data-max-height")); | |||
const maxWidth = cssLengthUnitValidator(dataset.maxWidth, undefined, (isValidated) => isValidated || $(this).removeAttr("data-max-width")); | |||
const subtitle = dataset.subtitle === "true" ? true : false; | |||
const t = parseInt(dataset.t); | |||
const tIsInvalid = isNaN(t) || t <= 0; | |||
const iframeContainer = $(this).find(".bilibili-iframe-container"); | |||
const title_text = $("<a/>").attr("rel", "nofollow noreferrer noopener").addClass("external text").attr({ | |||
href: `https://www.bilibili.com/video/${prefix.href}${id}?p=${page}${tIsInvalid ? "" : `&t=${t}`}`, | |||
target: "_blank", | |||
}).prependTo($(this).find(".bilibili-title")); | |||
const iframe = $("<iframe/>").attr({ | |||
frameborder: 0, | |||
scrolling: "no", | |||
src: "", | |||
allowfullscreen: true, | |||
"class": "bilibili-iframe", | |||
}).css({ | |||
width: width, | |||
height: height, | |||
"max-width": maxWidth, | |||
"max-height": maxHeight, | |||
}); | |||
if (!tIsInvalid) { selfbox.removeAttr("data-auto-expand"); } | |||
let sec = `${t % 60}`; | |||
if (sec.length === 1) { sec = `0${sec}`; } | |||
const time = `${Math.floor(t / 60)}:${sec}`; | |||
title_text.text(`${(title || prefix.href + id) + ([0, 1].indexOf(page) === -1 ? ` (${page})` : "") + (tIsInvalid ? "" : `[视频从${time}开始播放]`)}【视频信息加载中……】`); | |||
iframeContainer.css({ | |||
width: width, | |||
height: height, | |||
"max-width": maxWidth, | |||
"max-height": maxHeight, | |||
}); | |||
iframe.appendTo(iframeContainer); | |||
window.setTimeout(() => { //异步出去不要卡主线程 | |||
$.ajax({ | $.ajax({ | ||
url: | url: `https://mgwbcprd.azureedge.net/BilibiliMeta/Index/${encodeURIComponent(typeof decode === "string" ? decode : prefix.href + id)}`, | ||
type: "GET", | type: "GET", | ||
timeout: 10000, | timeout: 10000, | ||
success: function (data) { | success: function (data) { | ||
const list = data.VideoEntities | const list = data.VideoEntities | ||
.map( | .map((e, i) => { | ||
e.page = i + 1; | e.page = i + 1; | ||
e.title = e.Title.replace(/^\d+、/, ""); | e.title = e.Title.replace(/^\d+、/, ""); | ||
| 第259行: | 第406行: | ||
} else { _page = page; } | } else { _page = page; } | ||
index = _page - 1; | index = _page - 1; | ||
const href = title_text.attr("href"); | |||
if ( | if (list[index] !== undefined && list[index].VideoCid !== undefined) { | ||
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${_page}${tIsInvalid ? "" : `&t=${t}`}`); | |||
title_text.attr("href", href.replace(new RegExp(`\\?p=${page}`, "g"), `?p=${_page}`)); | |||
title_text.text(`${name} [${_page}/${list.length}]${tIsInvalid ? "" : `[ 视频从${time}开始播放]`}`); | |||
if (subtitle) { title_text.append(`<br>(${_page} 、${list[index].Title})`); } | |||
} else { | |||
title_text.text(name + (tIsInvalid ? "" : `[视频从${time}开始播放]`)); | |||
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${_page}${tIsInvalid ? "" : `&t=${t}`}`); | |||
} | } | ||
lazyLoadObserver.observe(iframe[0]); | |||
}, | }, | ||
error: function () { | error: function (e) { | ||
title_text.text((title || prefix.href + id) + ([0, 1].indexOf(page) === -1 ? ` (${page})` : "") + (tIsInvalid ? "" : `[视频从${time}开始播放]`)); | |||
if (e && e.responseJSON && e.responseJSON.message && e.responseJSON.message === "Authentication is required for accessing this video.") { title_text.parent().append('<sup title="“Bilibili采用会员制,大部分投稿视频会员与游客都可以观看,\n 但部分视频在UP主设定下只有会员才可以观看(这些视频常被称为‘只有会员才知道的世界’)。”\n - Bilibili#用户制度 @ ZhMoegirl\n在这种情况下我们无法为您解析视频及其分P标题、分P数量等。">(只有会员才知道的世界)</sup>'); } | |||
iframe.attr("data-src", `${iframe_href_base + prefix.iframe}=${id}&page=${page}${tIsInvalid ? "" : `&t=${t}`}`); | |||
lazyLoadObserver.observe(iframe[0]); | |||
}, | }, | ||
}); | }); | ||
}, 137); | |||
//toggle | |||
selfbox.find(".bilibili-toggle").on("click", function () { | |||
selfbox.width(iframeContainer.outerWidth(true)); | |||
selfbox.toggleClass("onshow"); | |||
iframeContainer.toggle(); | |||
if ($(this).text() === "显示视频") { | |||
$(this).text("隐藏视频"); | |||
$(window).resize(); | |||
} else { | |||
$(this).text("显示视频"); | |||
selfbox.removeAttr("style"); | |||
} | |||
}); | }); | ||
selfbox.find(".bilibili-widescreen").on("click", function () { | |||
if (selfbox.is(":not(.onshow)")) { return; } | |||
if (selfbox.is(".widescreen")) { | |||
selfbox.removeClass("widescreen"); | |||
$(this).text(" 显示宽屏"); | |||
recallWH(iframeContainer); | |||
recallWH(iframe); | |||
recallWH(selfbox); | |||
} else { | } else { | ||
selfbox.addClass("widescreen"); | |||
$(this).text("退出宽屏"); | |||
rememberWH(selfbox); | |||
selfbox.css("width", selfbox.parent().width() > Math.min(911, global_element.width()) ? "73%" : "100%"); //可以看见按钮的最小宽度 665 的 1/0.73 倍 | |||
setTureHeight(selfbox); | |||
rememberWH(iframe); | |||
rememberWH(iframeContainer); | |||
setWH(iframe); | |||
setWH(iframeContainer); | |||
iframeContainer.height(selfbox.height() - title_text.parent().height()); | |||
setMaxHeight(selfbox, iframeContainer); | |||
} | } | ||
}); | }); | ||
}); | |||
$(window).on("resize", () => { | |||
$(".bilibili-video-container.onshow.widescreen").each(function () { | |||
const selfbox = $(this); | |||
selfbox.css("width", selfbox.parent().width() > Math.min(911, global_element.width()) ? "73%" : "100%"); | |||
setTureHeight(selfbox); | |||
setMaxHeight(selfbox, selfbox.find(".bilibili-iframe-container")); | |||
}); | }); | ||
}); | |||
setTimeout(() => { | |||
$('.bilibili-video-container.exec[data-auto-expand="true"]').find(".bilibili-toggle").click(); | |||
}, 100); | |||
} | |||
setTimeout(async () => { | |||
if (temp.size > 0 && mw.config.get("wgUserGroups").includes("autoconfirmed")) { | |||
const raw = await $.get(`https://zh.moegirl.org/User:AnnAngela/SandBox/bvid?action=raw&ctype=application/json&_=${Math.random()}`); | |||
let flags = false; | |||
for (const i of temp) { | |||
if (!(i in raw)) { | |||
flags = true; | |||
raw[i] = mw.config.get("wgPageName"); | |||
} | } | ||
} | } | ||
if (flags) { | |||
}); | new mw.Api().postWithToken("csrf", { | ||
action: "edit", | |||
title: "User:AnnAngela/SandBox/bvid", | |||
text: JSON.stringify(raw), | |||
summary: `[[Widget:BilibiliVideo|BilibiliVideo]]:bvid不符合格式 - ${Array.from(temp.values()).filter(bvid => !raw.includes(bvid)).join(", ")}`, | |||
tags: "Automation tool", | |||
minor: true, | |||
bot: true, | |||
nocreate: true, | |||
watchlist: "nochange", | |||
contentformat: "application/json", | |||
contentmodel: "json", | |||
}); | |||
} | |||
} | |||
}, 1); | |||
}); | }); | ||
</script><!--{/if}--> | </script><!--{/if}--> | ||
</includeonly> | </includeonly> | ||
2020年6月28日 (日) 18:47的版本
| 名称: | Bilibili视频插件 |
| 作者: | 加大号的猫 |
| 修订: | Boxsnake |
| 重修订: | AnnAngela |
| H5版再修订: | |
| 新H5版又修订: | |
| 移动版支持: | XYZ指示物 |
| 版权协定: | MIT |
| 发布日期: | 2012年6月29日第一版发布; |
| 发布地址: | https://zh.moegirl.org.cn/Widget:BilibiliVideo && https://zh.moegirl.org.cn/Template:BilibiliVideo |
| 注意事项: | 如有问题,请联系作者。 |
本Widget不能单独使用,请使用{{BilibiliVideo}}!