// ==UserScript== // @name For Imhentai // @namespace http://tampermonkey.net/ // @version 2.2 // @description 不翻墙下,更快加载 imhentai.xxx 的图片,并提供打包下载 // @author 水母 // @match https://imhentai.xxx/gallery/* // @match https://*.imhentai.xxx/* // @icon https://imhentai.xxx/images/logo.png // @require https://cdn.jsdelivr.net/npm/jszip@3.6.0/dist/jszip.min.js#sha512-uVSVjE7zYsGz4ag0HEzfugJ78oHCI1KhdkivjQro8ABL/PRiEO4ROwvrolYAcZnky0Fl/baWKYilQfWvESliRA== // @grant GM_setValue // @grant GM_getValue // @grant GM_download // @grant GM_openInTab // @license MIT // @downloadURL none // ==/UserScript== (function () { "use strict"; // 全局数据 let IS_INIT = false; let IS_RUN = false; let IS_DOWNLOADING = false; // 页码序列 [cover.jpg, 1.jpg, ..., 30.jpg] : cover不计入页数; eg.总页数定为 30; 数组 [0] 定为 cover /** * 当前页码 */ let CURRENT_PAGE = 0; /** * 最大浏览的页码,只增 */ let MAX_BROWSE_PAGE = 0; /** * 已加载的页码 */ let PAGE_LOADED = 0; /** * @desc 标识当前在哪个页面 */ let CURRENT_URL; /** * @desc 页面枚举 */ const CURRENT_URL_TYPE = { /** * @desc 标识在 https://imhentai.xxx/gallery/? 页面 */ gallery: "gallery", /** * @desc 标识在 https://imhentai.xxx/view/? 页面 */ view: "view", /** * @desc 标识在 https://?.imhentai.xxx/?/?/cover.jpg 页面 */ imgPage: "imgPage", /** * @desc 标识在 测试 gallery 页面 */ testGallery: "testGallery", /** * @desc 标识在 测试 view 页面 */ testView: "testView", /** * @desc 标识为无法识别页面 */ unknow: "unknow", }; /** * 用户定义的下载页码区间 */ let UserCustemRange = { min: 0, max: 0, page_loaded: 0, }; // enum const CanEleID = { /** * 主体 */ app: "can-app", runBtn: "can-run", previousBtn: "can-pre", nextBtn: "can-next", downloadBtn: "can-down", scaleUpBtn: "can-sUp", scaleResetBtn: "can-sReset", scaleDownBtn: "can-sDown", /** * 页码 */ pageLabel: "can-page", /** * 页码跳转 */ changePageInput: "can-input", /** * 图片显示 */ showImg: "can-img", /** * 图片显示外包
*/ showImgDiv: "can-img-div", /** * 转 base64 */ canvas: "can-cvs", }; const BtnText = { runBtn: "启动🥰", previousBtn: "⫷", nextBtn: "⫸", downloadBtn: "下载🥵", scaleUpBtn: "⇲", scaleResetBtn: "↺◲", scaleDownBtn: "⇱", }; /** * FileReader 加载完毕计算器,由异步方法调用 */ const CounterForFileReader = { /** * 异步锁 */ is_lock: false, count: 0, /** * 如果更新成功,返回 true * @returns {boolean} */ update() { if (this.is_lock) return false; else { this.is_lock = true; this.count++; this.is_lock = false; return true; } }, }; // 避免没必要下载属性,被 JSON.stringify() const keyImageBase64 = Symbol("imageBase64"); const keyImageScale = Symbol("imageScale"); /** * * @param {string} imgName * @param {string} imgUrl * @param {string} imgType * @param {number} width * @param {number} height * @param {number} scale 仅用于页面浏览 * @param {string} imageBase64 */ function ImgInfo( imgName, imgUrl = "", imgType = "", width = 0, height = 0, scale = 1.0, imageBase64 = "" ) { this.imgName = imgName; this.imgUrl = imgUrl; this.imgType = imgType; this.width = width; this.height = height; this[keyImageScale] = scale; this[keyImageBase64] = imageBase64; } /** * 本子数据 * @param {string} name_en * @param {string} name_sub * @param {number} page * @param {string} root_url * @param {ImgInfo[]} imgInfoList */ function BzData( name_en = "Null", name_sub = "Null", page = 0, root_url = "", imgInfoList = [] ) { this.name_en = name_en; this.name_sub = name_sub; this.page = page; this.root_url = root_url; this.imgInfoList = imgInfoList; } /** * BzData 迭代器 * @param {BzData} bzData */ function* BzDataIterator(bzData) { let index = 0; while (index < bzData.imgInfoList.length) { let imgInfo = bzData.imgInfoList[index]; yield [index++, bzData.root_url, imgInfo]; } } //