// ==UserScript== // @name 清水河畔音视频播放 // @namespace bbs.uestc.edu.cn // @license MIT // @author ____ // @version 0.3.1 // @description 通过 HTML5 多媒体功能播放帖子中上传的音视频附件。 // @match *://bbs.uestc.edu.cn/forum.php* // @connect b23.tv // @connect bilibili.com // @grant GM_xmlhttpRequest // @run-at document-end // @downloadURL none // ==/UserScript== function makeAv(container, a, kind) { let media = document.createElement(kind); media.controls = true; media.src = a.href; media.style.maxWidth = '100%'; media.style.maxHeight = '80vh'; media.style.display = 'block'; media.style.margin = '0.5em auto'; a.outerHTML = media.outerHTML; let outer = container.querySelector('dl.tattl'); if (outer) { outer.style.width = 'auto'; outer.style.height = 'auto'; } let outer2 = container.querySelector('p.attnm'); if (outer2) { outer2.style.height = 'auto'; } let icon = container.querySelector('dl.tattl > dt'); if (icon) { icon.style.display = 'none'; } } [].forEach.call(document.querySelectorAll('#postlist ignore_js_op'), el => { let a = el.querySelector('a'); if (a.href.match(/https?:\/\/.*?forum\.php\?mod=attachment&/)) { let fileName = a.textContent.trim(); if (fileName.match(/\.(?:mp4|flv)/i)) { makeAv(el, a, 'video'); } else if (fileName.match(/\.(?:mp3)/i)) { makeAv(el, a, 'audio'); } } }); function getRedirectUrl(url) { return new Promise(resolve => { if (window.GM_xmlhttpRequest) { GM_xmlhttpRequest({ method: 'HEAD', url, onload: r => resolve(r.finalUrl), }) } else { chrome.runtime.sendMessage({request: 'getRedirectUrl', url}).then(r => r && r.url && resolve(r.url)); } }); } function createIframe(src, extra) { let el = document.createElement('iframe'); el.style.display = 'block'; el.style.width = '80%'; el.style.aspectRatio = '16 / 9' el.style.margin = '0.5em auto'; el.allowFullscreen = true; if (extra && extra.allow) { el.allow = extra.allow; } el.src = src; return el; } function makeBvPlayer(bv) { return createIframe(`https://player.bilibili.com/player.html?bvid=${encodeURIComponent(bv)}`); } function makeBilibiliLivePlayer(id) { return createIframe(`https://www.bilibili.com/blackboard/live/live-activity-player.html?cid=${id}&quality=0`, { allow: 'encrypted-media', }); } const externalAvHandlers = [ { regex: /https?:\/\/b23\.tv\/([^/?]+)/i, handler: url => getRedirectUrl(url).then(url => matchHandlers(url)), }, { regex: /https?:\/\/(?:www|m)\.bilibili\.com\/video\/(BV[^/?]+)/i, handler: (url, match) => Promise.resolve(makeBvPlayer(match[1])), }, { regex: /https?:\/\/live\.bilibili\.com\/([0-9]+)/i, handler: (_, match) => Promise.resolve(makeBilibiliLivePlayer(match[1])), }, ]; function matchHandlers(url, extra) { for (let {regex, handler} of externalAvHandlers) { let match = url.match(regex); if (match) { return handler(url, match); } } return Promise.reject(); } [].forEach.call(document.querySelectorAll('#postlist table.plhin .t_fsz table a'), a => { matchHandlers(a.href).then(el => { let e = a.insertAdjacentElement('afterend', document.createElement('br')); e = e.insertAdjacentElement('afterend', el); e = e.insertAdjacentElement('afterend', document.createElement('br')); }); });