From b9267f0a41fe1bfb48f40ec3b8f85ffabf0f5e43 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 30 Dec 2018 16:38:13 +0800 Subject: [PATCH] Add download video for bangumi --- bilibili-evolved.offline.user.js | 9 +- bilibili-evolved.preview-offline.user.js | 9 +- bilibili-evolved.preview.user.js | 5 +- bilibili-evolved.user.js | 5 +- min/download-video.min.js | 2 +- version.txt | 2 +- video/download-video/download-video.js | 116 ++++++++++++----------- 7 files changed, 80 insertions(+), 68 deletions(-) diff --git a/bilibili-evolved.offline.user.js b/bilibili-evolved.offline.user.js index 221152615..4b7858498 100644 --- a/bilibili-evolved.offline.user.js +++ b/bilibili-evolved.offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Offline) -// @version 166.19 +// @version 167.04 // @description 增强哔哩哔哩Web端体验(离线版): 修复界面瑕疵, 删除广告, 使用夜间模式浏览; 下载视频,封面,弹幕, 以及增加对触屏设备的支持等. // @author Grant Howard, Coulomb-G // @copyright 2018, Grant Howrad (https://github.com/the1812) @@ -457,7 +457,7 @@ dependencies: [ "downloadVideoDom", "downloadVideoStyle", - "videoInfo", + // "videoInfo", ], displayNames: { "downloadVideo": "下载视频", @@ -1042,7 +1042,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/gui-settings.min.html"] = `
附加功能
设置
    视频样式
  • 工具触摸其他
