Bilibili-Evolved/min/download-video.min.js
2018-11-19 19:47:34 +08:00

1 line
5.8 KiB
JavaScript

(()=>{return(e,t)=>{const o=t.attributes.videoInfo.export.VideoInfo;const n=t.attributes.videoInfo.export.BangumiInfo;const s=t.attributes.videoInfo.export.DanmakuInfo;const i={aid:undefined,cid:undefined,isBangumi:false,isMovie:false};class a{constructor(e,t,o){this.quality=e;this.internalName=t;this.displayName=o}async downloadInfo(){const e=new l(this);await e.fetchVideoInfo();return e}static get availableFormats(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${i.aid}&cid=${i.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 i=s.accept_quality;const r=s.accept_format.split(",");const l=s.accept_description;const d=[];while(i.length>0){const e=new a(i.pop(),r.pop(),l.pop());d.push(e)}e(d)});n.addEventListener("error",()=>t(`获取清晰度信息失败.`));n.withCredentials=true;n.open("GET",o);n.send()})}}class r{constructor(e,t,o,n){this.length=e;this.size=t;this.url=o;this.backupUrls=n}}class l{constructor(e,t){this.format=e;this.fragments=t||[];this.progress=null;this.loaded=0;this.totalSize=null;this.workingXhr=null}fetchVideoInfo(){return new Promise((e,t)=>{const o=`https://api.bilibili.com/x/player/playurl?avid=${i.aid}&cid=${i.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 r(e.length,e.size,e.url,e.backup_url));e(this.fragments)});n.withCredentials=true;n.open("GET",o);n.send()})}cancelDownload(){if(this.workingXhr){this.workingXhr.abort()}}downloadUrl(e){return new Promise((t,o)=>{const n=new XMLHttpRequest;n.open("GET",e);n.responseType="arraybuffer";n.withCredentials=false;n.addEventListener("progress",e=>{this.progress&&this.progress((this.loaded+e.loaded)/this.totalSize)});n.addEventListener("load",()=>{if(n.status===200){t(n.response)}else{o(`请求失败.`)}});n.addEventListener("abort",()=>o("下载已取消."));n.addEventListener("error",()=>o(`下载失败.`));n.send();this.workingXhr=n})}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"}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=new Blob([t],{type:this.extension()===".flv"?"video/x-flv":"video/mp4"});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)=>{t.file(`${o} - ${n+1}${this.extension(this.fragments[n])}`,e)})}else{t.file(`${o}}${this.extension()}`,data)}if(settings.downloadDanmaku){const e=new s(i.cid);await e.fetchInfo();t.file(`${o}.xml`,e.rawXML)}const n=await t.generateAsync({type:"blob"});const a=o+".zip";return[n,a]}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.downloadUrl(t.url);this.loaded+=t.size;e.push(o)}if(e.length<1){throw new Error("下载失败.")}let t=null;let o=null;if(e.length===1&&!settings.downloadDanmaku){[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}}}function d(){(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]})().then(e=>{const[o,n]=e;if(o===undefined||n===undefined){return}i.aid=o;i.cid=n;a.availableFormats.then(e=>{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=`下载完成. <a class="link" href="${t.url}" download="${t.filename}">再次保存</a>`;Toast.success(i,"下载视频");$(".download-video-panel").removeClass("progress").addClass("quality")}async function i(){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",i);e.forEach(e=>{$(`<li>${e.displayName}</li>`).on("click",()=>{o=e;$(".download-video-panel").removeClass("quality").addClass("action")}).prependTo("ol.video-quality")});t.applyStyle("downloadVideoStyle");$("#download-video").on("click",()=>{$(".download-video-panel").toggleClass("opened")}).parent().removeClass("hidden")});$(".video-error").on("click",()=>{$(".video-error").text("");$(".download-video-panel").removeClass("error").removeClass("progress").addClass("quality")})})}return{settingsWidget:{category:"视频与直播",content:t.data.downloadVideoDom.text,success:d}}}})();