// ==UserScript== // @name bilibili plus bilibilijj // @namespace http://qli5.tk/ // @description 在bilibili界面上直接添加jj的三种下载链接。flv是分段超清,mp4是整段高清,ass下载已引用大神代码修复。请登录jj以跳过广告页。播放弹幕可使用potplayer等。视频弹幕同名即可自动加载。 // @include http://www.bilibili.com/video/av* // @include https://www.bilibili.com/video/av* // @include http://bangumi.bilibili.com/anime/* // @include https://bangumi.bilibili.com/anime/* // @version 0.4 // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @author qli5 // @copyright qli5, 2014+, 田生 // @license Mozilla Public License 2.0; http://www.mozilla.org/MPL/2.0/ // @require https://greasyfork.org/scripts/2231-bilibili-ass-danmaku-downloader/code/bilibili%20ASS%20Danmaku%20Downloader.user.js // @connect-src www.jijidown.com // @connect-src comment.bilibili.com // @connect-src www.flvcd.com // @downloadURL none // ==/UserScript== // 感谢所有大佬,鄙人只做了微小的工作。 (function () { // jj的站长说被攻击了,所以加了很严格的机器人检查。可以尝试加快检查,但是如果您真的是机器人也没办法。 var testingBypassSafedog = GM_getValue && GM_getValue('testingBypassSafedog') || undefined; // 本测试功能适合一次会下载很多视频的场景,可以尽量方便地把mp4的文件名改成ass的。这是我能在同源限制下想出的最好办法。请诸大佬指教。 var testingMP4Rename = GM_getValue && GM_getValue('testingMP4Rename') || undefined; // 本测试功能适合看完就删的场景,可以将ass的文件名改成mp4的。文件名一般是数字乱码,也有可能失败,但不需要多点击。 var testingASSRename = GM_getValue && GM_getValue('testingASSRename') || undefined; // 本测试功能将在jj无数据时尝试另一个老牌通用解析网站flvcd.com。暂时没做番剧解析。 var testingFLVCD = GM_getValue && GM_getValue('testingFLVCD') || undefined; // 强迫症就请自己动手把undefined改成true/false吧 // settings if (GM_setValue && (typeof (testingBypassSafedog) != 'boolean' || typeof (testingMP4Rename) != 'boolean' || typeof (testingASSRename) != 'boolean' || typeof (testingFLVCD) != 'boolean')) { testingBypassSafedog = confirm('欢迎使用bilibili plus bilibilijj。jj的站长说被攻击了,所以加了很严格的机器人检查。可以尝试加快检查,但是如果您真的是机器人也没办法。要这样做吗?'); testingMP4Rename = confirm('本测试功能适合一次会下载很多视频的场景,可以尽量方便地把mp4的文件名改成ass的。这是我能在同源限制下想出的最好办法。请诸大佬指教。要这样做吗?'); testingASSRename = confirm('本测试功能适合看完就删的场景,可以将ass的文件名改成mp4的。文件名一般是数字乱码,也有可能失败,但不需要多点击。要这样做吗?'); testingFLVCD = confirm('本测试功能将在jj无数据时尝试另一个老牌通用解析网站flvcd.com。暂时没做番剧解析。要这样做吗?'); alert('到油猴界面重置脚本可以清除这些设置,强迫症可以继续改源码。多谢使用。'); GM_setValue('testingBypassSafedog', testingBypassSafedog); GM_setValue('testingMP4Rename', testingMP4Rename); GM_setValue('testingASSRename', testingASSRename); GM_setValue('testingFLVCD', testingFLVCD); } // reset dalao's script window.removeEventListener('DOMContentLoaded', init); GM_addStyle = init = function () { }; initFont(); var paraOriginal; GM_xmlhttpRequest(paraOriginal = { method: 'GET', url: 'http://www.jijidown' + location.href.match(/\.com.*/)[0], onload: function (response) { var doc = new DOMParser().parseFromString(response.responseText, 'text/html'); var links = document.createElement('div'); // anchor to jj var aa; aa = document.createElement('a'); aa.href = 'http://www.jijidown' + location.href.match(/\.com.*/)[0]; aa.textContent = 'bilibilijj'; links.appendChild(aa); // testingMP4Rename var input, button; if (testingMP4Rename) { input = document.createElement('input'); input.type = 'text'; input.value = '请选择ass...'; input.onclick = function () { this.select(); }; links.appendChild(input); button = document.createElement('button'); button.onclick = function () { try { input.select(); document.execCommand('copy'); } catch (e) { console.warn('Oops, copy failed' + e); } }; button.textContent = 'copy'; links.appendChild(button); } if (doc.getElementsByClassName('yjs-browser-verification').length > 0) { // jj boom links.appendChild(document.createTextNode('jj觉得你是机器人,请手动访问一次。')); // testingBypassSafedog if (testingBypassSafedog) { links.appendChild(document.createTextNode('但是你选择了跳过jj的机器人验证,讨厌~~稍后刷新')); var jschl_vc = response.responseText.match(/)/)[0].slice(44); var pass = response.responseText.match(/)/)[0].slice(40); var jschl_answer = eval( response.responseText .match(/setTimeout\(function\(\){[\s\S]*?}[\s\S]*?(?=})/)[0].slice(23) .replace("a = document.getElementById('jschl-answer');", 'a = {}') .replace("f = document.getElementById('challenge-form');", '// f') .replace("f.submit();", 'a;') ); // safedog will reject false starts. you may tweak the delay if you have a higher RTT, especially if you are not in China setTimeout(function () { links.remove(); GM_xmlhttpRequest({ method: 'GET', url: 'http://www.jijidown.com/cdn-cgi/l/chk_jschl?' + 'jschl_vc=' + encodeURIComponent(jschl_vc) + '&pass=' + encodeURIComponent(pass) + '&jschl_answer=' + encodeURIComponent(jschl_answer.value), headers: { 'Referer': 'http://www.jijidown.com/' }, onload: function () { GM_xmlhttpRequest(paraOriginal); } }); }, 4000); testingBypassSafedog = false; // to avoid infinite loop } } else { // testingFLVCD index_*.html var indexCount; if (testingFLVCD) indexCount = 1; // parse jj var listCols = doc.getElementById('Right_Main'); if (listCols.children.length === 0) links.appendChild(document.createTextNode('本视频貌似太冷门了,需要到jj刷新一下。')); for (var i = 0; i < listCols.children.length; i++) { var list = listCols.children[i]; for (var j = 0; j < list.children.length; j++) { var flvDiv, mp4Div, assDiv; var name, cid; if (list.children[j].querySelector('span.PBoxName')) { flvDiv = list.children[j].querySelector('span.Data_Main > span.Data_Flv > span.Data_Data'); mp4Div = list.children[j].querySelector('span.Data_Main > span.Data_Mp4 > span.Data_Data'); assDiv = list.children[j].querySelector('span.Data_Main > span.Data_Ass > span.Data_Data'); if (list.children[j].querySelector('span.PBoxName').textContent == '下载地址(右侧方块切换类型)') name = assDiv.children[0].title.slice(0, -7); else name = list.children[j].querySelector('span.PBoxName').textContent; cid = list.children[j].getAttribute('data-cid'); // name links.appendChild(document.createElement('br')); links.appendChild(document.createTextNode(name)); links.appendChild(document.createTextNode(' ')); // flv var a; a = document.createElement('a'); a.href = 'http://www.jijidown.com' + flvDiv.querySelector('a').getAttribute('href'); a.textContent = 'flv'; links.appendChild(a); links.appendChild(document.createTextNode(' ')); // mp4 a = document.createElement('a'); if (testingASSRename) a.onclick = function () { this.nextSibling.nextSibling.download = this.href.match(/\/\d*(?=(-1-hd)?\.mp4)/)[0].slice(1) + '-1-hd.ass'; }; if (mp4Div.querySelector('a')) a.href = 'http://www.jijidown.com' + mp4Div.querySelector('a').getAttribute('href'); else if (testingFLVCD && location.host == 'www.bilibili.com') { // testingFLVCD (function (a) { GM_xmlhttpRequest({ method: 'GET', // flvcd is not that smart on bilibili. manual convert required... url: 'http://www.flvcd.com/parse.php?format=high&kw=' + location.href.match(/http:\/\/www.bilibili.com\/video\/av\d*/) + '/index_' + indexCount + '.html', onload: function (response) { var doc = new DOMParser().parseFromString(response.responseText, 'text/html'); a.href = doc.getElementsByClassName('link')[0].getAttribute('href'); if (doc.getElementsByClassName('link').length > 1) console.warn('flvcd fail. bilibili changed its api?'); } }); })(a); } else { a.onclick = function () { alert('no mp4 data\nplease check jj'); }; } a.textContent = 'mp4'; links.appendChild(a); links.appendChild(document.createTextNode(' ')); // ass a = document.createElement('a'); a.onclick = (function (name, cid, self) { return function () { if (self.href.slice(0, 4) != 'blob') { fetchDanmaku(cid, function (danmaku) { var ass = generateASS(setPosition(danmaku), { 'title': name, 'ori': location.href, }); // I would assume most users are using Windows var blob = new Blob(['\ufeff' + ass], { type: 'application/octet-stream' }); self.setAttribute('href', window.URL.createObjectURL(blob)); self.click(); }); return false; } if (testingMP4Rename) { input.value = name + '.mp4'; input.select(); } }; })(name, cid, a); a.download = name + '.ass'; a.href = 'http://www.bilibilijj.com' + assDiv.querySelector('a').getAttribute('href'); a.textContent = 'ass'; links.appendChild(a); if (testingFLVCD) indexCount++; } } } } // set styles links.style.backgroundColor = 'white'; links.style.padding = '10px'; links.style.border = 'black'; links.style.borderWidth = 'thin'; links.style.borderStyle = 'dashed'; // append to page if (location.hostname == 'www.bilibili.com') { links.style.zIndex = '500000'; links.style.position = 'absolute'; links.style.top = '0px'; document.querySelector('.v_small').appendChild(links); } else if (location.hostname == 'bangumi.bilibili.com') { document.querySelector('.v1-bangumi-list-part-wrapper').appendChild(links); } } }); })();