Bilibili-Evolved/min/download-danmaku.min.js
2020-11-10 13:31:04 +08:00

1 line
4.0 KiB
JavaScript

(()=>(n,t)=>{const{getFriendlyTitle:e}=t.import("title");const{DanmakuConverter:o,XmlDanmaku:a}=t.import("danmaku-converter");const s=async()=>{const n=e();const t={font:"微软雅黑",alpha:.4,duration:n=>{switch(n.type){case 4:case 5:return 4;default:return 6}},blockTypes:[7,8],resolution:{x:1920,y:1080},bottomMarginPercent:.15,bold:false};let o={...t,title:n};try{await loadDanmakuSettingsPanel();const n=localStorage.getItem("bilibili_player_settings");if(n){const t=JSON.parse(n);const e=(n,e)=>_.get(t,`setting_config.${n}`,e);o.blockTypes=(()=>{const n=[];const e={scroll:[1,2,3],top:[5],bottom:[4],color:["color"]};for(const[o,a]of Object.entries(e)){if(_.get(t,`block.type_${o}`,true)===false){n.push(...a)}}return n.concat(7,8)})();o.bold=e("bold",false);o.alpha=_.clamp(1-parseFloat(e("opacity","0.4")),0,1);const a=1.4-.4*e("fontsize",1);o.resolution={x:Math.round(1920*a),y:Math.round(1080*a)};o.duration=(()=>{const n=18-3*e("speedplus",0);return t=>{switch(t.type){case 4:case 5:return 4;default:return n}}})();const s=e("danmakuArea",0);o.bottomMarginPercent=s>=100?0:s/100;if(o.bottomMarginPercent===0&&e("preventshade",false)){o.bottomMarginPercent=.15}const c=_.get(t,"block.list",[]);o.blockFilter=n=>{for(const t of c){if(!t.s){continue}switch(t.t){case"keyword":{if(n.content.includes(t.v)){return false}break}case"regexp":{if(new RegExp(t.v).test(n.content)){return false}break}case"user":{if(n.userHash===t.v){return false}break}}}return true}}else{console.warn("[弹幕转换] 未找到播放器设置");o={...o,...t}}o.font=dq(".bilibili-player-video-danmaku-setting-right-font .bui-select-result").innerText}catch(n){logError(n);o={...o,...t}}for(const[n,e]of Object.entries(o)){if(e===undefined||e===null){console.warn("danmaku config invalid for key",n,", value =",e);o[n]=t[e]}}console.log(o);return o};async function c(n){const t=new o(await s());const e=t.xmlStringToAssDocument(n);return e.generateAss()}const r=async n=>{const t=new o(await s());const e=t.xmlDanmakuToAssDocument(n.xmlDanmakus.map((n=>new a(n))));return e.generateAss()};async function i(n){const c=e();let r;const i=(unsafeWindow||window).aid;const l=parseInt((unsafeWindow||window).cid);const{DanmakuInfo:u,JsonDanmaku:d}=await t.importAsync("video-info");switch(n){case"xml":{const n=new u(l);await n.fetchInfo();r=new Blob([n.rawXML],{type:"text/xml"});break}case"json":{const n=await new d(i,l).fetchInfo();r=new Blob([JSON.stringify(n.jsonDanmakus)],{type:"text/json"});break}case"ass":{console.log("start ass");const n=await new d(i,l).fetchInfo();console.log("get json danmaku");const t=new o(await s());console.log("get config");const e=n.xmlDanmakus.map((n=>new a(n)));console.log("map");const c=t.xmlDanmakuToAssDocument(e);console.log("convert");r=new Blob([c.generateAss()],{type:"text/ass"});break}}const f=URL.createObjectURL(r);const m=dq("#danmaku-link");const p=m.getAttribute("href");if(p){URL.revokeObjectURL(p)}m.setAttribute("download",`${c}.${n}`);m.setAttribute("href",f);m.click()}return{export:{downloadDanmaku:i,convertToAss:c,convertToAssFromJson:r,getUserDanmakuConfig:s},widget:{content:`\n<a id="danmaku-link" style="display:none"></a>\n<button\n class="gui-settings-flat-button"\n id="download-danmaku-xml">\n<i class="icon-danmaku"></i>\n<span>下载弹幕<span>(XML)</span></span>\n</button>\n<button\n class="gui-settings-flat-button"\n id="download-danmaku-json">\n<i class="icon-danmaku"></i>\n<span>下载弹幕<span>(JSON)</span></span>\n</button>\n<button\n class="gui-settings-flat-button"\n id="download-danmaku-ass">\n<i class="icon-danmaku"></i>\n<span>下载弹幕<span>(ASS)</span></span>\n</button>\n`,condition:async()=>{let n=await SpinQuery.select((()=>(unsafeWindow||window).cid));return Boolean(n)},success:()=>{const n=["xml","json","ass"];const t=n.map((n=>dq(`#download-danmaku-${n}`)));const e=(n,e)=>{n.addEventListener("click",(async()=>{try{t.forEach((n=>n.disabled=true));await i(e)}catch(n){logError(n)}finally{t.forEach((n=>n.disabled=false))}}))};n.forEach(((n,o)=>{e(t[o],n)}))}}}})();