// ==UserScript== // @name FanboxPic Downloader // @namespace TypeNANA // @version 0.3 // @description Add download button to Fanbox image, and click to download the original image named by format. // @author HY // @match *.fanbox.cc/* // @include *.fanbox.cc/* // @require http://code.jquery.com/jquery-3.3.1.min.js // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== (function () { /** Edit defaultFileName to change the file name format * * <%Userid> Fanbox user ID. eg: shiratamaco * <%Postid> Fanbox post ID. eg: 1459770 * <%Time> Current timestamp. eg: 1550557810891 * <%PicName> Original pic name. eg: 6tpWcFZjqFmc1faOs4TraugL * <%PicNo> Ordinal number of pic. eg: 0 * * default: "fanbox <%Userid> <%Postid>_p<%PicNo>" * result: "fanbox shiratamaco 1459770_p0.jpg" * * example1: "<%Userid> <%Postid> <%PicName>” * result: "shiratamaco 1459770 6tpWcFZjqFmc1faOs4TraugL.jpg" * * example2: "<%Postid>_p<%PicNo>” * result: "1459770_p0.jpg" */ let defaultFileName = "fanbox <%Userid> <%Postid>_p<%PicNo>"; function download(url, name) { GM_xmlhttpRequest({ method: "GET", url: url, binary: true, responseType: "blob", onload: function (response) { downloadFile(name, response.response) }, onerror: function (e) { console.log("failed. cause:", e) }, }); } function downloadFile(fileName, blob) { //通过a标签的download属性来下载指定文件名的文件 let anchor = getDlBtn(); let src = URL.createObjectURL(blob); anchor.download = fileName; anchor.href = src; anchor.click(); } function getDlBtn() { if (document.getElementsByClassName("img-link").length == 0) { let btnDownloadImg = document.createElement('A'); btnDownloadImg.className = 'img-link'; document.getElementById("root").appendChild(btnDownloadImg); } return document.getElementsByClassName("img-link")[0]; } function setBtn(v, index) { if (v == null || v.length == 0) return; let target = v[0]; if (target == null) return; if (target.getElementsByClassName("dl_btn_div").length > 0) return; if (target.getElementsByTagName("img").length <= 0 && target.getElementsByTagName("img")[0].src == null) return; let pageUrl = document.location.href; let picUrl = target.href; let dlbtn = document.createElement('DIV'); target.parentElement.appendChild(dlbtn); dlbtn.outerHTML = '
'; dlbtn = target.parentElement.getElementsByClassName("dl_btn_div")[0] //获取文件名 // https://downloads.fanbox.cc/images/post/1459770/6tpWcFZjqFmc1faOs4TraugL.png let nameArr = picUrl.split("/"); let picName = nameArr[nameArr.length - 1]; let dl_picname = picName.split(".")[0]; let dl_time = new Date().getTime(); //获取图片编号 // https://www.fanbox.cc/@shiratamaco/posts/1459770 let dl_userid = pageUrl.split("@")[1].split("/")[0]; let dl_tid = pageUrl.split("/")[pageUrl.split("/").length - 1]; let dl_picno = index; //替换内容,拼接文件名 let dl_filename = defaultFileName .replace("<%Userid>", dl_userid) .replace("<%Postid>", dl_tid) .replace("<%Time>", dl_time) .replace("<%PicName>", dl_picname) .replace("<%PicNo>", dl_picno); //获取拓展名,推特只存在.jpg和.png格式的图片,故偷个懒不做正则判断 let dl_ext = picUrl.split(".")[picUrl.split(".").length - 1]; dlbtn.addEventListener('touchstart', function (e) { dlbtn.onclick = function (e) { return false; } return false; }); dlbtn.addEventListener('mousedown', function (e) { dlbtn.onclick = function (e) { return false; } return false; }); dlbtn.addEventListener('click', function (e) { //调用下载方法 cancelBubble(e); download(picUrl, dl_filename + "." + dl_ext); return false; }); return false; } function findFirstA(node) { var tmp = node; for (var i = 0; i < 20; i++) { tmp = tmp.parentElement if (tmp == null) return null; if (tmp.nodeName == "a" || tmp.nodeName == "A") { return tmp } } } function findFirstLi(node) { var tmp = node; for (var i = 0; i < 20; i++) { tmp = tmp.parentElement if (tmp == null) return null; if (tmp.nodeName == "li" || tmp.nodeName == "LI") { return tmp } } } function cancelBubble(e) { var evt = e ? e : window.event; if (evt.stopPropagation) { evt.stopPropagation(); } else { evt.cancelBubble = true; } } function waitForKeyElements( selectorTxt, actionFunction, bWaitOnce ) { var targetNodes, btargetsFound; targetNodes = $(selectorTxt); if (targetNodes && targetNodes.length > 0) { btargetsFound = true; targetNodes.each(function (i, v) { var jThis = $(this); var alreadyFound = jThis.data('alreadyFound') || false; if (!alreadyFound) { var cancelFound = actionFunction(jThis, i); if (cancelFound) { btargetsFound = false; } else { jThis.data('alreadyFound', true); } } }); } else { btargetsFound = false; } var controlObj = waitForKeyElements.controlObj || {}; var controlKey = selectorTxt.replace(/[^\w]/g, "_"); var timeControl = controlObj[controlKey]; if (btargetsFound && bWaitOnce && timeControl) { clearInterval(timeControl); delete controlObj[controlKey] } else { if (!timeControl) { timeControl = setInterval(function () { waitForKeyElements(selectorTxt, actionFunction, bWaitOnce ); }, 300); controlObj[controlKey] = timeControl; } } waitForKeyElements.controlObj = controlObj; } waitForKeyElements('article a[href^="https://downloads.fanbox.cc/images/post"]', setBtn); })();