`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-viewer.min.html"] = `
`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `
下载视频
`; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/version.txt"] = `1.6.22`; +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/version.txt"] = `1.6.24`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/icons.min.css"] = `.icons-enabled [class^=icon-]{width:24px;height:24px;display:inline-block;background-image:none;}.icons-enabled [class^=icon-]::after{content:"";width:24px;height:24px;display:inline-block;}.icons-enabled .icon-view::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-clear::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-download::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-update::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-info::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-settings::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-widgets::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-cancel::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-ok::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-video::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-style::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-tool::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-touch::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-other::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-arrow::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-rank::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-like::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-danmaku::after{background-image:url('data:image/svg+xml;utf-8,');}`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/settings-side-bar.min.js"] = (()=>{return(i,s)=>{if($(".gui-settings-icon-panel").length===0){$("body").append(`\n
\n
\n \n
\n
\n \n
\n
`);$(".gui-settings").on("click",()=>{$(".gui-settings-box,.gui-settings-mask").addClass("opened")});$(".gui-settings-widgets").on("click",()=>{$(".gui-settings-widgets-box,.gui-settings-mask").addClass("opened")})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/text-validate.min.js"] = (()=>{return(t,e)=>{class i{constructor(t){this.key=t}get originalValue(){return t[this.key]}static getValidator(t){switch(t){case"customStyleColor":return new r(t);case"blurBackgroundOpacity":case"customControlBackgroundOpacity":return new a(t);case"defaultPlayerMode":case"defaultVideoQuality":return new s(t);case"darkScheduleStart":case"darkScheduleEnd":return new n(t);default:return new i(t)}}isValidate(t){return t}validate(t){const e=this.isValidate(t);if(e===undefined){return this.originalValue}return e}}class r extends i{isValidate(t){if(/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(t)){if(t.length<7){return`#${t[1]}${t[1]}${t[2]}${t[2]}${t[3]}${t[3]}`}else{return t}}}}class a extends i{isValidate(t){if(/^([-\+]?\d+)(\.\d+)?$/.test(t)){const e=parseFloat(t);if(e>=0&&e<=1){return t}}}}class s extends i{isValidate(t){const[e]=Object.values(Resource.manifest).filter(t=>t.dropdown&&t.dropdown.key===this.key).map(t=>t.dropdown);if(e.items.indexOf(t)!==-1){return t}}}class n extends i{isValidate(t){const e=t.match(/^([\d]{1,2}):([\d]{1,2})$/);if(e&&e.length>=3){const t={hour:parseInt(e[1]),minute:parseInt(e[2])};(function(){while(this.minute<0){this.minute+=60;this.hour-=1}while(this.minute>=60){this.minute-=60;this.hour+=1}while(this.hour<0){this.hour+=24}while(this.hour>=24){this.hour-=24}}).call(t);return`${t.hour}:${t.minute<10?"0"+t.minute:t.minute}`}}}return{export:{Validator:i,ColorValidator:r,DropDownValidator:s,OpacityValidator:a,TimeValidator:n}}}})(); @@ -1071,7 +1071,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/dark-schedule.min.js"] = (()=>{return(e,t)=>{class s{constructor(...e){if(e.length===0){const e=new Date;this.hour=e.getHours();this.minute=e.getMinutes()}else if(e.length===1){const[t]=e;[this.hour,this.minute]=t.split(":").slice(0,2).map(e=>this.validatePart(e));this.normalize()}else if(v.length===2){[this.hour,this.minute]=e}}validatePart(e){const t=parseInt(e);if(!isNaN(t)&&0<=t&&t<=59){return t}else{return null}}normalize(){while(this.minute<0){this.minute+=60;this.hour-=1}while(this.minute>=60){this.minute-=60;this.hour+=1}while(this.hour<0){this.hour+=24}while(this.hour>=24){this.hour-=24}}lessThan(e){if(this.houre.hour||this.hour===e.hour&&this.minute>e.minute){return true}return false}equals(e){return this.hour===e.hour&&this.minute===e.minute}isInRange(e,t){if(e.equals(t)){return false}let s=this.greaterThan(e)&&this.lessThan(t);if(e.greaterThan(t)){s=this.greaterThan(e)||this.lessThan(t)}const i=s||this.equals(e);return i}static millisecondsBefore(e){const t=new s;const i=(new Date).getSeconds();const r=1e3*(t.hour*3600+t.minute*60+i);const n=1e3*(e.hour*3600+e.minute*60);let h=n-r;if(t.greaterThan(e)||t.equals(e)&&i!==0){h+=24*3600*1e3}return h}}function i(){if(e.darkSchedule){const t=new s(e.darkScheduleStart);const r=new s(e.darkScheduleEnd);const n=new s;const h=n.isInRange(t,r);if(e.useDarkStyle!==h){e.useDarkStyle=h;saveSettings(e)}let u=0;if(h){u=s.millisecondsBefore(r)}else{u=s.millisecondsBefore(t)}if(u!==0){setTimeout(()=>i(),u)}}}i();return{export:s}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/force-wide.min.js"] = (()=>{return(e,t)=>{t.applyImportantStyle("forceWideStyle")}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/clear-cache.min.js"] = (()=>{return(n,c)=>{return{widget:{content:`\n \n \n 清除缓存\n `,condition:()=>typeof offlineData==="undefined",success:()=>{$("#clear-cache").on("click",()=>{n.cache={};saveSettings(n);Toast.success("已删除全部缓存.","清除缓存",5e3)})}}}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(e,t)=>{const o=t.attributes.videoInfo.export.VideoInfo;const n=t.attributes.videoInfo.export.BangumiInfo;const s={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};class i{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new r(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const s=o.data;const a=s.accept_quality;const r=s.accept_format.split(",");const l=s.accept_description;const d=[];while(a.length>0){const e=new i(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()})}}class a{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class r{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&qn=${this.format.quality}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const s=o.durl;this.fragments=s.map(e=>new a(e.length,e.size,e.url,e.backup_url));e(this.fragments)});n.withCredentials=true;n.open("GET",o);n.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function l(){const e=await(async()=>{let e=(unsafeWindow||window).aid;let t=(unsafeWindow||window).cid;if(e===undefined||t===undefined){const n=document.URL.match(/\/av(\d+)/);const s=document.URL.match(/\/ep(\d+)/);if(n&&n[1]){const s=await new o(n[1]).fetchInfo();e=s.aid;t=s.cid}}return[e,t]})();const[t,n]=e;s.aid=t;s.cid=n;return t!==undefined&&n!==undefined}async function d(){await l();const e=await i.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function s(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",s);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
  • ${e.displayName}
  • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const r=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!r.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:l,success:d}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(e,t)=>{const o={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};const n=[];$(document).ajaxSend((e,t,o)=>{if(o.url.indexOf("https://bangumi.bilibili.com/player/web_api/v2/playurl")!==-1){n.unshift(o.url)}});class s{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new a(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{function i(o){const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const i=o.data;const a=i.accept_quality;const r=i.accept_format.split(",");const l=i.accept_description;const d=[];while(a.length>0){const e=new s(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()}let a=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&otype=json`;if(o.isBangumi){SpinQuery.select(()=>n[0],e=>{a=e;i(a)},()=>logError("获取番剧下载链接失败."))}else{i(a)}})}}class i{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class a{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const n=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&qn=${this.format.quality}&otype=json`;const s=new XMLHttpRequest;s.addEventListener("load",()=>{const o=JSON.parse(s.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const n=o.durl;this.fragments=n.map(e=>new i(e.length,e.size,e.url,e.backup_url));e(this.fragments)});s.withCredentials=true;s.open("GET",n);s.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function r(){const e=await SpinQuery.select(()=>(unsafeWindow||window).aid);const t=await SpinQuery.select(()=>(unsafeWindow||window).cid);o.aid=e;o.cid=t;if(document.URL.indexOf("bangumi")!==-1){o.isBangumi=true}return e!==undefined&&t!==undefined}async function l(){await r();const e=await s.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function i(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",i);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
  • ${e.displayName}
  • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const l=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!l.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:r,success:l}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-danmaku.min.js"] = (()=>{return(n,t)=>{const e=t.attributes.videoInfo.export.DanmakuInfo;async function a(n){const t=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace("_番剧_bilibili_哔哩哔哩","");const a=new e((unsafeWindow||window).cid);await a.fetchInfo();const o=new Blob([a.rawXML],{type:"text/plain"});const i=URL.createObjectURL(o);const c=$("#danmaku-link");const d=c.attr("href");if(d){URL.revokeObjectURL(d)}clearTimeout(n);document.querySelector("#download-danmaku>span").innerHTML="下载弹幕";c.attr("download",`${t}.xml`).attr("href",i).get(0).click()}return{widget:{content:`\n \n \n 下载弹幕\n \n `,condition:async()=>{let n=await SpinQuery.condition(()=>(unsafeWindow||window).cid,n=>n!==undefined);return n!==undefined},success:()=>{const n=document.querySelector("#danmaku-link");$("#download-danmaku").on("click",t=>{if(t.target!==n){const n=setTimeout(()=>document.querySelector("#download-danmaku>span").innerHTML="请稍侯...",200);a(n)}})}}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-info.min.js"] = (()=>{return()=>{class t{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await downloadText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new e(this.cid);return this.danmaku.fetchInfo()}}class i{constructor(t,i){this.text=t;this.p=i}}class e{constructor(t){this.cid=t}async fetchInfo(){const t=await downloadText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const e=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=e;this.danmakus=[].map.call(e.querySelectorAll("d[p]"),t=>{return new i(t.innerHTML,t.getAttribute("p"))})}}class a{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const i=await downloadText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const e=JSON.parse(i.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=e.mediaInfo.title;this.cover=e.mediaInfo.cover;this.squareCover=e.mediaInfo.square_cover;this.aid=e.epInfo.aid;this.cid=e.epInfo.cid;this.videos=e.epList.map(async i=>{return{title:i.index_title,aid:i.aid,cid:i.cid,info:await new t(i.aid).fetchInfo()}});return this}}return{export:{VideoInfo:t,BangumiInfo:a,Danmaku:i,DanmakuInfo:e}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/about.min.html"] = `

    Bilibili Evolved

    开源组件

      `; @@ -1551,6 +1551,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m ResourceManager, Resource, ResourceType, + GM_info }; const resources = new ResourceManager(); resources.fetch().catch(error => logError(error)); diff --git a/bilibili-evolved.preview-offline.user.js b/bilibili-evolved.preview-offline.user.js index 8e253ea61..7150425cb 100644 --- a/bilibili-evolved.preview-offline.user.js +++ b/bilibili-evolved.preview-offline.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Preview Offline) -// @version 166.19 +// @version 167.04 // @description 增强哔哩哔哩Web端体验(预览离线版): 修复界面瑕疵, 删除广告, 使用夜间模式浏览; 下载视频,封面,弹幕, 以及增加对触屏设备的支持等. // @author Grant Howard, Coulomb-G // @copyright 2018, Grant Howrad (https://github.com/the1812) @@ -457,7 +457,7 @@ dependencies: [ "downloadVideoDom", "downloadVideoStyle", - "videoInfo", + // "videoInfo", ], displayNames: { "downloadVideo": "下载视频", @@ -1042,7 +1042,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/gui-settings.min.html"] = `
      附加功能
      设置
        视频样式
      • 工具触摸其他
      `; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/image-viewer.min.html"] = `
      `; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.html"] = `
      下载视频
      `; -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/version.txt"] = `1.6.22`; +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/version.txt"] = `1.6.24`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/icons.min.css"] = `.icons-enabled [class^=icon-]{width:24px;height:24px;display:inline-block;background-image:none;}.icons-enabled [class^=icon-]::after{content:"";width:24px;height:24px;display:inline-block;}.icons-enabled .icon-view::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-clear::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-download::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-update::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-info::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-settings::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-widgets::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-cancel::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-ok::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-video::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-style::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-tool::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-touch::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-other::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-arrow::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-rank::after{background-image:url('data:image/svg+xml;utf-8, ');}.icons-enabled .icon-like::after{background-image:url('data:image/svg+xml;utf-8,');}.icons-enabled .icon-danmaku::after{background-image:url('data:image/svg+xml;utf-8,');}`; offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/settings-side-bar.min.js"] = (()=>{return(i,s)=>{if($(".gui-settings-icon-panel").length===0){$("body").append(`\n
      \n
      \n \n
      \n
      \n \n
      \n
      `);$(".gui-settings").on("click",()=>{$(".gui-settings-box,.gui-settings-mask").addClass("opened")});$(".gui-settings-widgets").on("click",()=>{$(".gui-settings-widgets-box,.gui-settings-mask").addClass("opened")})}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/text-validate.min.js"] = (()=>{return(t,e)=>{class i{constructor(t){this.key=t}get originalValue(){return t[this.key]}static getValidator(t){switch(t){case"customStyleColor":return new r(t);case"blurBackgroundOpacity":case"customControlBackgroundOpacity":return new a(t);case"defaultPlayerMode":case"defaultVideoQuality":return new s(t);case"darkScheduleStart":case"darkScheduleEnd":return new n(t);default:return new i(t)}}isValidate(t){return t}validate(t){const e=this.isValidate(t);if(e===undefined){return this.originalValue}return e}}class r extends i{isValidate(t){if(/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(t)){if(t.length<7){return`#${t[1]}${t[1]}${t[2]}${t[2]}${t[3]}${t[3]}`}else{return t}}}}class a extends i{isValidate(t){if(/^([-\+]?\d+)(\.\d+)?$/.test(t)){const e=parseFloat(t);if(e>=0&&e<=1){return t}}}}class s extends i{isValidate(t){const[e]=Object.values(Resource.manifest).filter(t=>t.dropdown&&t.dropdown.key===this.key).map(t=>t.dropdown);if(e.items.indexOf(t)!==-1){return t}}}class n extends i{isValidate(t){const e=t.match(/^([\d]{1,2}):([\d]{1,2})$/);if(e&&e.length>=3){const t={hour:parseInt(e[1]),minute:parseInt(e[2])};(function(){while(this.minute<0){this.minute+=60;this.hour-=1}while(this.minute>=60){this.minute-=60;this.hour+=1}while(this.hour<0){this.hour+=24}while(this.hour>=24){this.hour-=24}}).call(t);return`${t.hour}:${t.minute<10?"0"+t.minute:t.minute}`}}}return{export:{Validator:i,ColorValidator:r,DropDownValidator:s,OpacityValidator:a,TimeValidator:n}}}})(); @@ -1071,7 +1071,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/dark-schedule.min.js"] = (()=>{return(e,t)=>{class s{constructor(...e){if(e.length===0){const e=new Date;this.hour=e.getHours();this.minute=e.getMinutes()}else if(e.length===1){const[t]=e;[this.hour,this.minute]=t.split(":").slice(0,2).map(e=>this.validatePart(e));this.normalize()}else if(v.length===2){[this.hour,this.minute]=e}}validatePart(e){const t=parseInt(e);if(!isNaN(t)&&0<=t&&t<=59){return t}else{return null}}normalize(){while(this.minute<0){this.minute+=60;this.hour-=1}while(this.minute>=60){this.minute-=60;this.hour+=1}while(this.hour<0){this.hour+=24}while(this.hour>=24){this.hour-=24}}lessThan(e){if(this.houre.hour||this.hour===e.hour&&this.minute>e.minute){return true}return false}equals(e){return this.hour===e.hour&&this.minute===e.minute}isInRange(e,t){if(e.equals(t)){return false}let s=this.greaterThan(e)&&this.lessThan(t);if(e.greaterThan(t)){s=this.greaterThan(e)||this.lessThan(t)}const i=s||this.equals(e);return i}static millisecondsBefore(e){const t=new s;const i=(new Date).getSeconds();const r=1e3*(t.hour*3600+t.minute*60+i);const n=1e3*(e.hour*3600+e.minute*60);let h=n-r;if(t.greaterThan(e)||t.equals(e)&&i!==0){h+=24*3600*1e3}return h}}function i(){if(e.darkSchedule){const t=new s(e.darkScheduleStart);const r=new s(e.darkScheduleEnd);const n=new s;const h=n.isInRange(t,r);if(e.useDarkStyle!==h){e.useDarkStyle=h;saveSettings(e)}let u=0;if(h){u=s.millisecondsBefore(r)}else{u=s.millisecondsBefore(t)}if(u!==0){setTimeout(()=>i(),u)}}}i();return{export:s}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/force-wide.min.js"] = (()=>{return(e,t)=>{t.applyImportantStyle("forceWideStyle")}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/clear-cache.min.js"] = (()=>{return(n,c)=>{return{widget:{content:`\n \n \n 清除缓存\n `,condition:()=>typeof offlineData==="undefined",success:()=>{$("#clear-cache").on("click",()=>{n.cache={};saveSettings(n);Toast.success("已删除全部缓存.","清除缓存",5e3)})}}}}})(); -offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(e,t)=>{const o=t.attributes.videoInfo.export.VideoInfo;const n=t.attributes.videoInfo.export.BangumiInfo;const s={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};class i{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new r(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const s=o.data;const a=s.accept_quality;const r=s.accept_format.split(",");const l=s.accept_description;const d=[];while(a.length>0){const e=new i(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()})}}class a{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class r{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&qn=${this.format.quality}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const s=o.durl;this.fragments=s.map(e=>new a(e.length,e.size,e.url,e.backup_url));e(this.fragments)});n.withCredentials=true;n.open("GET",o);n.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function l(){const e=await(async()=>{let e=(unsafeWindow||window).aid;let t=(unsafeWindow||window).cid;if(e===undefined||t===undefined){const n=document.URL.match(/\/av(\d+)/);const s=document.URL.match(/\/ep(\d+)/);if(n&&n[1]){const s=await new o(n[1]).fetchInfo();e=s.aid;t=s.cid}}return[e,t]})();const[t,n]=e;s.aid=t;s.cid=n;return t!==undefined&&n!==undefined}async function d(){await l();const e=await i.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function s(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",s);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
    • ${e.displayName}
    • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const r=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!r.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:l,success:d}}}})(); +offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-video.min.js"] = (()=>{return(e,t)=>{const o={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};const n=[];$(document).ajaxSend((e,t,o)=>{if(o.url.indexOf("https://bangumi.bilibili.com/player/web_api/v2/playurl")!==-1){n.unshift(o.url)}});class s{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new a(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{function i(o){const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const i=o.data;const a=i.accept_quality;const r=i.accept_format.split(",");const l=i.accept_description;const d=[];while(a.length>0){const e=new s(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()}let a=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&otype=json`;if(o.isBangumi){SpinQuery.select(()=>n[0],e=>{a=e;i(a)},()=>logError("获取番剧下载链接失败."))}else{i(a)}})}}class i{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class a{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const n=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&qn=${this.format.quality}&otype=json`;const s=new XMLHttpRequest;s.addEventListener("load",()=>{const o=JSON.parse(s.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const n=o.durl;this.fragments=n.map(e=>new i(e.length,e.size,e.url,e.backup_url));e(this.fragments)});s.withCredentials=true;s.open("GET",n);s.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function r(){const e=await SpinQuery.select(()=>(unsafeWindow||window).aid);const t=await SpinQuery.select(()=>(unsafeWindow||window).cid);o.aid=e;o.cid=t;if(document.URL.indexOf("bangumi")!==-1){o.isBangumi=true}return e!==undefined&&t!==undefined}async function l(){await r();const e=await s.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function i(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",i);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
    • ${e.displayName}
    • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const l=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!l.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:r,success:l}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/download-danmaku.min.js"] = (()=>{return(n,t)=>{const e=t.attributes.videoInfo.export.DanmakuInfo;async function a(n){const t=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","").replace("_番剧_bilibili_哔哩哔哩","");const a=new e((unsafeWindow||window).cid);await a.fetchInfo();const o=new Blob([a.rawXML],{type:"text/plain"});const i=URL.createObjectURL(o);const c=$("#danmaku-link");const d=c.attr("href");if(d){URL.revokeObjectURL(d)}clearTimeout(n);document.querySelector("#download-danmaku>span").innerHTML="下载弹幕";c.attr("download",`${t}.xml`).attr("href",i).get(0).click()}return{widget:{content:`\n \n \n 下载弹幕\n \n `,condition:async()=>{let n=await SpinQuery.condition(()=>(unsafeWindow||window).cid,n=>n!==undefined);return n!==undefined},success:()=>{const n=document.querySelector("#danmaku-link");$("#download-danmaku").on("click",t=>{if(t.target!==n){const n=setTimeout(()=>document.querySelector("#download-danmaku>span").innerHTML="请稍侯...",200);a(n)}})}}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/video-info.min.js"] = (()=>{return()=>{class t{constructor(t){this.aid=t}async fetchInfo(){const t=JSON.parse(await downloadText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(t.code!==0){throw new Error(t.message)}const i=t.data;this.cid=i.cid;this.pageCount=i.videos;this.coverUrl=i.pic;this.tagId=i.tid;this.tagName=i.tname;this.title=i.title;this.description=i.desc;this.up={uid:i.owner.mid,name:i.owner.name,faceUrl:i.owner.face};this.pages=i.pages.map(t=>{return{cid:t.cid,title:t.part,pageNumber:t.page}});return this}async fetchDanmaku(){this.danmaku=new e(this.cid);return this.danmaku.fetchInfo()}}class i{constructor(t,i){this.text=t;this.p=i}}class e{constructor(t){this.cid=t}async fetchInfo(){const t=await downloadText(`https://api.bilibili.com/x/v1/dm/list.so?oid=${this.cid}`);this.rawXML=t;const e=(new DOMParser).parseFromString(t,"application/xml").documentElement;this.xml=e;this.danmakus=[].map.call(e.querySelectorAll("d[p]"),t=>{return new i(t.innerHTML,t.getAttribute("p"))})}}class a{constructor(t){this.ep=t;this.videos=[]}async fetchInfo(){const i=await downloadText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const e=JSON.parse(i.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=e.mediaInfo.title;this.cover=e.mediaInfo.cover;this.squareCover=e.mediaInfo.square_cover;this.aid=e.epInfo.aid;this.cid=e.epInfo.cid;this.videos=e.epList.map(async i=>{return{title:i.index_title,aid:i.aid,cid:i.cid,info:await new t(i.aid).fetchInfo()}});return this}}return{export:{VideoInfo:t,BangumiInfo:a,Danmaku:i,DanmakuInfo:e}}}})(); offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/min/about.min.html"] = `

      Bilibili Evolved

      开源组件

        `; @@ -1551,6 +1551,7 @@ offlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/m ResourceManager, Resource, ResourceType, + GM_info }; const resources = new ResourceManager(); resources.fetch().catch(error => logError(error)); diff --git a/bilibili-evolved.preview.user.js b/bilibili-evolved.preview.user.js index 81fcb9194..f9a808bfd 100644 --- a/bilibili-evolved.preview.user.js +++ b/bilibili-evolved.preview.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved (Preview) -// @version 1.6.22 +// @version 1.6.24 // @description 增强哔哩哔哩Web端体验(预览版分支): 修复界面瑕疵, 删除广告, 使用夜间模式浏览; 下载视频,封面,弹幕, 以及增加对触屏设备的支持等. // @author Grant Howard, Coulomb-G // @copyright 2018, Grant Howrad (https://github.com/the1812) @@ -456,7 +456,7 @@ dependencies: [ "downloadVideoDom", "downloadVideoStyle", - "videoInfo", + // "videoInfo", ], displayNames: { "downloadVideo": "下载视频", @@ -1522,6 +1522,7 @@ ResourceManager, Resource, ResourceType, + GM_info }; const resources = new ResourceManager(); resources.fetch().catch(error => logError(error)); diff --git a/bilibili-evolved.user.js b/bilibili-evolved.user.js index ea8705700..82de52cf2 100644 --- a/bilibili-evolved.user.js +++ b/bilibili-evolved.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name Bilibili Evolved -// @version 1.6.22 +// @version 1.6.24 // @description 增强哔哩哔哩Web端体验: 修复界面瑕疵, 删除广告, 使用夜间模式浏览; 下载视频,封面,弹幕, 以及增加对触屏设备的支持等. // @author Grant Howard, Coulomb-G // @copyright 2018, Grant Howrad (https://github.com/the1812) @@ -456,7 +456,7 @@ dependencies: [ "downloadVideoDom", "downloadVideoStyle", - "videoInfo", + // "videoInfo", ], displayNames: { "downloadVideo": "下载视频", @@ -1522,6 +1522,7 @@ ResourceManager, Resource, ResourceType, + GM_info }; const resources = new ResourceManager(); resources.fetch().catch(error => logError(error)); diff --git a/min/download-video.min.js b/min/download-video.min.js index b213a87f3..a2bcd3e6c 100644 --- a/min/download-video.min.js +++ b/min/download-video.min.js @@ -1 +1 @@ -(()=>{return(e,t)=>{const o=t.attributes.videoInfo.export.VideoInfo;const n=t.attributes.videoInfo.export.BangumiInfo;const s={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};class i{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new r(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const s=o.data;const a=s.accept_quality;const r=s.accept_format.split(",");const l=s.accept_description;const d=[];while(a.length>0){const e=new i(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()})}}class a{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class r{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${s.aid}&cid=${s.cid}&qn=${this.format.quality}&otype=json`;const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const s=o.durl;this.fragments=s.map(e=>new a(e.length,e.size,e.url,e.backup_url));e(this.fragments)});n.withCredentials=true;n.open("GET",o);n.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function l(){const e=await(async()=>{let e=(unsafeWindow||window).aid;let t=(unsafeWindow||window).cid;if(e===undefined||t===undefined){const n=document.URL.match(/\/av(\d+)/);const s=document.URL.match(/\/ep(\d+)/);if(n&&n[1]){const s=await new o(n[1]).fetchInfo();e=s.aid;t=s.cid}}return[e,t]})();const[t,n]=e;s.aid=t;s.cid=n;return t!==undefined&&n!==undefined}async function d(){await l();const e=await i.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function s(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",s);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
      • ${e.displayName}
      • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const r=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!r.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:l,success:d}}}})(); \ No newline at end of file +(()=>{return(e,t)=>{const o={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};const n=[];$(document).ajaxSend((e,t,o)=>{if(o.url.indexOf("https://bangumi.bilibili.com/player/web_api/v2/playurl")!==-1){n.unshift(o.url)}});class s{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new a(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{function i(o){const n=new XMLHttpRequest;n.addEventListener("load",()=>{const o=JSON.parse(n.responseText);if(o.code!==0){t("获取清晰度信息失败.")}const i=o.data;const a=i.accept_quality;const r=i.accept_format.split(",");const l=i.accept_description;const d=[];while(a.length>0){const e=new s(a.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()}let a=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&otype=json`;if(o.isBangumi){SpinQuery.select(()=>n[0],e=>{a=e;i(a)},()=>logError("获取番剧下载链接失败."))}else{i(a)}})}}class i{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class a{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null;this.fragmentSplitFactor=6*5}fetchVideoInfo(){return new Promise((e,t)=>{const n=`https://api.bilibili.com/x/player/playurl?avid=${o.aid}&cid=${o.cid}&qn=${this.format.quality}&otype=json`;const s=new XMLHttpRequest;s.addEventListener("load",()=>{const o=JSON.parse(s.responseText.replace(/http:/g,"https:")).data;if(o.quality!==this.format.quality){t("获取下载链接失败, 请确认当前账号有下载权限后重试.")}const n=o.durl;this.fragments=n.map(e=>new i(e.length,e.size,e.url,e.backup_url));e(this.fragments)});s.withCredentials=true;s.open("GET",n);s.send()})}cancelDownload(){if("forEach"in this.workingXhr){this.workingXhr.forEach(e=>e.abort())}else{logError("Cancel Download Failed: forEach in this.workingXhr not found.")}}downloadFragment(e){const t=[];this.workingXhr=[];const o=Math.round(e.size/this.fragmentSplitFactor);let n=0;while(n{let n=0;const i=new XMLHttpRequest;i.open("GET",e.url);i.responseType="arraybuffer";i.withCredentials=false;i.addEventListener("progress",e=>{this.loaded+=e.loaded-n;n=e.loaded;this.progress&&this.progress(this.loaded/this.totalSize)});i.addEventListener("load",()=>{if((""+i.status)[0]==="2"){t(i.response)}else{o(`请求失败.`)}});i.addEventListener("abort",()=>o("下载已取消."));i.addEventListener("error",()=>o(`下载失败.`));i.setRequestHeader("Range",s);i.send();this.workingXhr.push(i)}));n=Math.round(n+o)}return Promise.all(t)}copyUrl(){const e=this.fragments.map(e=>e.url).reduce((e,t)=>e+"\r\n"+t);GM_setClipboard(e,"text")}extension(e){return(e||this.fragments[0]).url.indexOf(".flv")!==-1?".flv":".mp4"}makeBlob(e,t=null){return new Blob(Array.isArray(e)?e:[e],{type:this.extension(t)===".flv"?"video/x-flv":"video/mp4"})}cleanUpOldBlobUrl(){const e=$("a#video-complete").attr("href");if(e&&$(`.link[href=${e}]`).length===0){URL.revokeObjectURL(e)}}downloadSingle(e){const[t]=e;const o=this.makeBlob(t);const n=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","")+this.extension();return[o,n]}async downloadMultiple(e){const t=new JSZip;const o=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");if(e.length>1){e.forEach((e,n)=>{const s=this.fragments[n];t.file(`${o} - ${n+1}${this.extension(s)}`,this.makeBlob(e,s))})}else{const[n]=e;t.file(`${o}${this.extension()}`,this.makeBlob(n))}const n=await t.generateAsync({type:"blob"});const s=o+".zip";return[n,s]}async download(){const e=[];this.loaded=0;this.totalSize=this.fragments.map(e=>e.size).reduce((e,t)=>e+t);for(const t of this.fragments){const o=await this.downloadFragment(t);e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1){[t,o]=this.downloadSingle(e)}else{[t,o]=await this.downloadMultiple(e)}const n=URL.createObjectURL(t);this.cleanUpOldBlobUrl();this.progress&&this.progress(0);return{url:n,filename:o}}}async function r(){const e=await SpinQuery.select(()=>(unsafeWindow||window).aid);const t=await SpinQuery.select(()=>(unsafeWindow||window).cid);o.aid=e;o.cid=t;if(document.URL.indexOf("bangumi")!==-1){o.isBangumi=true}return e!==undefined&&t!==undefined}async function l(){await r();const e=await s.availableFormats;let[o]=e;const n=()=>o.downloadInfo().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});async function i(){if(!o){return}$(".download-video-panel").removeClass("action").addClass("progress");const e=await n();e.progress=(e=>{$(".download-progress-value").text(`${fixed(e*100)}`);$(".download-progress-foreground").css("transform",`scaleX(${e})`)});document.querySelector(".download-progress-cancel>span").onclick=(()=>e.cancelDownload());const t=await e.download().catch(e=>{$(".download-video-panel").addClass("error");$(".video-error").text(e)});if(!t){return}const s=document.getElementById("video-complete");s.setAttribute("href",t.url);s.setAttribute("download",t.filename);s.click();const i=`下载完成. 再次保存`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function a(){if(!o){return}const e=await n();e.copyUrl();Toast.success("已复制链接到剪贴板.","复制链接",3e3);$(".download-video-panel").removeClass("action").addClass("quality")}$(".video-action>#video-action-download").on("click",i);$(".video-action>#video-action-copy").on("click",a);e.forEach(e=>{$(`
      • ${e.displayName}
      • `).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");const l=document.querySelector(".download-video-panel");const d=()=>$(".download-video-panel").toggleClass("opened");$("#download-video").on("click",e=>{if(!l.contains(e.target)){d()}});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})}return{widget:{content:t.data.downloadVideoDom.text,condition:r,success:l}}}})(); \ No newline at end of file diff --git a/version.txt b/version.txt index cdacd0632..57c041a15 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.6.22 \ No newline at end of file +1.6.24 \ No newline at end of file diff --git a/video/download-video/download-video.js b/video/download-video/download-video.js index 7cfd44b00..936c38f5f 100644 --- a/video/download-video/download-video.js +++ b/video/download-video/download-video.js @@ -2,14 +2,23 @@ { return (_, resources) => { - const VideoInfo = resources.attributes.videoInfo.export.VideoInfo; - const BangumiInfo = resources.attributes.videoInfo.export.BangumiInfo; + // const VideoInfo = resources.attributes.videoInfo.export.VideoInfo; + // const BangumiInfo = resources.attributes.videoInfo.export.BangumiInfo; const pageData = { aid: undefined, cid: undefined, isBangumi: false, isMovie: false }; + + const bangumiUrls = []; + $(document).ajaxSend((event, request, params) => + { + if (params.url.indexOf("https://bangumi.bilibili.com/player/web_api/v2/playurl") !== -1) + { + bangumiUrls.unshift(params.url); + } + }); class VideoFormat { constructor(quality, internalName, displayName) @@ -28,35 +37,53 @@ { return new Promise((resolve, reject) => { - const url = `https://api.bilibili.com/x/player/playurl?avid=${pageData.aid}&cid=${pageData.cid}&otype=json`; - const xhr = new XMLHttpRequest(); - xhr.addEventListener("load", () => + function downloadFormats(url) { - const json = JSON.parse(xhr.responseText); - if (json.code !== 0) + const xhr = new XMLHttpRequest(); + xhr.addEventListener("load", () => { - reject("获取清晰度信息失败."); - } - const data = json.data; - const qualities = data.accept_quality; - const internalNames = data.accept_format.split(","); - const displayNames = data.accept_description; - const formats = []; - while (qualities.length > 0) - { - const format = new VideoFormat( - qualities.pop(), - internalNames.pop(), - displayNames.pop() - ); - formats.push(format); - } - resolve(formats); - }); - xhr.addEventListener("error", () => reject(`获取清晰度信息失败.`)); - xhr.withCredentials = true; - xhr.open("GET", url); - xhr.send(); + const json = JSON.parse(xhr.responseText); + if (json.code !== 0) + { + reject("获取清晰度信息失败."); + } + const data = json.data; + const qualities = data.accept_quality; + const internalNames = data.accept_format.split(","); + const displayNames = data.accept_description; + const formats = []; + while (qualities.length > 0) + { + const format = new VideoFormat( + qualities.pop(), + internalNames.pop(), + displayNames.pop() + ); + formats.push(format); + } + resolve(formats); + }); + xhr.addEventListener("error", () => reject(`获取清晰度信息失败.`)); + xhr.withCredentials = true; + xhr.open("GET", url); + xhr.send(); + } + let url = `https://api.bilibili.com/x/player/playurl?avid=${pageData.aid}&cid=${pageData.cid}&otype=json`; + if (pageData.isBangumi) + { + SpinQuery.select(() => bangumiUrls[0], + bangumiUrl => + { + url = bangumiUrl; + downloadFormats(url); + }, + () => logError("获取番剧下载链接失败."), + ); + } + else + { + downloadFormats(url); + } }); } } @@ -257,33 +284,14 @@ } async function loadPageData() { - const result = await (async () => - { - let aid = (unsafeWindow || window).aid; - let cid = (unsafeWindow || window).cid; - if (aid === undefined || cid === undefined) - { - const aidMatch = document.URL.match(/\/av(\d+)/); - const epMatch = document.URL.match(/\/ep(\d+)/); - if (aidMatch && aidMatch[1]) - { - const info = await new VideoInfo(aidMatch[1]).fetchInfo(); - aid = info.aid; - cid = info.cid; - } - // TODO: Download bangumi, the legacy method not work... - // else if (epMatch && epMatch[1]) - // { - // const info = await new BangumiInfo(epMatch[1]).fetchInfo(); - // aid = info.aid; - // cid = info.cid; - // } - } - return [aid, cid]; - })(); - const [aid, cid] = result; + const aid = await SpinQuery.select(() => (unsafeWindow || window).aid); + const cid = await SpinQuery.select(() => (unsafeWindow || window).cid); pageData.aid = aid; pageData.cid = cid; + if (document.URL.indexOf("bangumi") !== -1) + { + pageData.isBangumi = true; + } return aid !== undefined && cid !== undefined; } async function loadWidget()