圖片全載-FancyboxV5

支持寫真、H漫、漫畫的網站1000+,圖片全量加載,簡易的看圖功能,漫畫無限滾動閱讀模式,下載壓縮打包,如有下一頁元素可自動化下載。

// ==UserScript==
// @name               圖片全載-FancyboxV5
// @name:en            Full Picture Load - FancyboxV5
// @name:zh-CN         图片全载-FancyboxV5
// @name:zh-TW         圖片全載-FancyboxV5
// @version            2.11.35
// @description        支持寫真、H漫、漫畫的網站1000+,圖片全量加載,簡易的看圖功能,漫畫無限滾動閱讀模式,下載壓縮打包,如有下一頁元素可自動化下載。
// @description:en     supports 1,000+ websites for photos, h-comics, and comics, fully loaded images, simple image viewing function, comic infinite scroll read mode, and compressed and packaged downloads.
// @description:zh-CN  支持写真、H漫、漫画的网站1000+,图片全量加载,简易的看图功能,漫画无限滚动阅读模式,下载压缩打包,如有下一页元素可自动化下载。
// @description:zh-TW  支持寫真、H漫、漫畫的網站1000+,圖片全量加載,簡易的看圖功能,漫畫無限滾動閱讀模式,下載壓縮打包,如有下一頁元素可自動化下載。
// @author             tony0809
// @match              *://*/*
// @connect            *
// @exclude            *.youtube.com*
// @exclude            *docs.google.com*
// @exclude            *google*/maps/*
// @exclude            *mail.google.com*
// @exclude            *accounts.google.com*
// @icon               data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAtFBMVEVEREAAAABEREBEREAuuaIzqpkvr58yiHgzhnY6kYM7mYI4kog4s6A2tpo0r544ooo2nY40sJw0sp00rZg1sJw0sZ0zsp01sZw0sZw0rZk1sJw1sZw1rZk0sp00rpk1sp01sZs1rpk1rpk0sp01spw1sJ00rZo1rZk1rpo0r5k0sJw0sZ01r5o0sZw0rpk0sp01sZ01sJw1spw1r5k1sp01sZw0sZ01sZw1rpk1sp01sZw1r5pUzpTcAAAAOXRSTlMAAAUGCw8QERIUFxgbHB0hIieqq6yvtLa3vb/AwMHCxMXFxsfIyc3Oz+zt7vDx8fL4+Pn5+vr7/v7AEFI4AAABR0lEQVR42qWT11bDMAxApbhsmm5KKVD2KiUQwpD1///FkZcSmh4e8FOsex3LsgymPy6ISkRyA4FlWMRXomIyQOg/SbyKAmSOE2Ip02UOYxf/DILNjOOEWLnAEAqio0MMAzJjTAZh1p0SrYCIuu0cMZc9JbENXLa1NWGdI1nWeQuXGPzBTdzC8ws52UI5MwchrA/VTOuTEP9fFyTG7E+R9q8JLsbW1UHzU8HHrCuU1fyToDlB43xRqMUgfc+/KA77fZrWSH/47zPlzOcpJxG8u32r/OEg5SRCqO/WTeT3+5oTuP4LxrXnd5F7waZ+wM5c+NVeujMRrDYMYueE+VK5E5r3uzOb7TbvHH7f/1pP/L8nU9u38Nwyy8OZdjfwY+ZnmPinp28y3mglNeERDJYy/9A3GYVS+GMPMB+uyL67/qO68Mb8MurBD7foVTtvIbtnAAAAAElFTkSuQmCC
// @license            MIT
// @namespace          https://greasyfork.org/users/20361
// @grant              GM_xmlhttpRequest
// @grant              GM.xmlHttpRequest
// @grant              GM_registerMenuCommand
// @grant              GM.registerMenuCommand
// @grant              GM_unregisterMenuCommand
// @grant              GM.unregisterMenuCommand
// @grant              GM_openInTab
// @grant              GM.openInTab
// @grant              GM_getValue
// @grant              GM.getValue
// @grant              GM_setValue
// @grant              GM.setValue
// @grant              GM_listValues
// @grant              GM.listValues
// @grant              GM_deleteValue
// @grant              GM.deleteValue
// @grant              GM_getResourceText
// @grant              GM.getResourceText
// @grant              GM_addElement
// @grant              GM.addElement
// @grant              unsafeWindow
// @grant              window.close
// @run-at             document-end
// @noframes
// @require            https://update.greasyfork.org/scripts/473358/1237031/JSZip.js
// @resource ajaxHookerJS https://update.greasyfork.org/scripts/465643/1421695/ajaxHookerLatest.js
// @resource JqueryJS https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
// @resource FancyboxV5JS https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.36/dist/fancybox/fancybox.umd.js
// @resource FancyboxV5Css https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.36/dist/fancybox/fancybox.css
// @resource FancyboxV3JS https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js
// @resource FancyboxV3Css https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css
// @resource ViewerJs https://cdn.jsdelivr.net/npm/viewerjs@1.11.6/dist/viewer.min.js
// @resource ViewerJsCss https://cdn.jsdelivr.net/npm/viewerjs@1.11.6/dist/viewer.min.css
// ==/UserScript==

(async (JSZip) => {
    "use strict";

    //await wait(() => !!document.body && document.readyState !== "loading");
    //await wait(() => !!document.body && document?.body?.childNodes?.length > 0);

    if ((ge("body.no-js:not(.has-preloader,.single-post)") && !ge("body.no-js #layout-default")) || ge(".captcha-area")) {
        debug("Cloudflare驗證中不運行腳本。");
        return;
    }

    if (document.title.startsWith("DDoS-Guard")) {
        debug("DDoS-Guard驗證中不運行腳本。");
        return;
    }

    //火狐Firefox使用open("about:blank", "_blank")打開空白頁,空白頁的location.href會變成父視窗的location.href,導致載入腳本,必須排除。
    if (["分頁畫廊:", "标签画廊:", "TabView:"].some(t => document.title.startsWith(t))) {
        return;
    }

    //await delay(600);

    const defaultOptions = {
        icon: 1, //是否顯示左下圖示,1:顯示、0:不顯示
        threading: 8, //最大下載線程數
        zip: 1, //1:圖片下載後壓縮打包,0:批量下載圖片,無法全自動下載
        file_extension: "zip", //zip or cbz
        autoInsert: 1, //頁面容器自動聚圖,1:自動、0:手動
        autoDownload: 0, //!!!維持0不要改!!!建議透過UI選項設定來開啟,需要customData也有autoDownload
        autoDownloadCountdown: 5, //有NEXT時自動下載的倒數秒數
        comic: 0, //1,忽視漫畫站點開關選項,啟用漫畫規則
        doubleTouchNext: 1, //觸控裝置雙擊前往下一頁,1:開啟、0:關閉
        zoom: 0, //1 ~ 10 腳本插入的圖片縮放比例,10 = 100%,9 = 90%,0 = auto
        column: 4, //圖片並排顯示的數量 2 ~ 6
        viewMode: 0, //0:置中、1:並排
        fancybox: 1, //Fancybox圖片燈箱展示功能,1:開啟、0:關閉
        shadowGallery: 0, //自動進入影子畫廊,1:自動、0:手動
        autoExport: 0 //自動匯出網址,1:自動、0:手動
    };
    const FullPictureLoadShowEye = localStorage.getItem("FullPictureLoadShowEye") ?? 1;
    const FullPictureLoadCustomDownloadVideo = localStorage.getItem("FullPictureLoadCustomDownloadVideo") ?? 1;
    let options = defaultOptions;

    const _unsafeWindow = unsafeWindow ?? window;
    const language = _unsafeWindow.navigator.language;
    let siteUrl = _unsafeWindow.location.href.replace(_unsafeWindow.location.hash, "");
    let frameWindow = _unsafeWindow;
    let siteData = {};
    let _this = {};
    let tempData = {};
    let siteJson = {};
    let displayLanguage = {};
    let globalImgArray = [];
    let captureSrcArray = [];
    let captureTotal = 0;
    let isCaptureMode = false;
    let thumbnailSrcArray = [];
    let videoSrcArray = [];
    let fileUrlArray = [];
    let promiseBlobArray = [];
    let captureLinksArray = [];
    let setArray = new Set();
    let setVideoArray = new Set();
    let customTitle = null;
    let isEsc = false;
    let isDownloading = false;
    let isStopDownload = false;
    let isCountdowning = false;
    let isFetching = false;
    let isGotAll = false;
    let isAutoScrolling = false;
    let isValidPage = true;
    let isSimpleMode = false;
    let isAddKeyEvent = false;
    let isAddFullPictureLoadButton = false;
    let isAddFullPictureLoadFixedMenu = false;
    let isAddNewTabViewButton = false;
    let isOpenOptionsUI = false;
    let isOpenMenu = false;
    let isOpenGallery = false;
    let isOpenFilter = false;
    let isChangeNum = false;
    let fetchErrorArray = [];
    let fastDownload = false;
    let currentDownloadThread = 0;
    let downloadNum = 0;
    let getImgFn = "";
    let doc = document;
    const fragment = new DocumentFragment();
    let autoPagerSwitch = true;
    let httpFetchError = false;
    let currentPageNum = 0;
    let nextLink = null;
    let nextElement = null;
    let tempNextLink = null;
    let tempEles = [];
    const PC_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36";
    const Mobile_UA = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36";
    let loading_bak = "data:image/gif;base64,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83uGje9+g7TK7znAs/1N/3BQTmbMt6lvwRde10/Xu89+ZrjEJ07xilv84hjPuMY3zvGOe/zjIA+5yEdO8pKb/OQoT7nKV87ylrv85TCPucxnTvOa2/zmOM+5znfO8577/OdAD7rQh070ohv96EhPutKXzvSmO/3pUI+61KdO9apb/epYz7rWt871rnv962APu9jHTvaym/3saE+72tfO9ra7/e1wj7vc5073utv97njPu973zve++/3vgA+84AdP+MIb/vCIT7ziF8/4xjv+8ZCPvOQnT/nKW/7ymM+85jfP+c57/vOgD73oR0/60pv+9KhPvepXz/rWu/71sI+97GdP+9rb/va4z73ud8/73pH7/vfAD77wh0/84hv/+MhPvvKXz/zmO//50I++9KdP/epb//rYz772t8/97nv/++APv/jHT/7ym//86E+/+tfP/va7//3wj7/850//+tv//vjPv/73z//++///ABiAAjiABFiABniACJiACriADNiADviAEBiBEjiBFFiBFniBGJiBGriBHNiBHviBIBiCFxEIACH5BAUKAGgALCwBjAACATABAAf/gGiCg4SFhoeIiYqLjI2JAQYGHhgaEC8FHBQfOhaOnp+goaKjpKWmp6iKAausra0GNDEUJ52ptre4ubq7vGiuv8CrGCksG2e9yMnKy8yOwc/ABjgsHc3W19jZo9DcwCsiJ9ri4+TW3ee/IyI65e3u76Xo8q4YLtXw+Pn6gvP9rS8Dju0bSBCbv4PCKCwoyLAhL4QQDXCQ4LCixXgQIT6YeLGjx0UZQz7wUeujyY8hUxpQwOCkS4spY6748LJmwZg4SdyzyfMdTpwPXLTsSXTcz58oMhRdavAozgY+hjKdiszpURoIqGrdlaJECRIQNHhoYBXhAyBb0yKTkOGDghgQ/wyURRdDqtq7vDp8EEGD7NxgNC7gHYxsgQwRK/7+8mCDsONeHShAUMyqAYjHmHd1UJCYso/MoHOdKPBAcQm7oVOXsrDDw18SC1XLLsUABIa5EErO3g2q9m2rKCjyHv6JAQXXTjUIJ86ckQQYfpHqbk790IbJRyHErs690BkKpX/mQN29+wUSR1OUXz/ojILoKTmwn5+hc0wW89lbwPG0cf71O8AHkQc7/cfdAOGFhMJ2BlaXwQgxFdBgeR3YlxFaE+pTQgExiLADCwNkwKA1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";
    let autoPagerLoading_gif = "data:image/gif;base64,R0lGODlh8ADwAPcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgUFBQgICAoKChAQEBUVFRwcHCEhISQkJCcnJywsLC8vLzIyMjQ0NDU1NTc3Nzk5OTo6Ojw8PD09PT8/P0FBQUJCQkNDQ0VFRUZGRkhISEpKSk1NTVBQUFdXV1xcXGFhYWVlZWxsbHJycnl5eYCAgJ6enrGxsbGxsbGysbGysbGysbKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrOysrOzs7Ozs7Ozs7S0tLS0tLS0tLS0tLS0tLW1tbW1tbW1tba2tra2tre3t7e3t7i3uLi4uLi4uLm5ubu7u728vL6+vsDAwMLBwsPDw8PDw8PDw8TEw8TExMTExMTExMTExMXFxcXFxcbGxsfHxsfHx8fHx8fHx8fHx8jIyMjIyMjIyMjIyMnJycrKysrLysvMy8zMzM7Ozs/Pz9HR0dLS0tLS0tPT09TU1NXV1dfX19nZ2dra2tvb29vc3N3d3d7e3uDg4OHh4eLi4uTk5Obm5ubm5ujo6Onp6erq6urq6urq6uvr6+vr6+zs7Ozs7Ozt7e3t7e3t7e3u7e7u7u/v7/Dw8PHx8fHy8fLz8vP08/T09PT09PX19fX19fb29vb39vf39/f39/j4+Pn5+fv7+/z8/P7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJBwDsACwAAAAA8ADwAAAI/gDZCRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjyuTo7NerVKM2PQLUZ86TWQpnpZnTB5Cj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srKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKzsrKzsrKzs7O0s7O0tLS1tLS1tbW2tra4uLi5ubm6urq7uru8u7u9vL2+vr7BwMHCwsLDwsLDw8PDw8PDw8PDw8PDw8PEw8PExMTExMTExMTFxcXFxcXGxsbGxsbHx8fHx8fHx8fHx8fHyMfIyMjIyMjIyMjIyMjIyMjIyMjKysrMzczPz8/Q0NDR0dHS0tLS0tLT09PU1NTV1dXW1tbX19fX2NjZ2dnb29vb29vc3Nzd3d3d3d3e3t7f39/g4ODi4uLk5OTm5ubn5+fo6Ojp6enq6urq6urr6+vs7Ozs7Ozs7Ozs7Ozs7Ozs7e3t7e3t7e3t7e3t7u3u7u7v7+/w8PDw8fDx8vHy8/Lz8/Pz9PP09PT19fT19vX29vb29/b39/f3+Pf4+Pj4+Pj5+vn6+vr7+/v7+/v8/Pz8/Pz9/f3+/v7+/v7+/v7+/v7+/v7+/v7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8I/gDRCRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjyuRYrNaoTpQYBXrDxsyPUwpPgTHD5s0fRpQ6jbJVbKbTpyyFoeLkSE+aH1izZv3yY5TCUVjB/OCq9UeaPI44oSIGta3bjKswKWojlmzZuz9EKQyFt+/YNooyrXpLuDBCVJb2iPHLGCsohaDENi5LVgwfS6gMa37q65Min2IlT777xZNCT6Pxkv0yVNEnX5tjq8yVqc4PMKztpiatSeEm0bvLSgYDpk6mXLKTgxzWKc/W4JMxKcSkG/pd3FjzdBKm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urq6uru7u7u7u729vb+/v8DAwMHBwcLCwsLCwsPDw8PDw8PDw8PDw8PDw8TExMTExMTExMTExMXFxcXFxcbGxsbGxsfHx8fHx8fIx8jIyMjIyMjIyMjIyMnJycrLys3Nzc/Pz9DQ0NHR0dLS0tPT09PU1NTU1NbW1tfX19jZ2dra2tvb29zc3N3d3d7e3t7f3+Dg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6urq6urq6uvr6+vr6+zs7Ozs7e3t7e3t7e3u7e7u7u7u7u/v7+/w7/Dw8PDx8PHx8fLy8vPz8/T09PT19PX19fX19fb29vb29vf39/f39/f49/j4+Pj4+Pn5+fr6+vv7+/7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wj+ANMJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPK5FiM1qhNlBoRkvMGDZNTCk8xQfNGzqBGlDaNqlVsptOnLImp0vTIDxsmWLNmNcNklMJRWrlqZbKmzyNNqohBXcs24ypMi+BgFTu2LpNQCkPZ3cvEDJxFmFi1HUwYoSpLf87wXYz1k8JPjO2KPQPIkqrCmJ/66rTIZ2TGZjgp3PRZ8tyhizr5ysxaJS5MeE7TLV3XTCaFmmiXxoMJV+vfIIdx6rNVd+RLCi/NNm6aSZ9NwoBLvzhqEdflzPeaqaSwUvbP1xf+eZ1OvqGwS3Kxf9dOSSGl9eCxwrk0rLz9grIczVUPvzYkhZD0Z5wjstxXHiqKCMhcIwo1omBpYikClIGtlULIaQ+WxohCjGQIIVaElEJhYakMgqGHny2i0CIofsgEIZeNCJUtjPDXIl+HKHTIjbRxxYgtMspUTCQ8MpdjQonYWKRdkTQVZEucqNHXkrQdidCOVNKmhmhPpuTKH1NmWZqVB2EpZmmAuNKlSZOEeWZkZpBpkJlvLiZWe2uGdEocbtbJWCIKJeInbXFM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kJ3SeaH9t4AQBgcgoJ06mBDJ9yYwYmVp8AHKKQIc0ighcmlvAJe0OQINMigS4mqLMAKrSQIAUicEImujYALRmZg+mhB/eCPzoXuvBgM0Kpcl0B1UIh66JhCkkAIHSowmkBzJBB1VahCWcAIcsJWlKBAg9yC8AYpf6gkqEAIOGpEqoBAnCB9okBrA+KUFAQcl4AEUsI8r8BjrQRmWgaddGFEMc3ACIVCksugCeWEcf4EJykioG3EKcIACI9ABqkmHMdBvi8EGZoEWYSmpIkELjQADKVACIvABGoABDtoGQTEURUEISKEUtFCCogoTxRCqt7qrvNqrvvqrHRUQACH5BAkHAOoALAAAAADwAPAAhwAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQQEBAoKChYWFiUlJTQ0NJKSkqqqqrGxsbGysbGysbGysbGysbGysbGysbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbKysrGxsrGxsrGxsrGxsrGxsrGxsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrOysrOysrOysrOysrSzs7Szs7S0tLS0tLW1tbW1tba2tre3t7i3uLm4ubm5ubq6uru7u7y8vL6+vsDAwMLCwsLCwsPCwsPDw8PDw8PDw8PDw8PDw8TExMTExMTExMTExMTExMXFxcbFxcbGxsfHx8fHx8fHx8fIx8fIx8fIx8jIyMjIyMjIyMjIyMnJycrKysvMzM3Nzc/Pz9DQ0NLS0tLS0tPT09PT09XV1djY2Nra2tvb29zd3N3d3d7e3uDg4OLi4uPk5OXl5efn5+jo6Onp6enp6erq6urq6uvr6+vr7Ozs7Ozs7O3t7e3t7e3u7e7u7u7v7u/v7/Dw8PHx8fHy8fLy8vPz8/P08/T09PX19fX29fb29vf39/f39/f49/j4+Pn5+fn5+fz8/P39/f7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wj+ANUJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPK5Khs1ypToDQ12oMnzhJYCmGhiYNnDyNNoEyt2qVsptOnLJPFKsUJkZ0lWLNmPbNklcJVWNEs4ap1iR1DnErFagq1rVuMtEZhyiOWbNm7S1QpVIW379g8mEbReku4MMJYoRK18csYKyqFqMQ2Lku2TaJQsQxrfkrs1CWfYiVPvnvGlEJTo/GSPTP00ilim2Or/DUq0BI0rO2mJk1KYSnRu8tKRoMm0KhfspODRGbK0Nbgk0UpFKUb+l3cWA2ZQqa8+8VVmLj+Vrfe90wohaHIT8Z+5pJX7/AbIhOVZyxw9X7PgFIICv9osnmIwl18BBKkyyZYnTGef6p1olAnDAaHxia6FBgfLJZECB0amiikiYapkWUJUBbK5kojty0IYl+ZKJTJiiES14grJRoWCyPEqQgjXpcodMl9O5aHVSOZ1QgVL5mwFuRuaEiikCRL7sZVJrwYKZMyn0RpnZMJVaKjlnh9wpaVLJkyx1hg7sYlQlCmmRoac5xCpkq2JGKfm6mteZAkQOLZFxqJ2DKnSaBg5+d/ehrU5qGNkbXfoCHBsgeajI5WiUKV9FmpcEvoQSKkHPV326ajJVoQn6Q2KtajoGKESx/+o6baWJOYaiprWX3g0qpFpVB6a2OmEpTpr6qWsutEL35JLFbBDiSJsssu0eKxDuGiR6zR+tWsQM9m29geulILmbelPknuZHKKe5Co5/qFxqUJdduuakuwqq5AL87LGLxs6ssYJveqI0wgCvqLF63xQntuccKIiwsetvqLMEKVGMwYHuG2WssbFjO2rToVd0zaEm8IuitqIuPF754RG2wataL4mvISHy86M1bSqcvuzGfUfPOo9orbiaEpr6zoz0s4GDC+RHf8sZcp4zbt0gJZonC0E7M8syVUE6RMIi1763PKiYw5p8kMKWPI1cSObbBYhpitENqy5fLG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5Fqu5nqu6Jqu6joQAQEAIfkECQcA7AAsAAAAAPAA8ACHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBQUFCQkJEBAQFxcXISEhIyMjJSUlKCgoKysrLy8vODg4QEBARkZGTk5OVlZWW1tbYGBgZGRkZ2dna2trbm5ucXFxdHR0d3d3e3t7fX19hISEi4uLkpKSl5eXnJycn5+foaKho6OjpKSkpKSkpaWlpaWlpaalpqampqemp6enp6inqKioqaqpqquqrK2sra6trq+ur7CvsLGwsbGxsbKxsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKys7OztLS0tLS0tbW1tbW1tba1tra2uLi4urq6vLy8v7+/wMDAwcLBw8PDw8PDw8PDw8PDw8PDw8PDxMTDw8TDxMTExMTExMTExcXFxcXFxsbGx8fHx8fHx8fHyMfIyMfIyMfIyMfIyMjIyMjIyMjIyMjIyMnJycnJysrKy8vLzM3Nzs/P0NDQ0dHR0tLS09PT1NTU1dXV19fX2dnZ29vb3Nzc3d3d3t7e39/f4ODg4+Pj5eXl5+fn6Ojo6enp6unq6urq6urq6+vr6+vr7Ozs7Ozs7e3t7e3t7e7t7u7u7+/v8PDw8PDw8fHx8fLx8vPy8/Pz9PT09PX09fX19vb29vf29/f39/f3+Pj4+fn5+fn5/Pz8/f39/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////CP4A2QkcSLCgwYMIEypcyLChw4cQI0qcSLGixYsYM2rcyLGjx48gQ4ocSbKkyZMoU6pcybKly5cwY8rk2OzXK1WlPEHys+fOF1oKaX25s8cPJE+lVL361Wym06csm9lKBQqR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srKysrKysrKysrKysrKysrKysrKysrOysrOysrOys7Ozs7SztLS0tbW1tra2t7e3uLi4ubq5uru6u7u7vLy8vL28vb29vr6+v7+/v7+/wcDBwsLCwsLCw8PDw8PDw8PDw8PDw8PDw8PDw8PDxMTExMTExMTExMTExMTExMTExMXExcXFxcXFxsbGxsbGxsfGx8fHx8fHx8fHx8fHx8fHx8jHyMjIyMjIyMjIyMjIysrKzMzMzs7O0NDQ0dHR0tLS09PT09PT1NTU1dXV1tbW2NfX2tra29vb3Nzc3Nzc3d3d3t7e39/f4eHh4uLj5OPk5eXl5ubm6Ojo6enp6enp6urq6urq6+vr6+vr7Ozs7Ozs7ezs7e3t7e3t7e3t7u7u7u7u7+/v8PDw8fHx8fHx8vLy8/Pz8/Pz9PT09PT09fX19vb29vb29/f39/f39/f3+Pj4+fn5+vr6+vr6+vr6+/v7+/v7+/v7/Pz8/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////CP4A2wkcSLCgwYMIEypcyLChw4cQI0qcSLGixYsYM2rcyLGjx48gQ4ocSbKkyZMoU6pcybKlSWfMXMqcSdNkr0sZLlioQGFCBAcG2iiMRQaNmzqNLn0yxaqXs5pQo8qMBUcnBQgLFhgwoFUrVwMcFLIiE6SsWbJl2QjKVGpWTKlw42p0VudCBQlfs27dy3cvBoWrzAoWjJYsmTeVRNmSy7jxwjgWKDDY67WvZcp/E6YazLlzWTJlDIGa5bh0XFR2gV5ezfqCwlOeYxMmQxZNJVTHTOtmGeoCBb2sg1te4DphKdnIPeMRFWy3c5GtfFcWTr1vcYShkmvvLMjUsufgM/5mqDC9uvm9FhSC2s5+MJlKrcLLh8jqgoTy5/OnT+ipvX/BcITy3XwEGmRJBfkleNl+CGny339oBYEJLwUW6AaC+CmYXwUKXfLgh2ZVEkuF4KVBgYYo9sVhQh6CCCIZjbxComlxnJjijVutiFAlLr5YViOkzRgXJuThaCQFCknS45JBWPKLkFDtYoGRVBqAZEJKMtkj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9vb39/f39/f4+Pj4+Pj5+fn5+fn6+vr7+/v8/Pz+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8I/gDVCRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqVLgsmWvZxJs6bFZbtaqSr16ZKhP3SsxFLY54EIEidSqGDxYsanXTajSmWpTFaqUJL2WHHjxorXr15bKZzB4UGHB2jLPihLAsWKF4GGTp1LFyOtU54Cbd3LFyxYVgplqEVLuHDasyVUvDgks67jxwZlmZoEp6/fy34BJ4RhuHNnDmU5fEDRQhDk01KJreo0p6tlzLC3rlLI2bNtw6DLilABYzbq3yl9nWLE9XXs41ZQKXxxu7ntDhxQvDAFvDpIZKokeXWNvDvYUwpd/jgf/1y6K+voL7by5L097FIKWwwmT39tWRUz0ut3iOxUIO7uBegVfAmxcFZ9CBZWggti7ecgQbqAIuCEfomi0AoJZmgWYSt48uB+sXBiHIXufXKhhigSpsIfH1b3yiUjkliiQiocmGKGoKVgR4uQyQIjgDJS2AmNNxb5QAqm8TgVL+wVF6SMbmiiUApG3giaCqAoWdMyo8T4pIBSJkRllSmC9sAKuWjpkip4fOmmV5tMSaaRHIwAg5oq3TKJl28GGCZCKcw3Z4ooRIKnSaU42eeXfx4U6KB0dsDCoSLFUsiiizZq0JiQFtlBByboQalHpACJ6ZOaFsRpp1VOOmpG/rkkcuqibsQpJquDnmDrqxSlouisbqZK0Kq40vkCrxN9Auypwg5EbLFGqgAMsg7lcumymDYr0LPQFmkCJdQutAq2s2qrDrfdWnlnuAeVQm65cqYLqavsDtTku9lOKai8RXKggjL1BsMIvvDeyi+kJ6QSbi5/EFwwoPseXGYHJEyCbC1yOHxqlFPaKDGZIByCrCoaMxvvx2RycCy1ppTcJ8cGo9wvBy7U667LwZ4s8430sisKzk/CDOjOVq5QL0GfmAp0e0I7SnSKKiBzNEEiLj1h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ACH5BAkHAOwALAAAAADwAPAAhwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgsLCxcXFyYmJi4uLjMzMzc3Nzg3ODk5OTk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkREREVFRUZGRkdHR0dHR0dHR0hISEhISElJSUpKSktLS01NTVBQUFNTU1ZWVlpaWl5eXmZlZW1tbXR0dHl5eXx8fIGBgYSEhIeHh4mJiY2NjZKSkpaWlpuamqCfn6SkpKuqqrCvr7KxsbKxsbKxsbKxsbKxsbKxsbKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKzsrKzsrOzs7S0tLS1tLW1tba2tre3t7i4uLm6uru7u72+vr/Av8HBwcPDw8PDw8PDw8PDw8PEw8TExMTExMTFxMXFxcbGxsfHx8fHx8fHx8jHyMjHyMjIyMjIyMrKysvMzM3Nzc/Pz9HR0dHR0dLS0tPT09TU1NXV1djY2Nra2tvb29zc3N7e3t/f3+Hh4eTk5OXl5ebm5ufn5+np6enp6erp6erq6uvr6+vr6+zs7Ozs7O3t7O3t7e3t7e7u7u7v7u/v7/Dw8PHx8fHx8fLy8vPz8/T09PX19fX19fb29vf49/r6+vv7+/z8/Pz8/P39/f7+/v7+/v7+/v7+/v7+/v7+/v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wj+ANkJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPK5OiMWK1XqkhxesTokJxcCnPJOcToESdSql7VIuZsptOnLJ3temWqkiI5WLEOyrq1lsJaWcNy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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
    const MutationObserverConfig = {
        childList: true,
        subtree: true
    };
    const smoothOptions = {
        behavior: "smooth",
        block: "center",
        inline: "center"
    };
    const instantOptions = {
        behavior: "instant",
        block: "center",
        inline: "center"
    };
    //自定義站點規則
    const customData = [{
        name: "交通部觀光署 桌布下載",
        reg: /^https?:\/\/www\.taiwan\.net\.tw\/m1\.aspx\?sNo=0012076$/,
        imgs: ".media-download>a:last-child",
        category: "photo"
    }, {
        name: "免費圖庫相片",
        url: {
            h: "www.pexels.com"
        },
        SPA: true,
        init: async () => {
            addNewTabViewButton();
            const get = async () => {
                let imgs = fn.gae("article[class^=MediaCard_card] img[srcset]:not(.get)");
                if (imgs.length > 0) {
                    imgs.forEach(img => img.classList.add("get"));
                    fn.getImgSrcArr(imgs).forEach(src => {
                        if (!src.includes("/free") && !src.includes("/lib/avatars/")) {
                            src = src.replace(/\?.+$/, '');
                            setArray.add(src);
                        }
                    });
                }
                let videos = fn.gae("video[class^=VideoTag_video]:not(.get)");
                if (videos.length > 0) {
                    videos.forEach(video => {
                        video.classList.add("get");
                        let src = video.src;
                        setVideoArray.add(src);
                    });
                    videoSrcArray = [...setVideoArray];
                }
                if (captureTotal != setArray.size) {
                    captureTotal = setArray.size;
                    await captureSrcB();
                }
            };
            await get();
            fn.addMutationObserver(async () => {
                if (captureExclude()) return;
                await get();
            });
        },
        imgs: () => setArray,
        capture: () => _this.imgs(),
        downloadVideo: true,
        category: "photo"
    }, {
        name: "wallhaven",
        url: {
            h: "wallhaven.cc",
            e: "figure[data-wallpaper-id]"
        },
        SPA: true,
        init: async () => {
            addNewTabViewButton();
            const get = async () => {
                let figures = fn.gae("figure[data-wallpaper-id]:not(.get)");
                if (figures.length > 0) {
                    figures.forEach(figure => {
                        figure.classList.add("get");
                        const id = figure.dataset.wallpaperId;
                        const isPng = !!fn.ge(".thumb-info .png", figure);
                        const ex = isPng ? "png" : "jpg";
                        const src = `https://w.wallhaven.cc/full/${id.substring(0, 2)}/wallhaven-${id}.${ex}`;
                        setArray.add(src);
                    });
                }
                if (captureTotal != setArray.size) {
                    captureTotal = setArray.size;
                    await captureSrcB();
                }
            };
            await get();
            fn.addMutationObserver(async () => {
                if (captureExclude()) return;
                await get();
            });
        },
        imgs: () => setArray,
        capture: () => _this.imgs(),
        category: "photo"
    }, {
        name: "小黃書/8色人體攝影",
        url: {
            h: [
                /^([a-z]{2}\.)?xchina\.(co|biz)$/,
                /^(tw\.)?8se\.me$/
            ],
            p: /^\/(photo|amateur)\/id-\w+\.html$/,
            e: ".tab-content div:has(>.fa-picture-o)"
        },
        init: () => {
            fn.run("$(document).off('keydown');");
            fn.remove("//div[@id='tab_1']/div[contains(text(),'推')] | //div[@class='rules']/ul/li[contains(text(),'推')]");
        },
        imgs: async () => {
            const isMp4 = fn.ge("video[src$='mp4']");
            if (!!isMp4) {
                const {
                    videos,
                    domain
                } = _unsafeWindow;
                videoSrcArray = videos.map(e => domain + e.url);
            }
            const [, album_id] = /id-([^.]+)/.exec(fn.lp);
            let [numP] = fn.gt(".tab-content div:has(>.fa-picture-o)").match(/\d+/);
            numP = Number(numP);
            const thumb = fn.ge("img.cr_only");
            const srcArrFn = (total, photoUrl = "https://img.xchina.biz/photos/", mode = 1) => {
                let suffix = ".jpg";
                if (mode === 2) {
                    suffix = "_600x0.webp";
                }
                return fn.arr(total, (v, i) => photoUrl + album_id + "/" + String(i + 1).padStart(4, "0") + suffix);
            };
            if (!!thumb) {
                const thumb_src = thumb.src;
                const OOOI = thumb_src.includes("/0001_600x0.webp");
                const [photoUrl] = /^https?:\/\/[^\/]+\/[^\/]+\//.exec(thumb_src);
                if (OOOI) {
                    thumbnailSrcArray = srcArrFn(numP, photoUrl, 2);
                    return srcArrFn(numP, photoUrl);
                } else {
                    let max;
                    try {
                        let pageUrls = fn.gau(".pager a[href]");
                        let lastUrl = pageUrls.at(-1);
                        let [, lastNum] = lastUrl.match(/\/(\d+)\.html$/);
                        max = Number(lastNum);
                    } catch {
                        max = 1;
                    }
                    if (max > 1) {
                        await fn.getNP(".photos>a", ".pager a[current=true]+a:not(.next)", null, ".pager", 1500);
                    }
                    thumbnailSrcArray = fn.getImgSrcArr("img.cr_only");
                    if (numP != thumbnailSrcArray.length) {
                        setTimeout(() => {
                            fn.hideMsg();
                            fn.showMsg("圖片數量不符合,請反饋", 5000);
                        }, 1500)
                    }
                    if (fn.lp.includes("amateur")) {
                        return thumbnailSrcArray;
                    } else {
                        return thumbnailSrcArray.map(e => e.replace("_600x0", "").replace(".webp", ".jpg"));
                    }
                }
            } else {
                const srcArr = srcArrFn(numP);
                const [first] = srcArr;
                const check1 = await fn.checkImgStatus(first);
                if (check1.ok) {
                    return srcArr;
                } else {
                    const test_src = first.replace("/photos/", "/photos2/");
                    const check2 = await fn.checkImgStatus(test_src);
                    if (check2.ok) {
                        return srcArr.map(src => src.replace("/photos/", "/photos2/"));
                    } else {
                        return [];
                    }
                }
            }
        },
        button: [4, "24%", 1],
        insertImg: [
            ["//div[div[@class='photos']]/*[last()]", 2, ".pager,.photos"], 2
        ],
        customTitle: () => {
            try {
                let text = "";
                let texts = [];
                [
                    "div:has(>.fa-video-camera) a",
                    "div:has(>.fa-video-camera) .joiner+a",
                    "div:has(>.fa-calendar)",
                    "div:has(>.fa-file-o)",
                    ".models div,.actorsOrModels",
                    "div:has(>.fa-address-card-o)"
                ].forEach((s, i, a) => {
                    let t = document.querySelector(s)?.innerText;
                    texts.push(t);
                    if (a.length - 1 == i && !!texts[4]) {
                        if (t.includes(texts[4])) {
                            text = text.replace(texts[4], "");
                        }
                    }
                    if (!!t && t?.length > 0) {
                        text += " " + t;
                    }
                    if (i == 0 && !!t) {
                        text += " -";
                    }
                });
                if (location.pathname.includes("/amateur/")) {
                    text = document.querySelector(".fa-angle-double-right+a").innerText + " -" + text;
                }
                if (text.includes("秀人")) {
                    text = text.replace("Vol. ", "NO.");
                } else {
                    text = text.replace("Vol. ", "Vol.");
                }
                text = text.replace(/(\d+)-(\d+)-(\d+)/, "$1.$2.$3");
                text = text.replace(" 秀人网 ", " [Xiuren秀人网] ").replace(" 秀人網 ", " [Xiuren秀人網] ")
                    .replace("各国其他套图 -", "").replace("各國其他套圖 -", "")
                    .replace("其他地区套图", "").replace("其他地區套圖", "")
                    .replace("其他套图 -", "").replace("其他套圖 -", "")
                    .trim();
                if (text.includes("其他中国工作室") || text.includes("其他中國工作室")) {
                    let t = document.querySelector("div:has(>.fa-tags)+div:has(>.fa-tags)")?.innerText;
                    if (!!t && t?.length > 0) {
                        text = text.replace(/其他中国工作室|其他中國工作室/, t);
                    }
                }
                if (text.includes("Graphis")) {
                    let t = document.querySelector("div:has(>.fa-tags)+div:has(>.fa-tags)")?.innerText;
                    if (!!t && t?.length > 0) {
                        text = text.replace("Graphis", "Graphis " + t);
                    }
                }
                return text;
            } catch {
                return document.title;
            }
        },
        css: `
body {
    overflow: unset !important;
}
.push-slider,
.article:has(>div>.media),
div:has(>.links),
a[clickmode=ad],
a:has(>div>div>img),
.photos>div.item,
.jquery-modal.blocker.current,
.push-top,
.push-bottom,
.slider-ad,
.article.ad,
.pager>.tips,
.photoMask,
.banner_ad,
.banner-sexgps {
    display: none !important;
}
        `,
        topButton: true,
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "小黃書/8色人體攝影 AD",
        url: {
            h: [
                /^([a-z]{2}\.)?xchina\.(co|biz|life|fun)$/,
                /^(tw\.)?8se\.me$/
            ]
        },
        init: () => fn.addMutationObserver(() => fn.remove("[class*='exoclick']")),
        css: `
body {
    overflow: unset !important;
}
[class*='exoclick'],
.push-slider,
.article:has(>div>.media),
.article:has(>.like-960x80),
div:has(>.links),
a[clickmode=ad],
a:has(>div>div>img),
.photos>div.item,
.jquery-modal.blocker.current,
.push-top-container,
.push-top,
.push-bottom,
.slider-ad,
.article.ad,
.pager>.tips,
.photoMask,
.banner_ad,
.banner-sexgps {
    display: none !important;
}
        `,
        category: "ad"
    }, {
        name: "紳士会所",
        host: ["www.hentaiclub.net"],
        reg: /^https?:\/\/www\.hentaiclub\.net\/r\d+\/\d+\.html$/,
        imgs: "div[data-fancybox]",
        button: [4],
        insertImg: [
            ["#masonry", 2, "#masonry"], 2
        ],
        customTitle: ".post-info-text",
        fancybox: {
            v: 3,
            css: false
        },
        hide: ".banner-top",
        category: "nsfw2"
    }, {
        name: "NLegs/HoneyLeg/Lady Lap/Nuyet/LegBabe", //需搭配專用腳本 https://greasyfork.org/scripts/463123
        host: ["www.nlegs.com", "www.honeyleg.com", "www.ladylap.com", "www.nuyet.com", "www.legbabe.com"],
        reg: [
            /^https?:\/\/www\.nlegs\.com\/girls\/\d+\/\d+\/\d+\/\d+\.html$/,
            /^https?:\/\/www\.honeyleg\.com\/article\/\d+\/\d+\/\d+\/\d+\.html$/,
            /^https?:\/\/www\.ladylap\.com\/show\//,
            /^https?:\/\/www\.nuyet\.com\/gallery\//,
            /^https?:\/\/www\.legbabe\.com\/hot\/[^\.]+\.html$/
        ],
        imgs: ".col-md-12.col-xs-12 img[src^=blob],.col-md-12.col-lg-12 img[src^=blob]",
        repeat: 1,
        button: [4],
        insertImg: ["//div[img[starts-with(@src,'blob')]]", 0],
        go: 1,
        customTitle: "strong",
        fetch: 1,
        category: "nsfw2"
    }, {
        name: "雅拉伊", //免VIP僅支援PC版和圖片命名是簡單數字遞增的。
        host: ["www.yalayi.com"],
        reg: /^https?:\/\/www\.yalayi\.com\/gallery\/\d+\.html/i,
        imgs: async () => {
            await fn.waitEle(".bigimg>img");
            let [max] = fn.ge(".tishiwenzi-box").innerText.match(/\d+/);
            let firstImg = fn.ge(".bigimg>img");
            let [path] = firstImg.dataset.original.match(/.+\//);
            let testArr = [path + "1.jpg", path + "01.jpg", path + "001.jpg", path + "0001.jpg"];
            let ok = false;
            let pad = 1;
            for (let [i, test] of testArr.entries()) {
                let obj = await fn.checkImgStatus(test);
                console.log(`確認圖片[${i}]`, obj);
                if (obj.ok) {
                    ok = true;
                    pad = i + 1;
                    break;
                }
            }
            if (ok) {
                return [firstImg.src, ...fn.arr(max, (v, i) => path + String(i + 1).padStart(pad, "0") + ".jpg")];
            } else {
                return [];
            }
        },
        button: [4, "24%", 4],
        insertImg: [".bigimg", 2],
        customTitle: () => fn.title(" - ", 3),
        category: "nsfw1"
    }, {
        name: "JKF",
        host: ["www.jkforum.net"],
        reg: /^https?:\/\/www\.jkforum\.net\/(p\/)?thread/,
        init: () => fn.waitEle("img[id^=aimg]"),
        imgs: () => hasTouchEvent ? fn.gae("img[id^=aimg]:not([style])") : fn.gae("img[id^=aimg][zoomfile]"),
        capture: () => _this.imgs(),
        customTitle: ".title-hd h1,.post-title",
        category: "nsfw2"
    }, {
        name: "草榴社區",
        host: ["www.t66y.com", "cl.6962x.xyz"],
        url: {
            e: ["//div[@id='header']//b[text()='草榴社區' or text()='草榴社区']", "img[ess-data]"],
            p: /^\/htm_data\/\d+\/\d+\/\d+\.html$/
        },
        imgs: () => fn.fetchDoc(fn.url).then(dom => fn.gae("img[ess-data]", dom)),
        capture: () => _this.imgs(),
        customTitle: "h4.f16",
        category: "nsfw2"
    }, {
        name: "24FA",
        host: ["www.24fa.com"],
        link: "https://www.24fa.com/c49.aspx",
        //reg: /^https?:\/\/(www\.)?\d{2,3}(m|w|fa\w?|aa|xx)?\.[a-z]{2,4}\/m?n\w+\.aspx/,
        //include: "#content img",
        url: {
            t: "24FA",
            p: ".aspx",
            e: ["#content img", ".pager"]
        },
        init: "document.onkeydown=null",
        imgs: () => fn.getImgA("#content img", ".pager a:not([title])"),
        button: [4],
        insertImg: ["#content", 2],
        autoDownload: [0],
        next: ".prevNews>a",
        prev: ".nextNews>a",
        customTitle: "h1",
        hide: "body>ins",
        category: "nsfw2"
    }, {
        name: "Hit-x-Hot格式",
        host: ["www.hitxhot.org", "hitxhot.com"],
        reg: [
            /^https?:\/\/www\.hitxhot\.org\/gallerys\/\w+\.html/i,
            /^https?:\/\/hitxhot\.com\/blog\/\w+\.html/i
        ],
        init: () => fn.clearElementEvent(),
        imgs: async () => {
            let max;
            try {
                [max] = fn.gt(".entry-title").match(/\d+$/);
            } catch {
                max = 1;
            }
            return /\?m=1/.test(siteUrl) ? await fn.getImg(".entry-content img", max, "8") : await fn.getImg(".entry-content img", max);
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.title(/^[a-z-\s\.I]+:/i).split("|")[0].trim(),
        category: "nsfw2"
    }, {
        name: "Depvailon格式",
        host: [
            "www.depvailon.com",
            "nungvl.net",
            "www.kaizty.com",
            "lootiu.com",
            "thismore.fun",
            "cosxuxi.club",
            "baobua.com"
        ],
        reg: [
            /^https?:\/\/www\.depvailon\.com\/[^\.]+\.html/,
            /^https?:\/\/cosxuxi\.club\/[^\.]+\.html/,
            /^https?:\/\/www\.kaizty\.com\/photos\//,
            /^https?:\/\/nungvl\.net\/gallerys\//,
            /^https?:\/\/lootiu\.com\/gallery\//,
            /^https?:\/\/thismore\.fun\/view\//,
            /^https?:\/\/baobua\.com\/post\//
        ],
        init: async () => {
            await fn.clearElementEvent();
            await fn.waitVar("jQuery");
            fn.run("jQuery(document).off();jQuery('body').off();");
            fn.createImgBox(".contentme,.contentme2", 2);
            fn.remove(".mobiletop");
        },
        imgs: async () => {
            let max;
            try {
                [max] = fn.gt("h1,h2").match(/\d+$/);
            } catch {
                max = 1;
            }
            return /\?m=1/.test(siteUrl) ? await fn.getImg(".contentme img,.contentme2 img", max, "8") : await fn.getImg(".contentme img,.contentme2 img", max);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".contentme,.contentme2"], 2
        ],
        endColor: "white",
        customTitle: () => fn.dt({
            t: document.title.split("|")[0],
            d: [
                /^[a-z-\s\.]+:/i,
                "NứngVL.net:"
            ]
        }),
        category: "nsfw2"
    }, {
        name: "pic.yailay.com格式",
        url: {
            h: ["pic.yailay.com", "www.dongojyousan.com"],
            p: ["/articles/"]
        },
        init: () => fn.clearElementEvent(),
        imgs: () => fn.getImgA(".VKSUBTSWA img", "div[id^=post] a"),
        button: [4],
        insertImg: [".VKSUBTSWA", 2],
        insertImgAF: () => fn.remove(".pagination,h3+.HCRIN"),
        customTitle: () => fn.title(/^[a-z-\s\.I]+:/i).split("|")[0].trim(),
        category: "nsfw2"
    }, {
        name: "RedSeats.Org格式",
        url: {
            h: ["redseats.org", "cn.looives.com"],
            p: ["/gallery/", "/view/"]
        },
        imgs: async () => {
            let links = fn.gau("div[id^=post] a");
            links.unshift(fn.url);
            fn.showMsg(displayLanguage.str_14, 0);
            let loop = true;
            let pn = 13;
            let fetchNum = 1;
            const getNext = () => {
                return fn.fetchDoc(fn.lp + "?page=" + pn).then(dom => {
                    fn.showMsg(`${displayLanguage.str_14} (Page${fetchNum += 1})`, 0);
                    if (fn.ge("div[id^=post]", dom)) {
                        links = [...links, ...fn.gau("div[id^=post] a", dom)];
                    } else {
                        loop = false;
                    }
                });
            };
            while (loop) {
                await getNext();
                pn += 12;
            }
            return fn.getImgA(".VKSUBTSWA img", links);
        },
        button: [4],
        insertImg: [".VKSUBTSWA", 2],
        insertImgAF: () => fn.remove("h3+.HCRIN"),
        customTitle: () => fn.dt({
            t: fn.title(/^[a-z-\s\.I]+:/i).split("|")[0].trim(),
            d: " - 1.jpg"
        }),
        category: "nsfw2"
    }, {
        name: "TGStat Show more",
        reg: /^https?:\/\/([a-z]{2}\.)?tgstat\.com\//,
        observerClick: "//button[contains(text(),'Show more')]",
        category: "autoPager"
    }, {
        name: "Telegram Web",
        host: ["telegra.ph"],
        reg: /^https?:\/\/telegra\.ph\/.+/,
        imgs: () => {
            fn.showMsg(displayLanguage.str_01, 0);
            return fn.fetchDoc(fn.url).then(dom => fn.gae(".tl_article img", dom));
        },
        capture: () => _this.imgs(),
        customTitle: "h1",
        //setFancybox: true,
        category: "nsfw2"
    }, {
        name: "Rentry.co",
        host: ["rentry.co"],
        reg: () => /^https?:\/\/rentry\.co\/\w+$/.test(fn.url) && fn.ge("img"),
        imgs: "img",
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "新闻吧/新闻屋/新娱乐在线/新娱乐网/福建热线/山东热线/广西热线/武汉热线/天津热线/云南热线/甘肃热线",
        link: "https://www.xinwenba.net/web/meinv/",
        init: () => fn.createImgBox(".main", 1),
        url: {
            h: [
                "www.xinwenba.net",
                /\.xwbar\.com$/,
                /\.dv67\.com$/,
                /\.xinent\.net$/,
                /\.fjrx\.org$/,
                /\.sdrx\.org$/,
                /\.gxrx\.org$/,
                /\.whrx\.org$/,
                /\.tjrx\.org$/,
                /\.ynrx\.org$/,
                /\.gsrx\.org$/,
                /\.xwwu\.net$/
            ],
            p: /^\/plus\/view-\d+-\d+\.html$/,
            e: ".main img"
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".paging>li>a,.tags>li>a,.pre_next>li>a").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".main img", max, "5");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".view_img .main"], 2
        ],
        insertImgAF: (parent) => {
            let text = fn.ge(".view_img .text");
            if (text) {
                insertBefore(parent, text);
            }
        },
        autoDownload: [0],
        next: "//li[contains(text(),'上一篇')]/a",
        prev: "//li[contains(text(),'下一篇')]/a",
        customTitle: ".title>h1",
        hide: "div.web",
        category: "nsfw1"
    }, {
        name: "四海资讯/娱乐吧/娱乐屋/娱乐宝/美女图片库",
        link: "https://www.shzx.org/b/12-0.html",
        url: {
            h: [
                /\.shzx\.org$/,
                "www.yuleba.org",
                "m.entba.net",
                /\.entwu\.com$/,
                /\.xwbzx\.com$/,
                /\.entbao\.com$/
            ],
            p: /\/a\/[\d-]+\.html$/,
            e: ".main img"
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".paging>a").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".main img", max, "5");
        },
        button: [4],
        insertImg: [".main", 2],
        insertImgAF: (parent) => {
            let text = fn.ge(".a_img .text");
            if (text) {
                insertBefore(parent, text);
            }
        },
        autoDownload: [0],
        next: ".pre_next li:last-child a",
        prev: ".pre_next li:first-child a",
        customTitle: ".title>h1",
        css: ".a_img .main img{max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "留园酷",
        host: ["www.cool18.com", "wap.cool18.com"],
        reg: [
            /^https?:\/\/www\.cool18\.com\/bbs\d*\/index\.php\?app=forum&act=threadview&tid=\d+/,
            /^https?:\/\/wap\.cool18\.com\/index\.php\?app=index&act=view&cid=\d+/
        ],
        imgs: "img[mydatasrc],#shownewsc img,.show_content img",
        customTitle: () => fn.dt({
            s: ".show_content b,h1.article-tit",
            d: /(\s?\.?)?\s?\(\d+P\)\s?/i
        }),
        hide: ".img_ad_list",
        category: "nsfw2"
    }, {
        name: "我为人人",
        host: ["2048.info", "2048.cc"],
        url: {
            e: "link[rel][title$='人人']",
            p: "/2048/read",
            s: "tid=",
        },
        imgs: "#read_tpc img",
        customTitle: "#subject_tpc",
        category: "nsfw2"
    }, {
        name: "秀人集",
        host: ["www.xiuren51.top"],
        url: {
            e: "//div[@class='item_info']//a[text()='秀人集']",
            p: /\/\w+\/\d+\.html$/
        },
        init: () => {
            let pag = fn.gae(".page");
            if (pag.length > 0) pag[0].remove();
        },
        imgs: () => fn.getImg(".content>p img[alt]", fn.gt(".page a:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: ["//div[p[img[@alt and @title]]]", 2],
        autoDownload: [0],
        next: "//span[contains(text(),'下一篇')]/a[contains(@href,'html')]",
        prev: "//span[contains(text(),'上一篇')]/a[contains(@href,'html')]",
        customTitle: ".item_title>h1",
        hide: ".content br",
        category: "nsfw1"
    }, {
        name: "秀人美女網",
        host: ["www.xiu01.top"],
        url: {
            e: "//div[@class='single-cat']/a[text()='秀人美女网']",
            p: /\/\w+\/\d+\/\d+\.html$/
        },
        imgs: () => fn.getImg(".content p img[alt]", fn.gt(".page a:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: ["//div[p[img[@alt]]]", 2],
        autoDownload: [0],
        next: "//span[contains(text(),'下一篇')]/a[contains(@href,'html')]",
        prev: "//span[contains(text(),'上一篇')]/a[contains(@href,'html')]",
        customTitle: ".item_title>h1",
        hide: ".item_info>a,p[align='center']:has(>img),.item_title>div[id],.item_title>a,.content br,.bottom_fixed,.update_area_lists>div[id]",
        category: "nsfw1"
    }, {
        name: "极品性感美女",
        host: ["www.xinggan5.top", "尤物网.Com"],
        url: {
            e: "//div[@class='toptip']/a[text()='极品性感美女']",
            p: /\/\w+\/\w+\.html$/
        },
        init: () => {
            let pag = fn.gae(".pagination");
            if (pag.length > 0) pag[0].remove();
            let p = fn.gae("//article/p[not(img)]");
            if (p.length > 0) {
                let te = fn.ge(".article-content");
                p.forEach(e => insertBefore(te, e));
            }
        },
        imgs: () => fn.getImg(".article-content img[alt]", fn.gt("a.current~*:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: [
            ["//div[@class='pagination'][last()]", 1, "//p[img[@alt]]"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: ".article-nav-next>a[href$=html]",
        prev: ".article-nav-prev>a[href$=html]",
        customTitle: ".article-title",
        hide: ".article-header>div[id],.article-header>a,.article-content br,img[src*='zz1.gif'],.bottom_fixed,.article-content~a,#bottom-banner,.content>div[id]",
        category: "nsfw1"
    }, {
        name: "性感美女",
        host: ["www.5201025.xyz"],
        url: {
            e: "//h1[@class='logo']/a[@title='性感美女尤物']",
            p: /\/\w+\/\w+\.html$/
        },
        init: () => {
            let pag = fn.gae(".pagination");
            if (pag.length > 0) pag[0].remove();
            let p = fn.gae("//article/p[not(img)]");
            if (p.length > 0) {
                let te = fn.ge(".article-content");
                p.forEach(e => insertBefore(te, e));
            }
        },
        imgs: () => fn.getImg(".article-content img[alt]", fn.gt("a.current~*:last-child", 2), 6),
        button: [4],
        insertImg: [
            ["//div[@class='pagination'][last()]", 1, "//p[img[@alt]]"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: ".article-nav-next>a[href$=html]",
        prev: ".article-nav-prev>a[href$=html]",
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "爱美女网",
        host: ["www.20mn.top"],
        url: {
            e: "//section[@class='container']//a[text()='爱美女网']",
            p: /\/\w+\/\w+\.html$/
        },
        imgs: () => fn.getImg(".imgwebp p img[alt]", fn.gt(".page a:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: ["//div[p[img[@alt]]]", 2],
        autoDownload: [0],
        next: "//span/b[contains(text(),'下一篇')]/a[contains(@href,'html')]",
        prev: "//span/b[contains(text(),'上一篇')]/a[contains(@href,'html')]",
        customTitle: ".focusbox h1+div",
        css: ".imgwebp br,img[src*='zz2.gif']{display:none!important}",
        category: "nsfw1"
    }, {
        name: "漂亮美女网",
        host: ["www.plmn5.cc", "plmn.cc"],
        reg: /^https?:\/\/(www\.)?plmn5\.cc\/\w+\/\d+\.html/i,
        include: ".page>a",
        imgs: () => fn.getImg(".newstext p img[alt]", fn.gt(".page a:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: ["//div[p[img[@alt]]]", 2],
        autoDownload: [0],
        next: "//span/b[contains(text(),'下一篇')]/a[contains(@href,'html')]",
        prev: "//span/b[contains(text(),'上一篇')]/a[contains(@href,'html')]",
        customTitle: ".news-title-h1",
        hide: ".newstext br,img[src*='zz2.gif']",
        category: "nsfw1"
    }, {
        name: "爱看美女网",
        host: ["www.ik009.top"],
        url: {
            e: ["//i[@class='iconfont icon-shouye']/following-sibling::a[text()='爱看美女网']", ".info-pagebar>a"],
            p: /^\/\w+\/\d+\.html$/
        },
        init: () => {
            let pag = fn.gae(".pagebar");
            if (pag.length > 0) pag[0].remove();
        },
        imgs: () => fn.getImg(".info-imtg-box img[alt]", fn.gt(".pagebar>*:last-child", 2), 3, null, 100),
        button: [4],
        insertImg: ["//p[img[@alt]]", 2],
        autoDownload: [0],
        next: ".info-next li:last-child a",
        prev: ".info-next li:first-child a",
        customTitle: "h1",
        category: "nsfw1"
    }, {
        name: "美人图",
        url: {
            t: "美人图",
            h: "meirentu",
            p: /\/pic\/\d+\.html$/
        },
        imgs: () => fn.getImg(".content_left img[alt]", fn.gt(".page a:last-child", 2), 5),
        button: [4],
        insertImg: [".content_left", 2],
        autoDownload: [0],
        next: "//span[contains(text(),'下一篇')]/a[contains(@href,'html')]",
        prev: "//span[contains(text(),'上一篇')]/a[contains(@href,'html')]",
        customTitle: ".item_title>h1",
        hide: "img[alt]~br",
        category: "nsfw1"
    }, {
        name: "卡卡美女网",
        url: {
            h: "kaka234",
            p: /^\/HTM\/\w+\/(\w+\/)?\d+\/\d+\/\d+\.html$/
        },
        init: () => {
            let ele = fn.ge(".PsBox");
            if (ele) {
                let te = ele.parentNode;
                insertBefore(te, ele);
            }
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".dede_pages li>a,.article_page li>a").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".content img,.ArticleImageBox img", max, 9);
        },
        button: [4],
        insertImg: ["//div[@class='content'] | //div[div[@class='ArticleImageBox']]", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//li[contains(text(),'上一篇')]/a");
            return next ? next.href : null;
        },
        prev: 1,
        customTitle: ".Title>h1,.PsBox",
        hide: ".m_adv",
        category: "nsfw1"
    }, {
        name: "高清图片吧",
        host: ["www.pic88.cc"],
        reg: /^https?:\/\/www\.pic88\.cc\/\w+\/\d+\/\d+\.html$/,
        imgs: () => {
            let max = fn.gt(".page>*:last-child");
            return fn.getImg(".content img,.ArticleImageBox img", max, 9);
        },
        button: [4],
        insertImg: [".content", 2],
        customTitle: "//div[@class='Title111']/h3[not(a)]",
        hide: ".center:has(>.dibu1),.center:has(>.dibu2)",
        category: "nsfw1"
    }, {
        name: "高清图片吧M",
        host: ["m.pic88.cc"],
        reg: /^https?:\/\/m\.pic88\.cc\/\w+\/\d+\/\d+\.html$/,
        init: () => fn.createImgBox(".PsBox", 2),
        imgs: ".ArticleImageBox>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".ArticleImageBox,.m_adv,.m_kanp"], 2
        ],
        customTitle: ".PsBox",
        hide: ".m_adv,.m_kanp",
        category: "nsfw1"
    }, {
        name: "美女写真网",
        host: ["www.ku138.cc"],
        reg: /^https?:\/\/www\.ku138\.cc\/\w+\/\d+\/\d+\.html$/,
        imgs: () => fn.getImgA(".content img", ".page>a[href]"),
        button: [4],
        insertImg: [".content", 2],
        customTitle: () => fn.ge("meta[name=keywords]").content,
        hide: ".center:has(>.dibu1),.center:has(>.dibu2)",
        category: "nsfw1"
    }, {
        name: "美女目录网 列表模式",
        host: ["www.girldir.com"],
        reg: /^https?:\/\/www\.girldir\.com\/photos\/\w+_list\/$/i,
        imgs: async () => {
            await fn.getNP(".list-page-box>.item", "li.active+li>a", null, ".pagination");
            thumbnailSrcArray = fn.getImgSrcArr(".list-page-box img");
            return thumbnailSrcArray.map(e => e.replace(".medium.", ".big."));
        },
        button: [4],
        insertImg: [".list-page-box", 2],
        customTitle: () => fn.dt({
            d: " - 美女目录网"
        }),
        category: "nsfw1"
    }, {
        name: "美眉村",
        host: ["meimeicun.com"],
        reg: /^https?:\/\/meimeicun\.com\/articles\/\d+$/,
        imgs: ".images-list img",
        autoDownload: [0],
        next: "//div[contains(text(),'上一篇')]/a",
        prev: "//div[contains(text(),'下一篇')]/a",
        customTitle: ".title",
        category: "nsfw1"
    }, {
        name: "ROSI写真",
        host: ["www.rosipic.com", "rosipic.com"],
        reg: /^https?:\/\/(www\.)?rosipic\.com\/rosi\/\d+\.html$/i,
        imgs: () => fn.gau("a.spotlight").map(u => u.replace("https://wsrv.nl/?url=", "").replace(/&blur=\d+/, "")),
        button: [4],
        insertImg: [
            ["#waterfall-container", 2], 2
        ],
        go: 1,
        category: "nsfw1"
    }, {
        name: "ROSI美女写真",
        host: ["www.rosixz.cc", "www.rosixiezhen.cc", "rosixiezhen.cc", "www.rosi985.com", "www.rosi365.cc", "www.rosi360.cc", "www.2meinv.cc", "www.silk-necktie.com"],
        url: {
            h: [
                /^(www\.)?rosixz\.\w+$/,
                /^(www\.)?rosixiezhen\.\w+$/,
                /^(www\.)?rosi\d{3}\.\w+$/,
                /^(www\.)?\dmeinv\.cc$/,
                /^www\.silk-necktie\.com$/
            ],
            p: /^\/\w+\/\w+\.html$/
        },
        exclude: "//span/a[text()='ROSI视频']",
        init: () => {
            let pag = fn.gae(".pagination2");
            if (pag.length > 0) pag[0].remove();
            fn.remove(".content>b,.content>br,.asst");
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt("//a[contains(text(),'共')]").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".article-content img", max, 9);
        },
        button: [4],
        insertImg: [".article-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev>a",
        prev: ".article-nav-next>.a",
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "ROSI小莉最新写真",
        host: ["www.rosi211.cc"],
        reg: /^https?:\/\/(www\.)?rosi\d{3}\.cc\/\d+$/i,
        init: () => {
            let pag = fn.gae(".wp-pagenavi");
            if (pag.length > 0) pag[0].remove();
            let ele = fn.ge(".entry-header");
            if (ele) {
                let te = fn.ge("article.post");
                insertBefore(te, ele);
            }
        },
        imgs: () => fn.getImgA("article img", ".wp-pagenavi a"),
        button: [4],
        insertImg: ["article.post", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".entry-title",
        css: "@media only screen and (max-width:480px){#primary{padding:6px !important}.col-md-12{padding:0px !important}}",
        category: "nsfw1"
    }, {
        name: "新老友图社",
        host: ["m.xtushe.com"],
        reg: /^https?:\/\/m\.xtushe\.com\/photo\/\d+\.html$/i,
        imgs: async () => {
            const error = async (dom) => {
                let ele = fn.ge("#content-photo>img", dom);
                if (!ele) {
                    await alert("遇到驗證");
                    location.reload();
                    return true;
                } else {
                    return false;
                }
            };
            await fn.getNP("#content-photo>img", "li.next>a", error, ".pagebreak");
            return fn.gae("#content-photo>img");
        },
        button: [4],
        insertImg: ["#content-photo", 2],
        insertImgAF: () => fn.remove(".pagebreak"),
        customTitle: "#content-title>h1",
        category: "nsfw1"
    }, {
        name: "闺秀网",
        host: ["www.guixiu.org", "guixiu.org"],
        reg: /^https:\/\/(www\.)?guixiu\.org\/post\/\d+\.html/i,
        imgs: () => fn.getImgA("#lightgallery img", "#ipage a[href*=ipage]"),
        button: [4],
        insertImg: ["#lightgallery", 2],
        customTitle: ".focusbox-title",
        category: "nsfw1"
    }, {
        name: "悄悄的看2019",
        host: ["qqdk2019.net"],
        reg: /^https?:\/\/qqdk2019\.net\/\w+\/\d+$/,
        init: () => fn.createImgBox(".blog-details-text>p:has(>img)", 1),
        imgs: ".blog-details-text>p>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".blog-details-text>p:has(>img)"], 2
        ],
        customTitle: "h2.blog-details-headline",
        category: "nsfw1"
    }, {
        name: "福利图",
        host: ["fulitu.me"],
        reg: /^https?:\/\/fulitu\.me\/pic\/\d+\.html$/i,
        imgs: () => fn.getImg(".content_left img", fn.gt("//a[text()='下页']", 2), 5),
        button: [4],
        insertImg: [".content_left", 2],
        autoDownload: [0],
        next: "//span[contains(text(),'下一篇')]/a",
        prev: "//span[contains(text(),'上一篇')]/a",
        customTitle: ".item_title>h1",
        hide: ".content br",
        category: "nsfw1"
    }, {
        name: "爱图门",
        host: ["aitu.men"],
        reg: /^https?:\/\/aitu\.men\/[^\/]+\/\d+\.html/i,
        imgs: async () => {
            await fn.getNP(".context img", ".pagelist span+a", null, ".pagelist", 0, null);
            return fn.gae(".context img");
        },
        button: [4],
        insertImg: [".context", 1],
        autoDownload: [0],
        next: ".post-previous a",
        prev: ".post-next a",
        customTitle: "#content h1",
        category: "nsfw1"
    }, {
        name: "K55",
        host: ["k55.net"],
        link: "https://k55.net/arttype/2.html",
        reg: /^https?:\/\/k55\.net\/artdetail-\d+\.html/,
        include: ".photo_box",
        imgs: () => fn.gae(".photo_box img").map(e => e.src).sort((a, b) => a.match(/(\d+)\.\w+$/)[1] - b.match(/(\d+)\.\w+$/)[1]),
        button: [4],
        insertImg: [".photo_box", 2],
        autoDownload: [0],
        next: ".item_prev_next>.item_right>a",
        prev: ".item_prev_next>.item_left>a",
        customTitle: () => fn.dt({
            s: ".title-box>.h3-md.mb-1",
            d: /\[\d+P\].+$/i
        }),
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "Hotgirl.biz",
        host: ["hotgirl.biz"],
        reg: /^https?:\/\/hotgirl\.biz\/[^\/]+\/$/i,
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "XLUST.ORG",
        host: ["xlust.org"],
        reg: /^https?:\/\/xlust\.org\/[^\/]+\/$/i,
        imgs: ".rl-gallery-item a",
        button: [4],
        insertImg: [
            [".entry-content", 0, ".rl-gallery-container"], 2
        ],
        customTitle: ".entry-title",
        fancybox: {
            blacklist: 1
        },
        category: "nsfw1"
    }, {
        name: "秀人网",
        host: ["xiurenwang.me"],
        reg: /^https?:\/\/xiurenwang\.me\/photo\.php\?id=\w+/i,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".intro>img");
            return thumbnailSrcArray.map(e => e.replace("_600x0", "").replace(".webp", ".jpg"));
        },
        button: [4],
        insertImg: [".intro", 2],
        customTitle: "h1",
        css: "@media only screen and (max-width:640px){.paragraph .intro img{width:100%!important}}",
        hide: ".article:has(>div>.media),.banner,.banner_ad,.push-top,.push-bottom,.banner-sexgps",
        category: "nsfw1"
    }, {
        name: "秀人网 AD",
        reg: /^https?:\/\/xiurenwang\.me/,
        hide: ".article:has(>div>.media),.banner,.banner_ad,.push-top,.push-bottom,.banner-sexgps",
        category: "ad"
    }, {
        name: "秀人网图集",
        host: ["xiurentu.com", "www.aixiurenmn.com", "www.aixiurenji.com", "www.aixiurentuji.com", "www.aixiurenwang.com"],
        url: {
            e: ".site .logo-wrapper img.logo.tap-logo[alt^='秀人']",
            p: /^\/\d+\.html/
        },
        exclude: "//button[contains(text(),'登录购买')]",
        imgs: () => fn.getImgA("a[data-fancybox],.entry-content img", ".fenye a"),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        observerClick: [".swal2-close", ".ht-n-close-toggle"],
        css: ".navbar .nav-list>.menu-item>a{line-height:20px;margin:0 6px}",
        category: "nsfw1"
    }, {
        name: "秀人网图集",
        url: {
            e: ".site .logo-wrapper img.logo.tap-logo[alt^='秀人']",
        },
        observerClick: [".swal2-close", ".ht-n-close-toggle"],
        css: ".navbar .nav-list>.menu-item>a{line-height:20px;margin:0 6px}",
        category: "ad"
    }, {
        name: "足控资源网",
        host: ["www.zukong8.com", "www.yuzu8.com", "aisituba.com"],
        url: {
            h: "www.yuzu8.com",
            p: "archives"
        },
        exclude: ".content-hide-tips",
        imgs: "a[data-fancybox]",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "超次元",
        host: ["www.ccy.moe"],
        reg: /^https?:\/\/www\.ccy\.moe\/\w+\/\w+\/\d+\/\d+\/\d+\/\d+/,
        init: async () => {
            await fn.waitEle(".entry-content p:has(>a>img)");
            fn.createImgBox(".entry-content p:has(>a>img)", 1)
        },
        imgs: () => {
            let pages = fn.ge(".post-links");
            if (pages) {
                return fn.getImgA(".entry-content img", ".post-links a");
            } else {
                return fn.gae(".entry-content img");
            }
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".entry-content p:has(>a>img),.post-links"], 2
        ],
        customTitle: ".entry-header h1",
        category: "nsfw1"
    }, {
        name: "资源库图站",
        host: ["www.zyktu.top"],
        url: {
            e: "a[title^=资源库图站]>img[alt^=资源库图站]",
            p: /^\/index\.php\/archives\/\d+\/$/
        },
        imgs: "span[data-fancybox]>img",
        button: [4],
        insertImg: [
            ["span[data-fancybox]", 1, "span[data-fancybox],span[data-fancybox]~br"], 2
        ],
        autoDownload: [0],
        next: "//a[text()='下一篇']",
        prev: "//a[text()='上一篇']",
        customTitle: ".joe_detail__title",
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "nsfw1"
    }, {
        name: "牛叉资源网",
        url: {
            h: "niuc.net",
            p: /^\/\d+\.html$/,
            e: "//i[@class='czs-folder-l']/following-sibling::a[1][text()='美女写真' or text()='Cosplay' or text()='JAV.PHOTO']"
        },
        imgs: ".content-warp img[title][alt]",
        button: [4],
        insertImg: [".content-warp", 2],
        customTitle: ".post-title",
        category: "nsfw2"
    }, {
        name: "8E资源站",
        host: ["8ezy.com"],
        reg: /^https?:\/\/8ezy\.com\/[^\/]+\/$/,
        include: ".entry-content",
        init: () => {
            fn.clearAllTimer();
            let e = fn.ge(".yarpp-related-website");
            let x = fn.ge(".entry-tags");
            if (e && x) {
                insertBefore(x, e);
            }
        },
        imgs: async () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            return fn.getImgSrcArr(".entry-content img").filter(i => !/jzfi4j-0\.gif|k0j1um-0\.gif/.test(i));
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            s: ".entry-header>h1",
            d: [
                "【在线观看】-",
                /\d+p(\d+v)?$|\(\d+[\w\s\.\+-]+\)|\[\d+[\w\s\.\+-]+\]|“\d+ photos.*/i
            ]
        }),
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "8E资源站 自動翻頁",
        host: ["8ezy.com"],
        url: {
            h: "8ezy.com",
            e: [".post-list-item", ".post-nav[data-max]"]
        },
        init: async () => {
            await fn.waitEle("button.selected,a.button.selected[href^=http]");
            currentPageNum = Number(fn.gt("button.selected,a.button.selected[href^=http]"));
        },
        autoPager: {
            ele: ".archive-row",
            observer: ".archive-row .post-list-item",
            next: () => {
                let lastNum = fn.ge(".post-nav[data-max]").dataset.max;
                lastNum = Number(lastNum);
                if (currentPageNum < lastNum) {
                    let url = document.location.pathname.replace(/page\/\d+\/?/, "");
                    if (document.location.search !== "") {
                        return url + "page/" + (currentPageNum += 1) + "/" + document.location.search;
                    }
                    return url + "page/" + (currentPageNum += 1);
                } else {
                    return null;
                }
            },
            bF: (dom) => {
                [...dom.querySelectorAll(".post-list-item .picture")].forEach(e => {
                    fn.ge("source", e)?.remove();
                    let img = fn.ge("img", e);
                    img.src = img.dataset.src;
                    img.classList.add("loaded");
                });
            },
            pageNum: () => currentPageNum
        },
        openInNewTab: ".post-list-item a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "丝袜室",
        host: ["www.siwashi.xyz"],
        reg: /^https?:\/\/www\.siwashi\.xyz\/\w+\/\d+\.html$/,
        imgs: () => {
            if (fn.ge("//div[contains(text(),'分页阅读')]")) {
                fn.showMsg(displayLanguage.str_05, 0);
                let links = fn.gau("//div[contains(text(),'分页阅读')]/a");
                links = [fn.url, ...links];
                return links.flatMap(url => fn.fetchDoc(url).then(dom => fn.gae(".entry-content img", dom).map(e => e.dataset.srcset ?? e.src)));
            } else {
                return fn.gae(".entry-content img").map(e => e.dataset.srcset ?? e.src);
            }
        },
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "牛牛美图",
        host: ["www.uyn8.cn"],
        reg: /^https?:\/\/www\.uyn8\.cn\/archives\/\d+/i,
        init: "fn.clearAllTimer();",
        imgs: () => {
            fn.showMsg("fn.xhrHEA(check)...", 0);
            let xhrNum = 0;
            let srcs = fn.getImgSrcArr(".entry-content img");
            return srcs.map((src, i, arr) => fn.xhrHEAD(src).then(res => {
                fn.showMsg(`fn.xhrHEAD(${xhrNum+=1}/${arr.length})`, 0);
                return res.finalUrl;
            }));
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "微密猫",
        url: {
            e: ".logo>a[title=微密猫]",
            p: /^\/archives\/\d+/
        },
        imgs: "figure.wp-block-image a[data-fancybox]",
        button: [4],
        insertImg: [
            [".article-content", 0, "figure.wp-block-image,.code-block"], 2
        ],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".article-title",
        go: 1,
        fancybox: {
            v: 3,
            css: false
        },
        hide: ".code-block",
        observerClick: "a.close",
        category: "nsfw1"
    }, {
        name: "优美图录",
        host: ["www.umei.net", "umei.net"],
        reg: /^https?:\/\/(www\.)?umei\.net\/\w+\/\d+\.html$/i,
        imgs: () => fn.getImgO(".image_div img", fn.gt(".item_info span"), 9, null, 200, ".nav-links"),
        button: [4],
        insertImg: [".image_div", 2],
        customTitle: ".item_title>h1",
        css: ".content_left img,.image_div a img{cursor:unset}",
        hide: ".affs,.xg_content>li:nth-child(n+1):nth-child(-n+2)",
        category: "nsfw1"
    }, {
        name: "Xiutaku/Kiutaku",
        url: {
            h: ["xiutaku.com", "kiutaku.com"],
            p: /^\/\d+$/
        },
        init: () => fn.remove(".search-form~*,.blog~*:not([class]),.pagination~*:not([class]):not(hr),.article.content~*:not([class]):not(hr),.bottom-articles~*"),
        imgs: () => fn.getImg(".article-fulltext img", fn.gt(".pagination-list>span:last-child")),
        button: [4],
        insertImg: [".article-fulltext", 2],
        customTitle: () => fn.dt({
            s: ".article-header>h1",
            d: /([\s-]+)?.Mitaku.*/i
        }),
        category: "nsfw1"
    }, {
        name: "XGirl/MissBby.com/Xerocos",
        host: ["xgirl.one", "missbby.com", "xerocos.com"],
        reg: [
            /^https?:\/\/(xgirl\.one|missbby\.com)\/[^\/]+$/,
            /^https?:\/\/xerocos\.com\/view\//
        ],
        include: "//div[strong[contains(text(),'Album Name')]]",
        imgs: () => fn.getImgA(".items-center.min-h-screen img", "a[class*=bg-pink-500][href*='page=']"),
        button: [4],
        insertImg: [".items-center.min-h-screen", 2],
        insertImgAF: () => fn.remove("//div[iframe]|//*[span[text()='Sponsored ads']]"),
        customTitle: () => fn.dt({
            s: "//div[strong[contains(text(),'Album Name')]]",
            d: "Album Name: "
        }),
        css: ".md\:px-16,.xl\:px-20{padding:unset!important}.max-w-3xl{max-width:100%!important}",
        category: "nsfw2"
    }, {
        name: "XGirl/MissBby.com 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/(xgirl\.one|missbby\.com)\//,
        autoPager: {
            mode: 1,
            waitEle: "//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[1][@class='grid grid-cols-1 md:grid-cols-3 gap-y-6 gap-x-4 xl:grid-cols-4']//img",
            ele: "//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[1][@class='grid grid-cols-1 md:grid-cols-3 gap-y-6 gap-x-4 xl:grid-cols-4']",
            pos: ["//div[@class='flex py-4 justify-center md:justify-between mt-4']", 1],
            next: "//a[text()='Next']",
            re: "//div[@class='flex py-4 justify-center md:justify-between mt-4']",
            pageNum: () => nextLink.match(/\d+$/)[0],
            bottom: screen.height * 2
        },
        openInNewTab: ".grid a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "Xerocos 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/xerocos\.com\//,
        autoPager: {
            mode: 1,
            waitEle: "//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[1][@class='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4']//img|//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[@class='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 pb-6']//img",
            ele: "//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[1][@class='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4']|//div[@class='flex py-4 justify-center md:justify-between mt-4']/preceding-sibling::div[@class='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 pb-6']",
            pos: ["//div[@class='flex py-4 justify-center md:justify-between mt-4']", 1],
            next: "//a[text()='Next']",
            re: "//div[@class='flex py-4 justify-center md:justify-between mt-4']",
            pageNum: () => nextLink.match(/\d+$/)[0],
            aF: () => fn.gae(".blur-2xl").forEach(e => e.classList.remove("blur-2xl")),
            bottom: screen.height * 2
        },
        openInNewTab: ".grid a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "私图网/图库库",
        host: ["baoruba.com", "tukuku.cc"],
        reg: /^https?:\/\/(baoruba\.com|tukuku\.cc)\/(bb|t)?\d+\.html$/i,
        imgs: ".entry-content img[decoding]",
        button: [4],
        insertImg: [".entry-content", 2],
        go: 1,
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: () => fn.title(/ - 私图网| - 图库库/),
        hide: "[id].widget_text,.gridmode-post-thumbnail-single,.gridbit-thumbnail-alignwide",
        category: "nsfw1"
    }, {
        name: "Cup2D",
        host: ["www.cup2d.com", "cup2d.com"],
        reg: /^https?:\/\/(www\.)?cup2d\.com\/[^\/]+\/$/i,
        imgs: () => {
            let imgs = fn.gae("img[data-high-res-src]");
            thumbnailSrcArray = imgs.map(e => e.src);
            return imgs;
        },
        button: [4],
        insertImg: ["//div[a[img[@data-high-res-src]]]", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: () => fn.title(" – Cup2D"),
        category: "nsfw1"
    }, {
        name: "COSERMM",
        host: ["cosermm.blog.2nt.com"],
        reg: /^https?:\/\/cosermm\.blog\.2nt\.com\/blog-entry-\d+\.html$/i,
        imgs: "#inner-contents img",
        button: [4],
        insertImg: ["#inner-contents", 2],
        autoDownload: [0],
        next: "a.next-a",
        prev: "a.prev-a",
        customTitle: "#entry-title",
        category: "nsfw1"
    }, {
        name: "COSERMM 自動翻頁",
        reg: /^https?:\/\/cosermm\.blog\.2nt\.com\/(page-\d+\.html)?$/i,
        autoPager: {
            mode: 1,
            waitEle: "#pagination>li",
            ele: "#grid-container",
            observer: "#grid-container>.grid-items",
            next: "li:has(>span#current)+li>a",
            re: "#pagination",
            pageNum: "li:has(>span#current)"
        },
        openInNewTab: ".grid-items a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "美图网",
        host: ["www.meitu8.cc", "meitu8.cc"],
        reg: /^https?:\/\/(www\.)?meitu8\.cc\/\w+\/\d+\/\d+\.html$/i,
        imgs: () => {
            let [max] = fn.gt(".pagelist>b").match(/\d+$/);
            return fn.getImg("#lightgallery img", max, 9);
        },
        button: [4],
        insertImg: ["#lightgallery", 2],
        autoDownload: [0],
        next: ".prev>a",
        prev: ".next>a",
        customTitle: ".focusbox-title",
        category: "nsfw1"
    }, {
        name: "美图社/花瓣美女",
        url: {
            h: [
                /^(www\.)?928r\.com$/,
                /^(www\.)?060k\.com$/,
            ],
            p: /^\/post\/\d+\.html$/i
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu("//a[text()='显示全文']");
            return fn.fetchDoc(url).then(dom => fn.gae("#lightgallery img", dom));
        },
        button: [4],
        insertImg: ["#lightgallery", 2],
        autoDownload: [0],
        next: ".prev>a",
        prev: ".next>a",
        customTitle: ".focusbox-title",
        category: "nsfw1"
    }, {
        name: "找套图/Xiuno BBS",
        url: {
            h: [
                /^(www\.)?zhaotaotu\.cc$/,
                /^(www\.)?kantaotu\.cc$/
            ],
            p: /^\/\??thread-\d+\.htm$/
        },
        imgs: ".message>img:not(:first-of-type)",
        button: [4],
        insertImg: [".message", 2],
        customTitle: ".media-body>h4",
        category: "nsfw1"
    }, {
        name: "尤美图库/M5MM",
        host: ["www.umeitu.com", "www.m5mm.com"],
        reg: [
            /^https?:\/\/(www\.)?umeitu\.com\/img\/\d+\.html$/,
            /^https?:\/\/(www\.)?m5mm\.com\/photo\/\d+\.html$/,
        ],
        imgs: () => fn.getImg(".vipimglist img", fn.gt(".stitle>h1>span").match(/\d+/)[0], 9),
        button: [4],
        insertImg: [".vipimglist", 2],
        customTitle: () => fn.dt({
            d: [
                " - 尤美图库",
                " - M5MM"
            ]
        }),
        css: ".vipimglist img{min-height:unset!important;}",
        hide: "union[id],.sb.list2>li:nth-child(n+2):nth-child(-n+3)",
        category: "nsfw1"
    }, {
        name: "秀套图吧/91性感美女",
        url: {
            h: ["www.taotu8.cc", "www.913wen.com", "913wen.com"],
            p: ["/mm/", "/p/"]
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gu(".page_navi a:last-child").split("_")[1].match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".sg_img img", max, 9);
        },
        button: [4],
        insertImg: [".sg_img", 2],
        customTitle: "h1",
        css: ".sg_img img{min-height:unset!important}",
        hide: "#divpsg,.tujia",
        category: "nsfw1"
    }, {
        name: "Xiuren 秀人网",
        url: {
            h: "www.xiuren.org"
        },
        imgs: "a[rel='gallery']:not([href*='html']",
        button: [4],
        insertImg: [
            [".post p>a:not([title])", 2, ".post p>a[title],.post p>span"], 2
        ],
        customTitle: "#title>h1",
        css: "#post .post img{max-width:100% !important}",
        category: "nsfw2"
    }, {
        name: "微圖坊",
        url: () => fn.checkUrl({
            h: ["www.v2ph.com", "www.v2ph.net", "www.v2ph.ru", "www.v2ph.ovh"],
            p: "/album/",
            e: ".photos-list"
        }) && !fn.ls.includes("page="),
        imgs: async () => {
            let [picTotalNum] = fn.gt("dd:last-child").match(/\d+/);
            let pagePicNum = fn.gae(".album-photo img[alt]").length;
            let max = Math.ceil(picTotalNum / pagePicNum);
            let links = fn.arr(max, (v, i) => siteUrl.replace(/\?hl=.+|\?page=\d+/, "") + `?page=${(i + 1)}`);
            let srcArr = [];
            let status = 200;
            let vip = false;
            let fetchNum = 0;
            fn.showMsg(displayLanguage.str_01, 0);
            for (let [page, link] of links.entries()) {
                await fetch(link).then(res => {
                    if (res.status == 403) status = 403;
                    fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${links.length}`, 0);
                    return res.arrayBuffer();
                }).then(buffer => {
                    const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                    const htmlText = decoder.decode(buffer);
                    const dom = fn.doc(htmlText);
                    debug(`\n${link}\n`, dom);
                    let vipEle = fn.ge(".lead", dom);
                    if (vipEle) vip = true;
                    let imgs = fn.gae(".album-photo img[alt]", dom);
                    imgs.length == 0 ? debug(`\n${link}\n沒有任何圖片`) : debug(`\n${link}\n此頁圖片`, imgs);
                    let tE = fn.gae("div.album-photo").at(-1);
                    imgs.forEach(img => {
                        img.dataset.src ? srcArr.push(img.dataset.src) : srcArr.push(img.src);
                        if (page != 0) insertAfter(tE, img.parentNode.cloneNode(true));
                    });
                    if (page != 0 && !vipEle && fn.ge(".pagination", dom)) fn.ge(".pagination").outerHTML = fn.ge(".pagination", dom).outerHTML;
                });
                if (status == 403) {
                    setTimeout(() => {
                        fn.showMsg("403請先登錄網站!", 0);
                    }, 1200);
                    return srcArr;
                }
                if (vip) {
                    setTimeout(() => {
                        fn.showMsg("VIP限定專輯圖片!", 5000);
                    }, 1200);
                    return srcArr;
                }
                await delay(600);
            }
            if (picTotalNum != srcArr.length && !vip) {
                setTimeout(() => {
                    fn.hideMsg();
                    fn.showMsg("圖片有缺,請看主控台訊息", 5000);
                }, 1300)
            }
            return srcArr;
        },
        button: [4],
        insertImg: [".photos-list", 2],
        customTitle: "h1",
        css: ".albums-list img,.photos-list img{opacity:1!important}",
        category: "nsfw2"
    }, {
        name: "柠檬皮",
        host: ["www.emonl.com"],
        reg: /^https?:\/\/www\.emonl\.com\/\d+\.html$/i,
        exclude: [
            ".read-point-box",
            "//div[@class='single-content']/p[not(.//img)] | //div[@class='single-content']/fieldset"
        ],
        imgs: () => {
            if (fn.ge(".page-links")) {
                return fn.getImg(".single-content img", (fn.gt(".page-links>a:last-child", 2) || 1), 7);
            } else {
                return fn.gae(".single-content img");
            }
        },
        button: [4],
        insertImg: [".single-content", 2],
        customTitle: "h1.entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "柠檬皮",
        host: ["www.emonl.com"],
        reg: /^https?:\/\/www\.emonl\.com\/\d+\.html$/i,
        include: "//div[@class='single-content']/p[not(.//img)] | //div[@class='single-content']/fieldset",
        exclude: [
            ".read-point-box",
            ".page-links"
        ],
        imgs: ".single-content img",
        capture: () => fn.gae(".single-content img"),
        setFancybox: true,
        button: [4],
        insertImg: [".single-content", 0],
        customTitle: "h1.entry-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "51sex",
        host: ["51sex.vip"],
        reg: /^https?:\/\/51sex\.vip\/pic\/\d+/i,
        init: () => fn.addUrlHtml(_this.next(), ".headling_main", 1, "下一篇"),
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".headling_swiper_num_small").match(/\d+/);
            } catch {
                max = 1;
            }
            let links = fn.arr(max, (v, i) => siteUrl + "/" + (i + 1));
            return fn.getImgA("#bigimg", links);
        },
        button: [4, "24%"],
        insertImg: [".headling_main", 2],
        next: () => {
            let [num] = siteUrl.match(/\d+$/);
            return siteUrl.replace(/\d+$/, "") + (Number(num) - 1);
        },
        customTitle: ".headling_word_main_box_title",
        css: ".headling_main{height:auto}",
        category: "nsfw1"
    }, {
        name: "51sex分類自動翻頁",
        reg: /^https?:\/\/51sex\.vip\/category\/\d+/i,
        init: () => {
            fn.lp.split("/").length == 3 ? currentPageNum = 1 : currentPageNum = Number(fn.lp.split("/").at(-1));
        },
        autoPager: {
            ele: ".headling_main_a",
            observer: ".headling_main_a",
            next: () => siteUrl.match(/https?:\/\/51sex\.vip\/category\/\d+/)[0] + "/" + (currentPageNum += 1),
            stop: (dom) => {
                let currentEleURLs = fn.gau(".headling_main_a");
                if (currentEleURLs.length < 24) {
                    return true;
                } else {
                    if (currentEleURLs.length > 24) currentEleURLs = currentEleURLs.slice(-24);
                    let nextEleURLs = fn.gau(".headling_main_a", dom);
                    for (let url of currentEleURLs) {
                        if (nextEleURLs.includes(url)) return true;
                    }
                }
                return false;
            },
            pageNum: () => currentPageNum
        },
        openInNewTab: "a.headling_main_a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "美图乐",
        host: ["www.meitule.net", "www.meitule.com", "www.meitulu.cc"],
        reg: /^https?:\/\/(www\.)?(meitule|meitulu)\.\w+\/photo\/\d+\.html$/i,
        imgs: () => {
            let max;
            try {
                [max] = fn.gu(".page>li:last-child>a").split("_")[1].match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImgO(".content img", max, 9);
        },
        button: [4],
        insertImg: [".content", 2],
        customTitle: "h1.h5",
        hide: "#dtag>center,#divpsg,.tujia,.list-album>li:nth-child(n+1):nth-child(-n+2)",
        category: "nsfw1"
    }, {
        name: "Elysium",
        url: {
            h: "www.elysium.pro",
            p: "/albums/",
            e: "a[data-thumbnail]:not([data-video])"
        },
        init: () => fn.createImgBox("div[data-lg-thumb=data-thumbnail]", 2),
        imgs: async () => {
            let pages = fn.ge("li.page-item.active+li>a:not([aria-label=Next])");
            if (pages) {
                let links = fn.gau(".pagination>.page-item:not(.disabled)>a:not([aria-label=Next])");
                await fn.getEle(links, "div[data-lg-thumb=data-thumbnail]>div", "div[data-lg-thumb=data-thumbnail]", "nav:has(>.pagination)");
            }
            thumbnailSrcArray = fn.gae("a[data-thumbnail]:not([data-video])").map(e => e.dataset.thumbnail);
            return fn.gae("a[data-thumbnail]:not([data-video])");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        go: 1,
        customTitle: () => fn.gt(".text-muted+a") + " - " + fn.gt(".btn-toolbar>h4"),
        category: "nsfw1"
    }, {
        name: "美桌",
        host: ["www.win4000.com"],
        link: "http://www.win4000.com/meitu.html",
        reg: /^https?:\/\/www\.win4000\.com\/meinv\d+\.html$/,
        imgs: () => fn.getImgA(".pic-large", "#scroll>li:not(.current)>a", 200),
        button: [4],
        insertImg: ["#pic-meinv,.pic-meinv", 2],
        autoDownload: [0],
        next: ".group-next>a",
        prev: ".group-prev>a",
        customTitle: ".ptitle>h1",
        category: "nsfw1"
    }, {
        name: "MM1311",
        host: ["www.mm1311.net", "m.mm1311.net"],
        reg: /^https?:\/\/(www|m)\.mm1311\.net\/\w+\/\d+\.html$/,
        imgs: () => {
            let max;
            fn.ge(".page-ch") ? [max] = fn.gt(".page-ch").match(/\d+/) : [, max] = fn.gt(".fenye>.rw").match(/\d+\/(\d+)/);
            return fn.getImg(".content-pic img,.post-content img", max, 9);
        },
        button: [4],
        insertImg: [".content-pic,.post-content", 2],
        autoDownload: [0],
        next: ".updown_r",
        prev: ".updown_l",
        customTitle: ".content>h5,.mm-title",
        hide: "union",
        category: "nsfw1"
    }, {
        name: "656G精品套图/秀人妹子图",
        url: {
            h: ["www.656g.com", "m.656g.com", "www.mmww.cc"],
            p: "/tid/"
        },
        imgs: () => {
            let [max] = fn.gt(".i1").match(/\d+/);
            return fn.getImgO(".imgg img", max, 9);
        },
        button: [4],
        insertImg: [".imgg", 2],
        customTitle: ".c-tt>h1",
        category: "nsfw1"
    }, {
        name: "依依图片网",
        host: ["www.eemm.cc"],
        reg: /^https?:\/\/www\.eemm\.cc\/pic\/\d+\.html$/,
        imgs: async () => {
            await fn.getNP("#content img", "a.on+a:not(.next)", null, ".page", 0, null, 0, 0);
            return fn.gae("#content img");
        },
        button: [4],
        insertImg: ["#content", 1],
        customTitle: ".article>h1",
        css: ".article .content img{max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "依依图片网M",
        host: ["m.eemm.cc"],
        reg: /^https?:\/\/m\.eemm\.cc\/pic\/\d+\.html$/,
        imgs: () => {
            let [, max] = fn.gt(".contentpage").match(/\d+\/(\d+)/);
            return fn.getImgO(".content img", max, 9, null, 200, ".contentpage>span:nth-child(2)");
        },
        button: [4],
        insertImg: [".content", 1],
        customTitle: ".content>h1",
        hide: ".topad,.mdiv",
        category: "nsfw1"
    }, {
        name: "青年美圖",
        host: ["jrants.com"],
        reg: [
            /^https?:\/\/(\w+\.)?jrants\.com\/\d+\.html$/,
            /^https:\/\/\w+\.jrants\.com\/[^\/]+\/$/
        ],
        imgs: () => fn.ge(".page-links") ? fn.getImg(".entry-content img", fn.gt(".page-links>a:last-child"), 7) : fn.gae(".entry-content img"),
        button: [4],
        insertImg: [".entry-content", 1],
        autoDownload: [0],
        next: "span.prev>a",
        prev: "span.next>a",
        customTitle: ".entry-title",
        hide: ".code-block",
        category: "nsfw2"
    }, {
        name: "CosBlay/風流雜誌/虹圖",
        host: ["cosblay.com", "trendszine.com", "www.hongimg.com"],
        reg: [
            /^https?:\/\/(cosblay\.com|trendszine\.com|www\.tiplogo\.com)\/\d+\.html/i,
            /^https?:\/\/[a-z]{2}\.cosblay\.com\/\d+\/[^\.]+\.html$/,
            /^https?:\/\/[a-z]{2,3}\.hongimg.com\/\d+\/[^\.]+\.html$/
        ],
        imgs: () => fn.getImg(".entry-content img", fn.gt(".pgntn-page-pagination-block>*:last-child", 2) || 1, 7),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: "span.prev>a",
        prev: "span.next>a",
        customTitle: ".entry-title",
        css: ".code-block{display:none!important;}@media (max-width:768px){.separate-containers .inside-article,.separate-containers .comments-area,.separate-containers .page-header,.separate-containers .paging-navigation,.one-container .site-content,.inside-page-header{padding:2px}.entry-content:not(:first-child),.entry-summary:not(:first-child),.page-content:not(:first-child){margin-top:2px}}",
        category: "nsfw2"
    }, {
        name: "MM5MM5美女图片",
        host: ["www.mm5mm5.com"],
        reg: /^https?:\/\/www\.mm5mm5\.com\/mm\/\d+/,
        imgs: () => _unsafeWindow.picinfo[0].split(","),
        button: [4],
        insertImg: ["#content", 2],
        customTitle: ".article>h2",
        css: ".article .content img{max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "MM5MM5美女图片M",
        host: ["m.mm5mm5.com"],
        reg: /^https?:\/\/m\.mm5mm5\.com\/mm\/\d+/,
        imgs: () => {
            let [, max] = fn.gt(".contentpage>span>i").match(/\/(\d+)/);
            let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl + "/" + (i + 1));
            return fn.getImgA("div>a>img", links, 2);
        },
        button: [4],
        insertImg: ["//div[a[img]]", 2],
        customTitle: ".content>h1",
        hide: "union[id],.pag-ts,.contentpage",
        category: "nsfw1"
    }, {
        name: "888美女网",
        host: ["www.888meinv.com"],
        reg: /^https?:\/\/www\.888meinv\.com\/\w+\/\d+$/,
        include: ".suoyou",
        imgs: () => {
            let [, max] = fn.gt(".suoyou").match(/\/(\d+)/);
            let links = fn.arr(max, (v, i) => siteUrl + "/" + (i + 1));
            return fn.getImgA(".pannel img", links);
        },
        button: [4],
        insertImg: [".pannel", 2],
        autoDownload: [0],
        next: ".pre_pageload>a",
        prev: ".next_pageload>a",
        customTitle: "h1",
        css: ".nr .tupianqu img{margin-top:0px!important}@media only screen and (max-width:480px){.nr .tupianqu,.nr .tupianqu .pannel{padding:0px!important}}union{display:none!important;}",
        category: "nsfw1"
    }, {
        name: "淑女爱",
        host: ["www.shunvi.com", "www.shunvai.com"],
        reg: /^https?:\/\/www\.shunva?i\.com\/\w+\/\d+\.html$/,
        include: "#allnum",
        imgs: () => {
            let max = fn.gt("#allnum");
            let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl.replace(".html", "") + "_" + (i + 1) + ".html");
            return fn.getImgA(".picsbox img", links, 2);
        },
        button: [4],
        insertImg: [".picsbox>center", 2],
        customTitle: ".picmainer>h1",
        hide: ".picpege",
        category: "nsfw1"
    }, {
        name: "淑女爱M",
        host: ["m.shunvi.com", "m.shunvai.com"],
        reg: /^https?:\/\/m\.shunva?i\.com\/photo\/\d+\.html$/,
        include: "#thenum",
        imgs: () => {
            let [max] = fn.gt("//span[b[@id='thenum']]").match(/\d+$/);
            let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl.replace(".html", "") + "_" + (i + 1) + ".html");
            return fn.getImgA(".swiper-slide img", links, 200);
        },
        button: [4],
        insertImg: ["#slider", 0],
        customTitle: () => fn.dt({
            s: ".infoline",
            d: /\d+\s\/\s\d+\n/
        }),
        category: "nsfw1"
    }, {
        name: "TWOIMG",
        link: "https://www.twoimg.com/people",
        url: {
            h: "www.twoimg.com",
            p: /^\/\d+\.html$/
        },
        imgs: ".gallery a",
        thums: ".gallery img",
        button: [4],
        insertImg: [
            [".article-content", 0, ".gallery"], 2
        ],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "mn52图库",
        host: ["www.mn52.com", "wap.mn52.com"],
        link: "https://www.mn52.com/xingganmeinv/",
        reg: /^https?:\/\/(www|wap)\.mn52\.com\/\w+\/\d+\.html$/,
        imgs: "#originalpic img,.w100 img,#piclist img",
        button: [4],
        insertImg: ["#originalpic,.w100", 2],
        autoDownload: [0],
        next: "//a[span[text()='上一个图集']]|//li[contains(text(),'上一篇')]/a",
        prev: "//a[span[text()='下一个图集']]|//li[contains(text(),'下一篇')]/a",
        customTitle: ".title>h1,.general-title>h4",
        css: ".general-title{padding:unset!important}",
        category: "nsfw1"
    }, {
        name: "三千图片网",
        host: ["www.win3000.com"],
        link: "https://www.win3000.com/tags/xingganmeinv/",
        reg: /^https?:\/\/www\.win3000\.com\/\w+\/\d+\.html$/,
        imgs: () => {
            let [max] = fn.gt(".title>span").match(/\d+$/);
            let links = fn.arr(max, (v, i) => siteUrl.replace(".html", "") + "_" + (i + 1) + ".html");
            return fn.getImgA(".pic-cont img", links);
        },
        button: [4],
        insertImg: [".pic-cont", 2],
        autoDownload: [0],
        next: "a.other-group.fr",
        prev: "a.other-group.fl",
        customTitle: ".title>h1",
        category: "nsfw1"
    }, {
        name: "三千图片网M",
        host: ["m.win3000.com"],
        link: "https://m.win3000.com/tags/xingganmeinv/",
        reg: /^https?:\/\/m\.win3000\.com\/\w+\/\d+\.html$/,
        imgs: () => {
            let max = fn.gt(".show-page>i");
            let links = fn.arr(max, (v, i) => siteUrl.replace(".html", "") + "_" + (i + 1) + ".html");
            return fn.getImgA(".pic-showbox .imgbox img", links);
        },
        button: [4],
        insertImg: [".pic-showbox", 2],
        autoDownload: [0],
        next: "a.page-next",
        prev: "a.page-prev",
        customTitle: ".pic-infobox h1",
        css: "#app{font-size:14px!important}",
        category: "nsfw1"
    }, {
        name: "3G 壁纸",
        host: ["www.3gbizhi.com", "m.3gbizhi.com"],
        link: "https://www.3gbizhi.com/meinv",
        reg: /^https?:\/\/(www|m|desk)\.3gbizhi\.com\/meinv\/(\w+\/)?\w+\.html$/,
        imgs: () => fn.getImgA("#contpic,#mobile_c_img>img", ".swiper-slide:not(:first-child) a"),
        thums: ".swiper-slide>a>img",
        button: [4],
        insertImg: ["#showimg", 1],
        endColor: "white",
        autoDownload: [0],
        next: "a.next[href$=html]",
        prev: "a.pver[href$=html]",
        customTitle: "h2.title,.titlew>h2",
        hide: ".showcontw #showimg{height:auto!important}[class^=ad_id]",
        category: "nsfw1"
    }, {
        name: "亿图全景图库",
        host: ["www.yeitu.com", "m.yeitu.com"],
        link: "https://www.yeitu.com/meinv/",
        reg: /^https?:\/\/(www|m)\.yeitu\.com\/\w+\/\w+\/\w+\.html$/,
        init: () => {
            let a = fn.ge(".article-body>a,.gallery-item>a");
            if (a) a.outerHTML = a.innerHTML;
        },
        imgs: () => {
            let [, max] = fn.gt(".imageset-sum,span.num").match(/\/\s?(\d+)/);
            let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl.replace(".html", "") + "_" + (i + 1) + ".html");
            return fn.getImgA(".img_box img[alt],.gallery-item img[alt],.article-show img", links, 2);
        },
        button: [4],
        insertImg: [".img_box,.gallery-item,.article-show", 2],
        customTitle: "#title>h1,h1.article-title,.article-info>h1",
        hide: ".appbox,.uk-page~section,.yt-pages+.mssp",
        category: "nsfw1"
    }, {
        name: "优美图库",
        host: ["www.umei.cc"],
        link: "https://www.umei.cc/meinvtupian/",
        reg: /^https?:\/\/www\.umei\.cc\/meinvtupian\/\w+\/\d+\.htm$/i,
        imgs: () => {
            let url = fn.gu(".pages li:last-child>a");
            let [, max] = url.match(/_(\d+).htm/);
            return fn.getImg(".big-pic img", max, 17);
        },
        button: [4],
        insertImg: [".big-pic", 1],
        autoDownload: [0],
        next: ".preandnext:not(.connext)>a",
        prev: ".preandnext.connext>a[href$=htm]",
        customTitle: "#photos>h1",
        css: ".photo img {max-width:100% !important}",
        category: "nsfw1"
    }, {
        name: "优美图库M",
        host: ["wap.umei.cc"],
        reg: /^https?:\/\/wap\.umei\.cc\/meinvtupian\/\w+\/\d+\.htm$/,
        include: "//a[text()='尾页']",
        imgs: () => {
            let [, max] = fn.gu("//a[text()='尾页']").match(/_(\d+).htm/);
            return fn.getImg("#maincont img", max, 17);
        },
        button: [4],
        insertImg: ["#maincont", 1],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("a.f-r.l3");
            return next ? next.href : null;
        },
        prev: 1,
        customTitle: ".title>h1",
        hide: "#maincont>div:not(#FullPictureLoadImgBox),dl:nth-child(n+1):nth-child(-n+2)",
        category: "nsfw1"
    }, {
        name: "MEITU131",
        host: ["www.meitu131.com", "m.meitu131.com"],
        link: "https://www.meitu131.com/nvshen/,https://www.meitu131.com/jigou/",
        reg: /^https?:\/\/(www|m)\.meitu131\.(com|net)\/(\w+\/)?meinv\/\d+\//,
        imgs: () => {
            let [, max] = fn.gt("a[title],.uk-page>span").match(/\/(\d+)/);
            return fn.getImgO(".work-content img,.uk-article-bd img", max, 15);
        },
        button: [4],
        insertImg: [".work-content>p,.uk-article-bd", 1],
        customTitle: ".contitle-box>h1,h1.uk-article-title",
        css: ".work-content img{max-width:100%!important}",
        hide: ".appbox,.uk-page~section",
        category: "nsfw1"
    }, {
        name: "爱套图",
        url: {
            h: ["www.aitaotu.cc", "aitaotu.cc", "www.2taotu.cc", "2taotu.cc"],
            p: "/photo/"
        },
        init: () => fn.createImgBox(".uk-inline", 2),
        imgs: () => {
            let [, max] = fn.gu("//a[text()='尾页']").match(/_(\d+).htm/);
            return fn.getImg(".uk-article img", max, 9);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "figure.uk-inline"], 2
        ],
        next: ".m-prevnext a",
        customTitle: ".uk-article-title",
        category: "nsfw1"
    }, {
        name: "和邪社",
        host: ["www.hexieshe.cn", "hexieshe.cn"],
        reg: /^https?:\/\/(www\.)?hexieshe\.cn\/\d+\/$/i,
        init: () => fn.getNP("#content-innerText>p", "span.current+a", null, ".post-links"),
        imgs: "#content-innerText img",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: "为您朗读"
        }),
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "天极图片",
        host: ["pic.yesky.com"],
        reg: /^https?:\/\/pic\.yesky\.com\/\d+\/\d+\.shtml$/i,
        init: () => {
            fn.ge(".bigPic").outerHTML = '<div class="imgBox"></div>';
        },
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".previewPic img");
            return thumbnailSrcArray.map(e => e.replace(/d-|\/180x320/g, ""));
        },
        button: [4],
        insertImg: [".imgBox", 2],
        customTitle: "h1",
        css: ".atlasSwiper .floatR,.atlasSwiper .floatR .previewPic{width:unset!important}",
        category: "nsfw1"
    }, {
        name: "天极图片M",
        host: ["wap.yesky.com"],
        reg: /^https?:\/\/wap\.yesky\.com\/pic\/\d+\/\d+\.shtml$/i,
        init: () => {
            globalImgArray = fn.gae("[data-imgid] img");
            fn.ge(".swiper-container").outerHTML = '<div class="imgBox"></div>';
        },
        imgs: () => globalImgArray,
        button: [4],
        insertImg: [".imgBox", 2],
        customTitle: ".atlas_introduce h1",
        hide: ".swiper-sum,[class^=ad]",
        category: "nsfw1"
    }, {
        name: "爱美女",
        host: ["www.92meinv.com"],
        reg: /^https?:\/\/www\.92meinv\.com\/article.+\.html$/,
        imgs: () => {
            let [, max] = fn.gt(".des>h1,.post_title_topimg").match(/\/\s?(\d+)/);
            let links = fn.arr(max, (v, i) => siteUrl.replace(/\.html$/, "") + "-" + (i + 1) + ".html");
            return fn.getImgA(".pp.hh img[alt],#image_div img", links, 200);
        },
        button: [4],
        insertImg: [".pp.hh,.content", 1],
        autoDownload: [0],
        next: "//a[@class='active' and contains(text(),'下一篇')] | //a[@class='active' and contains(text(),'下一组')]",
        prev: "//a[@class='active' and contains(text(),'上一篇')] | //a[@class='active' and contains(text(),'上一组')]",
        css: ".pp img{max-width:100%!important}",
        customTitle: () => fn.title("_", 1),
        category: "nsfw1"
    }, {
        name: "爱美女M",
        host: ["m.92meinv.com"],
        reg: /^https?:\/\/m\.92meinv\.com\/article-\d+\.html$/,
        imgs: () => {
            let max = fn.gt(".article-page>*:last-child", 2);
            let links = fn.arr(max, (v, i) => siteUrl.replace(/\.html$/, "") + "-" + (i + 1) + ".html");
            return fn.getImgA(".arcmain img,#image_div img", links, 200);
        },
        button: [4],
        insertImg: [".clearfix.arcmain,.content", 1],
        autoDownload: [0],
        next: "a.f-r.l3",
        prev: "a.f-l.l2",
        hide: "body>a",
        customTitle: () => fn.title("_", 1),
        category: "nsfw1"
    }, {
        name: "美女图册",
        host: ["www.mntuce.top", "www.mntuce.com"],
        reg: /^https?:\/\/www\.mntuce\.com\/\d+\/\.html$/,
        init: () => {
            _unsafeWindow.onload = null;
            _unsafeWindow.onresize = null;
            if ("showWarning" in _unsafeWindow) {
                _unsafeWindow.showWarning = null;
            }
            if ("detectDevTools" in _unsafeWindow) {
                _unsafeWindow.detectDevTools = null;
            }
            fn.clearAllTimer();
        },
        imgs: () => fn.getImgA(".article-content img", ".post-nav-links a"),
        button: [4],
        insertImg: [".article-content", 2],
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "美女图册",
        url: {
            h: "www.mntuce.com"
        },
        init: () => {
            _unsafeWindow.onload = null;
            _unsafeWindow.onresize = null;
            if ("showWarning" in _unsafeWindow) {
                _unsafeWindow.showWarning = null;
            }
            if ("detectDevTools" in _unsafeWindow) {
                _unsafeWindow.detectDevTools = null;
            }
            fn.clearAllTimer();
        },
        category: "ad"
    }, {
        name: "扮之狐狸",
        host: "www.costhisfox.com",
        reg: [
            /^https?:\/\/www\.costhisfox\.com\/\d+\/$/i,
            /^https?:\/\/www\.costhisfox\.com\/\d+\.html$/,
            /^https?:\/\/www\.costhisfox\.com\/\w+\/\d+\.html$/
        ],
        include: "//ul[@class='breadcrumb']//a[text()='cos福利美图']|//ul[@class='breadcrumb']//a[text()='写真系列']",
        imgs: ".wp-posts-content img[data-src]",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: "h1.article-title",
        fancybox: {
            blacklist: 1
        },
        css: "div[data-nav=posts][style]{max-height:unset!important}",
        category: "nsfw1"
    }, {
        name: "男人之家",
        host: ["nanrenhome.cc", "nanrenhome.com"],
        reg: /^https?:\/\/nanrenhome\.(cc|com)\/\d+\.html$/,
        include: "//a[@rel='category tag'][text()='福利美图']",
        imgs: () => {
            let pag = fn.ge(".article-paging a[href]");
            return pag ? fn.getImgA(".article-content img", ".article-paging a[href]") : fn.gae(".article-content img");
        },
        button: [4],
        insertImg: [
            ["//article/p[img]", 2, "//article/p[img] | //div[@class='article-paging']"], 2
        ],
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "网红跟我俩",
        host: "www.2wh.net",
        reg: /^https?:\/\/www\.2wh\.net\/\d+\.html$/,
        include: "//div[@class='breadcrumbs']/a[2][text()='美女写真机构']",
        imgs: () => {
            let pag = fn.ge(".article-paging a[href]");
            return pag ? fn.getImgA(".article-content img", ".article-paging a[href]") : fn.gae(".article-content img");
        },
        button: [4],
        insertImg: [".article-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: () => fn.dt({
            s: ".article-title",
            d: "无删减私房写真流出"
        }),
        category: "nsfw1"
    }, {
        name: "网红跟我俩",
        reg: /^https?:\/\/www\.2wh\.net\/\d+\.html$/,
        imgs: ".article-content img",
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: () => fn.dt({
            s: ".article-title",
            d: "无删减私房写真流出"
        }),
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "RedBust",
        host: "redbust.com",
        reg: /^https?:\/\/redbust\.com\/[^\/]+\/$/,
        include: ".entry-inner img",
        imgs: () => fn.getImgSrcset(".entry-inner img"),
        thums: ".entry-inner img",
        button: [4],
        insertImg: [".entry-inner", 2],
        autoDownload: [0],
        next: ".previous>a",
        prev: ".next>a",
        customTitle: "h1.post-title",
        category: "nsfw2"
    }, {
        name: "PixiBB 新分頁開啟連結",
        host: ["www.pixibb.com"],
        reg: [
            /^https?:\/\/www\.pixibb\.com\/$/,
            /^https?:\/\/www\.pixibb\.com\/\?list=/
        ],
        openInNewTab: ".list-item-image a",
        category: "none"
    }, {
        name: "PixiBB",
        host: ["www.pixibb.com"],
        link: "https://www.pixibb.com/explore",
        reg: /^https?:\/\/www\.pixibb\.com\/album\//,
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a");
            try {
                thumbnailSrcArray = fn.gae(".list-item-image img").map(e => e.src.replace(/(-\d+)-1(\.md\.\w+)$/i, "$1$2")).sort((a, b) => a.match(/-(\d+)\.md\./)[1] - b.match(/-(\d+)\.md\./)[1]);
            } catch {
                thumbnailSrcArray = fn.gae(".list-item-image img").map(e => e.src).sort();
            }
            return thumbnailSrcArray.map(e => e.replace(".md.", "."));
        },
        button: [4],
        insertImg: ["#list-most-recent", 2],
        customTitle: () => fn.title(" - PixiBB", 1),
        category: "nsfw1"
    }, {
        name: "PixiBB",
        host: ["new.pixibb.com"],
        reg: /^https?:\/\/new\.pixibb\.com\/[\w-]+\/$/,
        imgs: () => fn.getImgA(".entry-content img", ".page-links a"),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".left-post a",
        prev: ".right-post a",
        customTitle: () => fn.dt({
            s: ".post h2",
            d: [
                /Sexy Cosplay.*$/,
                /Maid Raiden Cosplay.*$/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "PutMega",
        host: ["www.putmega.com"],
        link: "https://www.putmega.com/explore/recent/?list=albums&sort=date_desc&page=1",
        reg: /^https?:\/\/(www\.)?putmega\.com\/album\//,
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a[href]");
            thumbnailSrcArray = fn.getImgSrcArr(".list-item-image img");
            return thumbnailSrcArray.map(e => e.replace(".md.", "."));
        },
        button: [4],
        insertImg: ["#list-most-recent", 3],
        customTitle: () => fn.title(" - PutMega"),
        category: "nsfw1"
    }, {
        name: "PutMega 分類自動翻頁",
        reg: /^https?:\/\/(www\.)?putmega\.com\/explore\//,
        autoPager: {
            ele: "#list-recent-albums>.pad-content-listing,#list-recent-images>.pad-content-listing",
            observer: "#list-recent-albums>.pad-content-listing>div,#list-recent-images>.pad-content-listing>div",
            next: ".pagination-next>a[href]",
            re: ".content-listing-pagination"
        },
        category: "autoPager"
    }, {
        name: "ImgBB",
        host: ["ibb.co"],
        reg: /^https?:\/\/ibb\.co\/album\//,
        links: [
            "https://shiki17chen.imgbb.com/albums",
            "https://2920215920.imgbb.com/albums",
            "https://ozpin.imgbb.com/albums"
        ],
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a[href]");
            thumbnailSrcArray = fn.getImgSrcArr(".list-item-image img");
            return fn.getImgA("link[rel=image_src]", ".list-item-image a").then(arr => arr.reverse());
        },
        button: [4],
        insertImg: ["#content-listing-tabs", 3],
        customTitle: () => fn.dt({
            d: [
                "— ImgBB",
                /^[\d\s-]+/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "anh.im",
        links: ["https://anh.im/bigradish/albums"],
        url: {
            h: "anh.im",
            p: "/album/",
            e: "#content-listing-tabs"
        },
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a[href]");
            thumbnailSrcArray = fn.getImgSrcArr(".list-item-image img");
            return thumbnailSrcArray.map(e => e.replace(".md.", ".")).reverse();
        },
        button: [4],
        insertImg: ["#content-listing-tabs", 3],
        customTitle: () => fn.dt({
            d: [
                "— anh.im",
                /^[\d\s-]+/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "JPG5",
        host: ["jpg5.su"],
        reg: /^https?:\/\/jpg5\.su\/a\//,
        links: [
            "https://jpg5.su/xelszy/albums",
            "https://jpg5.su/rainbowsmile/albums"
        ],
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a[href]");
            thumbnailSrcArray = fn.getImgSrcArr(".list-item-image img");
            return thumbnailSrcArray.map(e => e.replace(".md.", ".")).reverse();
        },
        button: [4],
        insertImg: ["#content-listing-tabs", 3],
        customTitle: () => fn.dt({
            d: [
                "— JPG5",
                /^[\d\s-]+/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "IMG.Kiwi",
        host: ["img.kiwi"],
        reg: /^https?:\/\/img\.kiwi\/album\//,
        link: "https://img.kiwi/album/whores-on-wheels.cIr6",
        imgs: async () => {
            await fn.getNP("#list-most-recent>.pad-content-listing", ".pagination-next>a[href]");
            thumbnailSrcArray = fn.getImgSrcArr(".list-item-image img");
            return thumbnailSrcArray.map(e => e.replace(".md.", ".")).reverse();
        },
        button: [4],
        insertImg: ["#content-listing-tabs", 3],
        customTitle: () => fn.dt({
            d: [
                " - IMG.Kiwi",
                /^[\d\s-]+/
            ]
        }),
        category: "nsfw2"
    }, {
        name: "Luscious",
        url: {
            h: "luscious.net"
        },
        SPA: () => document.URL.includes("/albums/"),
        observerURL: true,
        imgs: async () => {
            if (!_this.SPA()) return [];
            fn.showMsg(displayLanguage.str_05, 0);
            await fn.waitEle("a[href*='/read/'],.album-heading a");
            const getApiUrl = (id, page) => {
                let searchParams = new URLSearchParams({
                    operationName: "PictureListInsideAlbum",
                    query: " query PictureListInsideAlbum($input: PictureListInput!) { picture { list(input: $input) { info { ...FacetCollectionInfo } items { __typename id title description created like_status number_of_comments number_of_favorites moderation_status width height resolution aspect_ratio url_to_original url_to_video is_animated position permissions url tags { category text url } thumbnails { width height size url } } } } } fragment FacetCollectionInfo on FacetCollectionInfo { page has_next_page has_previous_page total_items total_pages items_per_page url_complete } ",
                    variables: `{"input":{"filters":[{"name":"album_id","value":"${id}"}],"display":"date_newest","items_per_page":50,"page":${page}}}`
                });
                return `https://apicdn.luscious.net/graphql/nobatch/?${searchParams}`;
            };
            let id = Number(new URL(fn.gu("a[href*='/read/'],.album-heading a")).pathname.split("/")[2].match(/\d+$/)[0]);
            let max = await fetch(getApiUrl(id, 1)).then(res => res.json()).then(json => json.data.picture.list.info.total_pages);
            let fetchNum = 0;
            let resArr = fn.arr(max, (v, i) => {
                let url = getApiUrl(id, (i + 1));
                return fetch(url).then(res => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                    return res.json();
                }).then(json => json.data.picture.list.items.map(e => {
                    return e.url_to_video ? {
                        video: e.url_to_video
                    } : {
                        original: e.url_to_original,
                        thumbnail: e.thumbnails.at(-1).url
                    }
                }));
            });
            return Promise.all(resArr).then(data => {
                videoSrcArray = data.flat().filter(item => item.video).map(e => e.video);
                thumbnailSrcArray = data.flat().filter(item => item.thumbnail).map(e => e.thumbnail);
                return data.flat().filter(item => item.original).map(e => e.original);
            });
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["article.o-padding-top-bottom,.picture-frame-wrapper", 3],
        downloadVideo: true,
        customTitle: () => {
            if (!_this.SPA()) return null;
            return fn.waitEle(".album-heading:not(.o-padding-sides),.album-heading.o-padding-sides a").then(e => e.innerText);
        },
        css: "body.o-modal-no-scroll{overflow:unset!important}",
        hide: "#modal-root",
        category: "hcomic"
    }, {
        name: "E次元",
        host: ["www.evacg.org"],
        reg: /^https?:\/\/www\.evacg\.org\/archives\/\d+/,
        include: ".wp-caption img",
        exclude: ".poi-alert__msg",
        imgs: ".wp-caption img",
        button: [4],
        insertImg: [
            [".inn-singular__post__body__content", 0, ".wp-caption"], 2
        ],
        customTitle: ".inn-singular__post__title",
        category: "nsfw1"
    }, {
        name: "次元岛",
        host: ["ciyuandao.com"],
        reg: /^https?:\/\/ciyuandao\.com\/photo\/show\/\d+/,
        imgs: ".talk_pic  img",
        button: [4],
        insertImg: [".talk_pic", 2],
        customTitle: "h1",
        category: "nsfw1"
    }, {
        name: "萌次元",
        host: ["www.mtutuu.com"],
        reg: /^https?:\/\/www\.mtutuu\.com\/\d+\.html$/,
        exclude: ".content-cap",
        imgs: ".entry-content img",
        button: [4],
        insertImg: [
            ["//div[@class='entry-content']/p[img]", 2, "//div[@class='entry-content']/p[img]"], 2
        ],
        customTitle: ".post-style-3-title",
        category: "nsfw1"
    }, {
        name: "次元小镇",
        host: ["dimtown.com"],
        reg: /^https?:\/\/dimtown\.com\/\d+\.html$/,
        exclude: ".down-login",
        imgs: "#content img",
        button: [4],
        insertImg: [
            ["p:has(>img),p:has(a>img)", 2, "p:has(>img),p:has(a>img)"], 2
        ],
        autoDownload: [0],
        next: ".post-pre a",
        prev: ".post-next a",
        customTitle: "h1",
        category: "nsfw1"
    }, {
        name: "米卡插画",
        host: ["mikagogo.com"],
        reg: /^https?:\/\/mikagogo\.com\/\d+/,
        imgs: "#content img",
        autoDownload: [0],
        next: ".post-pre a",
        prev: ".post-next a",
        customTitle: "h1:not([class])",
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "推次元",
        host: ["www.a2cy.com", "a2cy.com"],
        reg: /^https?:\/\/(www\.)?a2cy\.com\/phone\/list\/\w+\/\d+\.html$/,
        imgs: ".imgBox img",
        customTitle: "h1",
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "Cosplay Porn",
        host: ["cosplayporn.online"],
        link: "https://cosplayporn.online/category/cosplay/",
        reg: /^https?:\/\/cosplayporn\.online\/\w+\/[^\/]+\/$/,
        include: ".video-description img",
        exclude: ".responsive-player",
        imgs: ".video-description img",
        button: [4],
        insertImg: [".video-description", 2],
        customTitle: ".entry-title",
        observerClick: "#wpdp-close",
        category: "nsfw1"
    }, {
        name: "Cosplay Porn",
        reg: /^https?:\/\/cosplayporn\.online\//,
        observerClick: "#wpdp-close",
        category: "ad"
    }, {
        name: "咿呀美图",
        url: {
            h: "www.1ymt.com",
            d: "pc"
        },
        SPA: true,
        imgs: () => {
            if (document.location.pathname.startsWith("/work/")) {
                return fn.fetchDoc(document.location.pathname, {
                    "headers": {
                        "accept": "text/html, */*; q=0.01",
                        "x-requested-with": "XMLHttpRequest"
                    }
                }).then(dom => fn.gae(".photo-thumbs li", dom));
            } else {
                return [];
            }
        },
        category: "nsfw1"
    }, {
        name: "Cosersets",
        host: ["www.cosersets.com"],
        link: "https://www.cosersets.com/1",
        reg: /^https?:\/\/www\.cosersets\.com/,
        SPA: true,
        observerURL: true,
        init: () => fn.waitEle(".z-breadcrumbs .z-breadcrumbs__item"),
        imgs: async (msg = 1) => {
            if (msg === 1) fn.showMsg(displayLanguage.str_05, 0);
            let body = {
                storageKey: "1",
                path: decodeURIComponent(window.location.pathname.replace(/^\/1/, "")),
                password: "",
                orderBy: "name",
                orderDirection: "asc"
            };
            let fetchJson = await fetch("/api/storage/files", {
                "headers": {
                    "accept": "application/json, text/plain, */*",
                    "content-type": "application/json;charset=UTF-8;"
                },
                "body": JSON.stringify(body),
                "method": "POST"
            }).then(res => res.json());
            return fetchJson.data.files.map(file => file.url);
        },
        capture: () => _this.imgs(0),
        customTitle: async () => {
            await delay(500);
            return fn.gt(".z-breadcrumbs")?.replace(/\n/g, " - ").replace(/首页 - |Cosersets - /, "");
        },
        category: "nsfw1"
    }, {
        name: "小丁 (Fantasy Factory) Patreon Cosplay Leaks",
        host: ["www.fantasyfactory.xyz"],
        reg: /^https?:\/\/www\.fantasyfactory\.xyz\//,
        SPA: true,
        observerURL: true,
        init: () => fn.waitEle("#crumbbar"),
        imgs: () => {
            let urls = fn.gau(".item.file>a");
            videoSrcArray = urls.filter(url => url.includes(".mp4"));
            return urls.filter(url => !/\.md$|\.mp4$/.test(url));
        },
        capture: () => _this.imgs(),
        customTitle: async () => {
            await delay(500);
            return fn.gt("#crumbbar")?.replace("www.fantasyfactory.xyz", "小丁 (Fantasy Factory)")
        },
        category: "nsfw1"
    }, {
        name: "Tokar浵卡 Cosplay",
        host: ["tokar.fantasyfactory.xyz"],
        reg: /^https?:\/\/tokar\.fantasyfactory\.xyz\/album\/\d+$/,
        init: () => fn.createImgBox(".container", 2),
        button: [4],
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let video = fn.ge("a[href^='/video/']");
            if (video) {
                let url = fn.gu("a[href^='/video/']");
                videoSrcArray = await fn.fetchDoc(url).then(dom => fn.gae("video>source", dom).map(e => e.src));
            }
            let viewUrl = fn.gu("//a[text()='View Photos']");
            return fn.iframeVar(viewUrl, "list").then(w => w.list.flat());
        },
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: "h2.text-center",
        downloadVideo: true,
        category: "nsfw1"
    }, {
        name: "蠢沫沫",
        link: "https://yanxiangrong.github.io/chunmomo/",
        reg: /^https?:\/\/yanxiangrong\.github\.io\/chunmomo\/[^\/]+\//,
        imgs: "p img[alt]",
        customTitle: "h1[id]",
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "二次元图库",
        host: ["vtecy.top"],
        reg: /^https?:\/\/vtecy\.top\/index\.php\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".post-next h2>a",
        prev: ".post-pre h2>a",
        customTitle: ".entry-header>h1",
        category: "nsfw2"
    }, {
        name: "女神社",
        host: ["nshens.com", "inewgirl.com", "lovens.shop"],
        reg: /^https?:\/\/((www\.)?nshens\.com|(www\.)?inewgirl\.com)\/(web\/)?\d+\/\d+\/\d+\/[^/]+$/,
        exclude: ".justify-center>button>.v-btn__content",
        init: () => fn.waitEle("h3"),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let [max] = fn.gt(".v-pagination li:last-child,div:has(>div.current-item)~div:last-child", 2).match(/\d+/);
            let links = fn.arr(max, (v, i) => siteUrl + "/" + (i + 1));
            let fetchNum = 0;
            let resArr = links.map((url, i, arr) => {
                return fn.fetchDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${arr.length}`, 0);
                    let code = fn.gst("photoList", dom);
                    return fn.run(code.match(/photoList:([^\]]+\])/)[1]);
                });
            });
            let photourl = await Promise.all(resArr).then(data => data.flat().map(e => e.photourl));
            if (photourl.length > [...new Set(photourl)].length) setTimeout(() => fn.showMsg("VIP套圖需升級為VIP", 5000), 1200);
            return photourl;
        },
        button: [4],
        insertImg: ["//div[a[div[@class='v-image v-responsive theme--light']]]", 2],
        customTitle: "h3",
        category: "nsfw2"
    }, {
        name: "Chottie", //很多都需要VIP,不然只會重複抓到第一頁的圖片
        host: ["chottie.com", "chinesehottie.com"],
        reg: /^https?:\/\/((www\.)?chottie\.com|(www\.)?chinesehottie\.com)\/blog\/(\w{2}\/)?archives\/\d+$/,
        exclude: ".justify-center>button>.v-btn__content",
        init: () => fn.waitEle("h3"),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let [max] = fn.gt(".v-pagination li:last-child,div:has(>div.current-item)~div:last-child", 2).match(/\d+/);
            let links = fn.arr(max, (v, i) => siteUrl + "/" + (i + 1));
            let fetchNum = 0;
            let resArr = links.map((url, i, arr) => {
                return fn.fetchDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${arr.length}`, 0);
                    let code, imgs;
                    try {
                        code = fn.gst("imgList", dom);
                        imgs = fn.run(code.match(/imgList:([^\]]+\])/)[1]);
                    } catch {
                        code = fn.gst("snapshotList", dom);
                        imgs = fn.run(code.match(/snapshotList:([^\]]+\])/)[1]);
                    }
                    return imgs;
                });
            });
            let data = await Promise.all(resArr).then(data => data.flat());
            if (data.length > [...new Set(data)].length) setTimeout(() => fn.showMsg("VIP套圖需升級為VIP", 5000), 1200);
            return data;
        },
        button: [4],
        insertImg: ["//div[a[div[@class='v-image v-responsive theme--light']]]", 2],
        customTitle: "h3",
        category: "nsfw2"
    }, {
        name: "美妹妹",
        host: ["www.meimeimei.org"],
        reg: [
            /^https?:\/\/www\.meimeimei\.org\/\d+\/\d+\/$/,
            /^https?:\/\/www\.meimeimei\.org\/\d+\/\d+\/\d+\.html$/
        ],
        imgs: () => {
            let max = fn.gt(".chapterpage>a:last-child", 2);
            let links = [];
            if (/\.html/.test(siteUrl)) {
                let url = fn.gu(".pageCurr").replace("_1.html", "");
                links = fn.arr(max, (v, i) => url + "_" + (i + 1) + ".html");
            } else {
                let url = fn.gu(".pageCurr").replace("1.html", "");
                links = fn.arr(max, (v, i) => url + (i + 1) + ".html");
            }
            return fn.getImgA(".img>img", links, 100);
        },
        button: [4],
        insertImg: [".txt_tcontent", 1],
        autoDownload: [0],
        next: "//div[contains(text(),'上一篇')]/a[not(@href='#')]",
        prev: "//div[contains(text(),'下一篇')]/a[not(@href='#')]",
        customTitle: ".bread>li:last-child>a",
        category: "nsfw1"
    }, {
        name: "tu928美女写真网",
        host: ["tu928.com"],
        reg: /^https?:\/\/tu928\.com\/\d+\.html/,
        imgs: () => fn.getImgA(".wp-block-image img", ".page-links>a", 300),
        button: [4],
        insertImg: [
            [".post-item-metadata", 1, ".wp-block-image"], 2
        ],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".entry-title",
        hide: "#af-preloader,#page>a,#page>div:not(#content):has(>a>img)",
        category: "nsfw1"
    }, {
        name: "图集网",
        host: ["aiavr.uk"],
        url: {
            h: /^aiavr\.uk$/,
            p: "/detail",
            s: "aid="
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let id = new URLSearchParams(fn.ls).get("aid");
            let total = await fetch(`/api/image/list?aid=${id}&pageNum=1`).then(res => res.json()).then(json => json.total);
            let pages = Math.ceil(total / 6);
            let links = fn.arr(pages, (v, i) => `/api/image/list?aid=${id}&pageNum=${i + 1}`);
            let fetchNum = 0;
            let resArr = links.map(url => fetch(url).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${links.length}`, 0);
                return json.data;
            }));
            return Promise.all(resArr).then(data => data.flat()).then(arr => arr.map(e => {
                if (e.sourceUrl?.startsWith("http")) {
                    return e.sourceUrl;
                } else if (e.sourceWeb?.startsWith("http") && e.sourceUrl?.startsWith("/")) {
                    return e.sourceWeb + e.sourceUrl;
                } else if (e.url?.startsWith("http")) {
                    return e.url;
                } else {
                    return null;
                }
            }));
        },
        capture: () => _this.imgs(),
        //button: [4],
        //insertImg: [".q-infinite-scroll", 2],
        customTitle: () => {
            let id = new URLSearchParams(fn.ls).get("aid");
            //return fetch(`https://admin.aiavr.uk/album/info?id=${id}`).then(res => res.json()).then(json => json.data.title);
            return fn.xhr(`https://admin.aiavr.uk/album/info?id=${id}`, {
                responseType: "json"
            }).then(json => json.data.title);
        },
        category: "nsfw1"
    }, {
        name: "图集网",
        url: {
            h: ["user.aiavr.uk", "m.aiavr.uk"],
            p: ["systemAlbum", "/detail"],
            s: "aid="
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let id = new URLSearchParams(fn.ls).get("aid");
            let total = await fetch(`https://admin.aiavr.uk/image/list?aid=${id}&pageNum=1`).then(res => res.json()).then(json => json.total);
            let pages = Math.ceil(total / 6);
            let links = fn.arr(pages, (v, i) => `https://admin.aiavr.uk/image/list?aid=${id}&pageNum=${i + 1}`);
            let fetchNum = 0;
            let resArr = links.map(url => fetch(url).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${links.length}`, 0);
                return json.data;
            }));
            return Promise.all(resArr).then(data => data.flat()).then(arr => arr.map(e => {
                if (e.sourceUrl?.startsWith("http")) {
                    return e.sourceUrl;
                } else if (e.sourceWeb?.startsWith("http") && e.sourceUrl?.startsWith("/")) {
                    return e.sourceWeb + e.sourceUrl;
                } else if (e.url?.startsWith("http")) {
                    return e.url;
                } else {
                    return null;
                }
            }));
        },
        capture: () => _this.imgs(),
        //button: [4],
        //sertImg: [".q-infinite-scroll", 2],
        customTitle: () => {
            let id = new URLSearchParams(fn.ls).get("aid");
            return fetch(`https://admin.aiavr.uk/album/info?id=${id}`).then(res => res.json()).then(json => json.data.title);
        },
        category: "nsfw1"
    }, {
        name: "图集网",
        link: "https://user.aiavr.uk/users",
        url: {
            h: ["user.aiavr.uk", "m.aiavr.uk"],
            p: "userAlbum",
            s: "aid="
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let id = new URLSearchParams(fn.ls).get("aid");
            let vip = await fetch(`https://admin.aiavr.uk/userAlbum/getInfo/${id}`).then(res => res.json()).then(json => json.data.isSee);
            if (vip == false) {
                setTimeout(() => {
                    fn.showMsg("VIP限定專輯圖片!", 5000);
                }, 1200);
                return [];
            }
            let total = await fetch(`https://admin.aiavr.uk/userImage/list?aid=${id}&pageNum=1`).then(res => res.json()).then(json => json.total);
            let pages = Math.ceil(total / 6);
            let links = fn.arr(pages, (v, i) => `https://admin.aiavr.uk/userImage/list?aid=${id}&pageNum=${i + 1}`);
            let fetchNum = 0;
            let resArr = links.map(url => fetch(url).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${links.length}`, 0);
                return json.data;
            }));
            return Promise.all(resArr).then(data => data.flat()).then(arr => arr.map(e => e.imgUrl == null ? null : "https://image.aiavr.uk/xinshijie" + e.imgUrl).filter(item => item));
        },
        capture: () => _this.imgs(),
        //tton: [4],
        //sertImg: [".q-infinite-scroll", 2],
        customTitle: () => {
            let id = new URLSearchParams(fn.ls).get("aid");
            return fetch(`https://admin.aiavr.uk/userAlbum/getInfo/${id}`).then(res => res.json()).then(json => json.data.title);
        },
        category: "nsfw1"
    }, {
        name: "爱死美女图片站",
        host: ["www.24tupian.org"],
        url: {
            h: "24tupian.org",
            p: /^\/\w+\/\d+\/\d+\/\d+\.html$/,
            e: "img[data-original*='imgs.diercun.com']"
        },
        imgs: async () => {
            let pid = fn.gt("#pid");
            let num = Number(fn.gt(".mores>a").match(/\d+/)[0]);
            let max = Math.ceil(num / 21);
            let html = "";
            let fetchNum = 0;
            for (let i = 0; i < num; i += 21) {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                await fetch(`/ajaxs.aspx?fun=getmore&id=${pid}&p=${i}`).then(res => res.text()).then(text => (html += text));
            }
            let dom = fn.doc(html);
            let datas = fn.gae("img[data]", dom).map(e => e.getAttribute("data"));
            thumbnailSrcArray = datas.map(data => "https://imgs.diercun.com" + data);
            return datas.map(data => "https://big.diercun.com" + _unsafeWindow.getbig(data));
        },
        button: [4],
        insertImg: [
            [".mores", 2], 2
        ],
        go: 1,
        topButton: true,
        customTitle: ".gtitle1>h1",
        hide: "body>.mask",
        category: "nsfw1"
    }, {
        name: "爱死美女图片鏡像站?",
        url: {
            h: "www.aisimm.com",
            p: ".html",
            e: [".gtps", "#hgg3"]
        },
        imgs: async () => {
            let imgs = fn.gae(".gtps img");
            if (fn.ge("//a[text()='尾页']")) {
                let [, max] = fn.gu("//a[text()='尾页']").match(/_(\d+)\.html$/);
                max = Number(max) + 1;
                let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url.replace(".html", "") + `_${i}.html`);
                imgs = await fn.getEle(links, ".gtps img");
            }
            thumbnailSrcArray = fn.getImgSrcArr(imgs);
            return thumbnailSrcArray.map(url => {
                let i = url.lastIndexOf("/");
                let murl = url.substring(i + 1);
                url = url.replace(murl, murl.substring(1));
                url = url.replace("img.", "big.");
                return url;
            });
        },
        button: [4],
        insertImg: [
            ["#hgg3", 1], 2
        ],
        go: 1,
        topButton: true,
        customTitle: ".gtitle1>h1",
        category: "nsfw1"
    }, {
        name: "爱死cos美女图片站",
        host: ["www.24cos.org", "www.lovecos.net"],
        reg: /^https?:\/\/(www\.24cos\.org|www\.lovecos\.net)\/\w+\/\d+\.html$/,
        imgs: async () => {
            let pages = fn.gau(".page>a");
            let liImgs = fn.gae(".mtp>li");
            if (pages.length > 0 && liImgs.length < 21) {
                await fn.getEle(pages, ".mtp>li", [".mtp", 0]);
            }
            thumbnailSrcArray = fn.gae(".mtp img").map(e => decodeURIComponent(e.src));
            return thumbnailSrcArray.map(url => {
                let i = url.lastIndexOf("/");
                let murl = url.substring(i + 1);
                url = url.replace(murl, murl.substring(1));
                return url;
            });
        },
        button: [4],
        insertImg: [
            [".mtp", 2, ".mtp"], 2
        ],
        topButton: true,
        customTitle: ".tmsg>h1",
        css: ".tpmh img{filter:unset!important;}",
        category: "nsfw1"
    }, {
        name: "Huamao wallpaper 花猫壁纸",
        host: ["huamaobizhi.com", "ja.huamaobizhi.com", "en.huamaobizhi.com"],
        url: {
            h: "huamaobizhi.com",
            p: "/mix/",
            e: ".images-card"
        },
        init: async () => {
            let load = fn.ge(".load-more-photos");
            if (load) load.remove();
            await fn.getNP(".images-card", "li.active+li>a", null, ".pagination");
            fn.gae(".thumb-nsfw").forEach(e => e.classList.remove("thumb-nsfw"));
        },
        imgs: async () => {
            thumbnailSrcArray = fn.gae(".images-card img").map(e => e.dataset.src ?? e.src);
            fn.clearAllTimer(2);
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            const resBlobUrl = (id, max) => {
                return fetch("/normal-download/", {
                    "headers": {
                        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
                        "content-type": "application/x-www-form-urlencoded"
                    },
                    "body": `wallpaperId=${id}`,
                    "method": "POST"
                }).then(res => res.blob()).then(blob => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                    return URL.createObjectURL(blob);
                });
            };
            let IDs = fn.gae("span[data-imgid]").map(e => e.dataset.imgid);
            let bigImgsArr = [];
            for (let id of IDs) {
                bigImgsArr.push(await resBlobUrl(id, IDs.length));
                //await delay(1500);
            }
            return bigImgsArr;
        },
        button: [4],
        insertImg: [
            ["#main", 2], 0
        ],
        go: 1,
        customTitle: ".title>h1",
        fetch: 1,
        ex: "jpg",
        category: "nsfw1"
    }, {
        name: "Huamao wallpaper 花猫壁纸 en.huamaobizhi.com 分類自動翻頁",
        host: ["ja.huamaobizhi.com", "en.huamaobizhi.com"],
        enable: 1,
        url: {
            h: "huamaobizhi.com",
            p: /^\/(mixs|tags|artists|people-tags)\/\?/
        },
        autoPager: {
            ele: "//div[@class='row'][div[div[@class='mixs-card']]] | //div[@class='table-responsive table-sm-no-border'] | //div[div[div[@class='thumbnail']]] | //div[@class='tags-wrap']",
            next: ".pagination li.active+li>a",
            re: ".pagination",
            pageNum: ".pagination li.active",
            bF: (dom) => {
                fn.gae(".mixs-card-img:not(.lock)", dom).forEach(e => {
                    let url = e.attributes[1].value.replaceAll("'", "");
                    e.outerHTML = `<div class="mixs-card-img" data-src="${url}" lazy="loaded" style="background-image: url('${url}');"></div>`;
                });
                fn.gae(".thumbnail .img-circle[v-lazy]", dom).forEach(e => {
                    let url = e.getAttribute("v-lazy").replaceAll("'", "");
                    e.outerHTML = `<img src="${url}" alt="${e.alt}" class="img-circle" data-src="${url}" lazy="loaded">`;
                });
                fn.gae(".tags-item img[v-lazy]", dom).forEach(e => {
                    let url = e.getAttribute("v-lazy").replaceAll("'", "");
                    e.outerHTML = `<img src="${url}" alt="${e.alt}" data-src="${url}" lazy="loaded">`;
                });
            }
        },
        openInNewTab: ".mixs-card-content>a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "次元LSP/猫猫网盘/云边网盘",
        url: {
            h: ["cylsp.org", "pan.catcat.blog", "qinzhi.top"]
        },
        SPA: true,
        observerURL: true,
        imgs: () => fn.getAList(),
        customTitle: () => fn.dt({
            d: [" | 次元LSP", " | 猫猫网盘", " | 云边网盘"]
        }),
        downloadVideo: true,
        category: "nsfw1"
    }, {
        name: "J M G T的AList",
        url: {
            h: "alist.qiuyeshudian.com"
        },
        SPA: true,
        observerURL: true,
        imgs: () => fn.getAList(),
        customTitle: () => fn.dt({
            d: [
                " | AList",
                /(\d+Photos)\s|\(\d+Photos\)\s|\d+Photos\s|\d+\spics|\(选登\)|(选登\d+P)/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "新美图录/臺灣美腿女郎",
        host: ["www.xinmeitulu.com", "www.twlegs.com"],
        reg: /^https?:\/\/(www\.xinmeitulu\.com|www\.twlegs\.com)\/photo\//,
        imgs: "img[data-original]",
        button: [4],
        insertImg: [".text-center", 2],
        customTitle: "h1.h3",
        category: "nsfw1"
    }, {
        name: "美图录",
        host: ["meitulu.me"],
        reg: /^https?:\/\/meitulu\.me\/item\/\d+\.html$/,
        imgs: () => fn.getImg(".mb-4>img[alt]", fn.gt(".pagination>li:last-child", 2), 9),
        button: [4],
        insertImg: [".mb-4", 1],
        customTitle: ".top-title",
        category: "nsfw1"
    }, {
        name: "秀窝/RMM吧/赞MM/恩图集/美Girl图集/狐图网/930圖片網/爱秀美女/四魔写真/JN美眉网",
        host: [
            "www.xiuwo.net",
            "www.rmm8.com",
            "www.zanmm.com",
            "www.entuji.com",
            "www.mhgirl.com",
            "www.hutu6.com",
            "www.930tu.com",
            "www.930tp.com",
            "wap.kunv.cc",
            "www.kunv.cc",
            "www.smkwan.com",
            "www.jnmmw.com"
        ],
        reg: [
            /^https?:\/\/(www\.xiuwo\.net|www\.rmm8\.com|www\.mhgirl\.com|(www|wap)\.kunv\.cc)\/tu([\w]+)?\/\d+\.html$/,
            /^https?:\/\/www\.zanmm\.com\/tupian\/\d+\.html$/,
            /^https?:\/\/(www\.entuji\.com|www\.hutu6\.com)\/\w+\/\d+\.html$/,
            /^https?:\/\/www\.930t(u|p)\.com\/\w+\/\d+\.html$/,
            /^https?:\/\/www\.smkwan\.com\/mm\/\d+\.html$/,
            /^https?:\/\/www\.jnmmw\.com\/meimei\/\d+\.html$/
        ],
        init: () => fn.clearAllTimer(),
        imgs: () => fn.getImgO("#showimg img", fn.gt("//p[contains(text(),'图片数量')]").match(/\d+/)[0], 9),
        button: [4],
        insertImg: ["#showimg", 2],
        customTitle: ".weizhi h1",
        css: "@media only screen and (max-width:3840px){.content img{max-width:100%!important}}",
        category: "nsfw1"
    }, {
        name: "图美图",
        host: ["www.tumeitu.com", "m.tumeitu.com"],
        url: {
            h: ".tumeitu.com",
            p: "/a/",
            e: [".content img", ".weizhi"]
        },
        imgs: () => {
            let max;
            if (fn.lh.startsWith("m.")) {
                max = fn.gt(".allpage").match(/\d+/g).at(-1);
            } else {
                [, max] = fn.gu("//a[text()='尾页']").match(/(\d+)\.html$/);
            }
            return fn.getImg(".content img", max, 9);
        },
        button: [4],
        insertImg: [".content", 2],
        customTitle: () => fn.dt({
            s: ".weizhi h1",
            d: /\/.+$/
        }),
        hide: ".shuoming,.bk20,center:has(>#pages)",
        category: "nsfw1"
    }, {
        name: "妹妹图",
        host: ["mm.tvv.tw"],
        reg: /^https?:\/\/mm\.tvv\.tw\/archives\/\d+\.html$/,
        imgs: ".img-responsive",
        button: [4],
        insertImg: ["//p[img]", 2],
        customTitle: ".blog-details-headline",
        category: "nsfw1"
    }, {
        name: "小姐姐么/妹妹图集",
        host: ["xiaojiejie.me", "www.mmtuji.com"],
        reg: [
            /^https?:\/\/xiaojiejie\.me\/\d+\/[^\/]+\/$/,
            /^https?:\/\/www\.mmtuji\.com\/\d+\.html$/
        ],
        init: () => {
            if (fn.lh.includes("mmtuji")) {
                _unsafeWindow.fuckyou = null;
                _unsafeWindow.ck = null;
                _unsafeWindow.hehe = null;
                _unsafeWindow.comprehensiveCheck = null;
                _unsafeWindow.onWindowSizeChange = null;
                _unsafeWindow.onresize = null;
                fn.clearAllTimer(3);
            }
            let ps = fn.gae("#image_div>p");
            if (ps.length > 0) {
                ps.forEach(p => {
                    let a = fn.ge("a", p);
                    if (!a) {
                        tempEles.push(p);
                    }
                });
            }
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            return fetch("/wp-admin/admin-ajax.php", {
                "headers": {
                    "accept": "*/*",
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `action=chenxing_imageall&type=all&post_id=${_unsafeWindow.chenxing.PID}`,
                "method": "POST",
            }).then(res => res.text()).then(text => fn.doc(text)).then(dom => [...dom.images]);
        },
        button: [4],
        insertImg: ["#content", 2],
        insertImgAF: (parent) => {
            if (tempEles.length > 0) {
                for (let e of tempEles) {
                    insertBefore(parent.firstChild, e);
                }
            }
            fn.run("$(document).off()");
        },
        customTitle: () => fn.dt({
            d: [
                / – 小姐姐| - 妹妹图集/,
                /(\d+月\d+打赏群(自购)?资源)/
            ]
        }),
        css: ".content_left>p{margin:0}",
        category: "nsfw1"
    }, {
        name: "14MM图片网",
        host: ["www.14mm.cn"],
        reg: /^https:\/\/www\.14mm\.\w+\/\d+\.html$/,
        exclude: "//a[@rel='category tag'][text()='演出视频']",
        imgs: async () => {
            let max = fn.gt("a[title='最后页']");
            return fn.getImg("#image_div img", max, 9, [/\?x-oss-process.+$/, ""]);
            //return fn.getImg("#image_div img", max, 9);
        },
        button: [4],
        insertImg: ["#content", 2],
        insertImgAF: () => fn.run("$(document).off()"),
        customTitle: () => fn.title(" – 14MM图片网"),
        category: "nsfw1"
    }, {
        name: "最好秀色",
        host: ["www.zhxszone.com"],
        reg: /^https?:\/\/www\.zhxszone\.com\/\??\d+\.html$/,
        imgs: () => {
            let srcs = fn.getImgSrcArr("#play img");
            let srcArr = [];
            srcs.forEach(src => {
                let arr = src.split("https").filter(i => i);
                if (arr.length > 1) {
                    for (let src of arr) {
                        srcArr.push("https" + decodeURIComponent(src).replace(/".+$/, ""));
                    }
                } else {
                    srcArr.push(decodeURIComponent(src));
                }
            });
            return srcArr.filter(src => [".wp.com", ".jpg"].every(s => src.includes(s)));
        },
        button: [4],
        insertImg: ["#play", 2],
        customTitle: ".item_title",
        hide: ".item_images_info",
        category: "nsfw1"
    }, {
        name: "最好秀色 自動翻頁",
        reg: /^https?:\/\/www\.zhxszone\.com\//,
        autoPager: {
            ele: "#index_ajax_list",
            observer: "#index_ajax_list>li",
            next: "a.page-num-current+a:not([title])",
            re: ".pagebar",
            pageNum: "a.page-num-current"
        },
        openInNewTab: "#index_ajax_list a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "COSPLAY Girl 18+",
        host: ["cosplay.girl18.net", "xiuren.girl18.net", "bobosocks.girl18.net", "imiss.girl18.net", "cosplay.girl18.net"],
        url: {
            h: ".girl18.net"
        },
        imgs: "#image_div img",
        button: [4],
        insertImg: ["#image_div", 2],
        customTitle: ".item_title",
        hide: ".item_images_info",
        category: "nsfw2"
    }, {
        name: "Girl 18+/Bikini Girl",
        host: ["girl18.net", "bikiniz.net"],
        reg: /^https?:\/\/((www\.|thailand\.)?girl18\.net|(www\.)?bikiniz\.net)\/\w+\/\d+\/\d+\/\d+\//,
        imgs: "#content img",
        button: [4],
        insertImg: ["#content", 2],
        customTitle: ".item_title",
        hide: ".item_images_info",
        category: "nsfw1"
    }, {
        name: "Coser Lab",
        host: ["coserlab.io"],
        reg: /^https?:\/\/coserlab\.io\/archives\/\d+$/,
        exclude: ".card-body .error-empty,.post-hide-content",
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("a.glightbox img");
            fn.showMsg("fn.xhrHEA(check)...", 0);
            let xhrNum = 0;
            return fn.gau("a.glightbox").map(u => u.replace("-scaled", "")).map(async (src, i, arr) => {
                await delay(100 * i);
                let res = await fn.xhrHEAD(src);
                fn.showMsg(`fn.xhrHEAD(${xhrNum+=1}/${arr.length})`, 0);
                let status = res.status;
                return status == 404 ? src.replace(/(\.[a-z]+)$/i, "-scaled$1") : src;
            });
        },
        thums: "a.glightbox img",
        button: [4],
        insertImg: [
            [".masonry-list", 2, ".masonry-list"], 2
        ],
        customTitle: "span.current,.card-body h1",
        category: "nsfw2"
    }, {
        name: "爱推图",
        url: {
            h: "www.aituitu.com",
            p: ".html",
            e: ".reading-open"
        },
        imgs: ".single-content img",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: "写真"
        }),
        category: "nsfw1"
    }, {
        name: "Zusi足丝",
        url: {
            h: "zusi.net"
        },
        init: () => [...document.getElementsByTagName("style")]?.find(s => s.textContent.includes("yuanshen.svg"))?.remove(),
        imgs: ".masonry-list a.glightbox",
        button: [4],
        insertImg: [
            [".masonry-list", 2, ".masonry-list"], 2
        ],
        customTitle: ".card-body h1",
        category: "nsfw1"
    }, {
        name: "美图坊",
        host: ["www.yalatu.com", "m2ph.xyz", "www.m2ph.xyz", "110.40.75.172:39000"],
        url: () => ["flutter.password", "flutter.account"].every(k => k in localStorage) && hasTouchEvent,
        SPA: true,
        init: () => {
            if ("gallery_json" in localStorage) {
                siteJson = JSON.parse(localStorage.getItem("gallery_json"));
            }
            _unsafeWindow.addEventListener("message", async event => {
                if (["response", "change"].some(m => event.data === m)) {
                    await captureSrcB();
                    //debug(`\n自定義標題:${customTitle}`);
                    //debug("\n此圖集JSON資料\n", siteJson);
                }
            });
            const ajaxHooker = addAjaxHookerLibrary();
            ajaxHooker.filter([{
                method: "POST",
                type: "xhr",
                url: "/ServerInfo",
            }, {
                method: "POST",
                type: "xhr",
                url: "/ServerConfig",
            }, {
                method: "POST",
                type: "xhr",
                url: "/Image/ImageUrl",
            }]);
            ajaxHooker.hook(request => {
                //debug("API請求", request);
                request.response = res => {
                    if (request.url.includes("/ServerConfig") || request.url.includes("/ServerInfo")) {
                        //debug("(ServerConfig_API || ServerInfo_API) 回應", res);
                        let text = new TextDecoder().decode(res.response);
                        let json = JSON.parse(text);
                        //debug("(ServerConfig_API || ServerInfo_API) 回應JSON", json);
                        if ("ipv4" in json.data) {
                            siteJson.big_image_base_url = Object.values(Object.fromEntries(Object.entries(json.data.ipv4).filter(([k, v]) => k.startsWith("big_image_base_url") && !!v)))[0];
                        } else if ("image_server_list" in json.data) {
                            siteJson.big_image_base_url = json.data.image_server_list[Math.round(Math.random())].image_big_base;
                        } else {
                            Reflect.deleteProperty(siteJson, "big_image_base_url");
                        }
                        //debug("big_image_base_url", siteJson.big_image_base_url);
                    }
                    if (request.url.includes("/Image/ImageUrl")) {
                        //debug("ImageUrl_API回應", res);
                        let text = new TextDecoder().decode(res.response);
                        let json = JSON.parse(text);
                        //debug("ImageUrl_API回應JSON", json);
                        siteJson = Object.assign(siteJson, json);
                        siteJson.title = fn.dt({
                            t: siteJson.title
                        });
                        customTitle = siteJson.title;
                        localStorage.setItem("gallery_json", JSON.stringify(siteJson));
                        _unsafeWindow.postMessage("response", fn.lo);
                    }
                };
            });
        },
        imgs: () => {
            if (!siteJson?.big_image_base_url && !siteJson?.data) return [];
            let paths = JSON.parse(siteJson.data);
            let base = siteJson.big_image_base_url;
            let srcs = paths.map(p => base + p);
            return srcs;
        },
        capture: () => _this.imgs(),
        customTitle: () => siteJson?.title,
        category: "nsfw1"
    }, {
        name: "孔雀海/洛丽网/ladymao图库/懒人看图",
        host: ["www.kongquehai.net", "www.lolili.net", "www.ladymao.net", "www.lazymanpic.net"],
        reg: [
            /^https?:\/\/((www\.)?kongquehai\.net|(www\.)?lolili\.net)\/\w+\/\w+\/\w+\.html(\?btwaf=\d+)?$/i,
            /^https?:\/\/(www\.)?ladymao\.net\/[a-z]{2,3}\/\w+(\?btwaf=\d+)?$/,
            /^https?:\/\/(www\.)?lazymanpic\.net\/[a-z]{2,3}\/\w+(\?btwaf=\d+)?$/
        ],
        imgs: async () => {
            await fn.getNP(".m-list-content img", "//a[text()='下一页'][@class='next']", null, ".link_pages");
            return fn.gae(".m-list-content img");
        },
        button: [4],
        insertImg: [".m-list-content", 2],
        autoDownload: [0],
        next: ".sxpage_r>a",
        prev: ".sxpage_l>a",
        customTitle: () => fn.dt({
            s: ".m-list-tools>h2",
            d: [
                /\(\d\)/,
                /\[\d+[\s\.\+\w-\/]+\].*/,
                /全网首发|免费下载|无损图包下载|未删减版|无删减图包/g
            ]
        }),
        category: "nsfw1"
    }, {
        name: "尤物秀",
        host: ["www.youwushow.net"],
        reg: /^https?:\/\/(www\.)?youwushow\.net\/pic\/\w+\.html(\?btwaf=\d+)?$/,
        imgs: async () => {
            await fn.getNP(".entry-content>*:not(.page-links)", "span.current+a", null, ".page-links");
            return fn.gae(".entry-content img");
        },
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: "a.prev-link",
        prev: "a.next-link",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: [
                /\(\d\)/,
                /\[\d+[\s\.\+\w-\/]+\].*/,
                /全网首发|免费下载|无损图包下载|未删减版|无删减图包/g
            ]
        }),
        category: "nsfw1"
    }, {
        name: "iLegs时光印象网",
        host: ["legskr.com"],
        reg: /^https?:\/\/legskr\.com\/album\/detail\/\d+\.html$/,
        imgs: () => {
            thumbnailSrcArray = fn.gae("#lightgallery .img-fluid[data-src]").map(e => e.dataset.src ?? e.src);
            return fn.gae("#lightgallery div.col-6[data-src]");
        },
        button: [4],
        insertImg: ["#lightgallery", 2],
        customTitle: () => fn.dt({
            s: ".title",
            d: "Album name:"
        }),
        category: "nsfw1"
    }, {
        name: "图集佬",
        url: {
            h: "www.tujilao.com",
            p: ".html"
        },
        imgs: ".wp-posts-content img",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']][not(starts-with(@href,'javascript'))]",
        prev: "//a[p[text()='下一篇']][not(starts-with(@href,'javascript'))]",
        customTitle: ".article-title",
        category: "nsfw1"
    }, {
        name: "比思在線圖庫",
        host: ["bisipic.xyz", "bisipic.online"],
        reg: /^https?:\/\/bisipic\.(xyz|online)\/thread[\d-]+\.html$/,
        imgs: () => fn.gae("img[zoomfile]").map(e => location.origin + "/" + e.getAttribute("zoomfile")),
        button: [4],
        insertImg: ["[id^=postmessage]", 2],
        customTitle: () => fn.ge("meta[name=keywords]").content.replace(/【\d+P】.*/i, ""),
        category: "nsfw1"
    }, {
        name: "洛秀网/维秘秀",
        host: ["www.loxiu.com", "www.xiunvw.com"],
        url: {
            t: ["洛秀网", "维秘秀"],
            p: "/post/"
        },
        imgs: () => fn.getImg(".info-imtg-box>img[alt]", fn.gt(".pagebar>*:last-child", 3)),
        button: [4],
        insertImg: ["div:has(>.info-imtg-box)", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: ".info-title>h1",
        category: "nsfw1"
    }, {
        name: "第一美女套图网",
        host: ["meitu.sbs"],
        url: {
            t: "第一美女套图网",
            p: /^\/artdetail\w+\.html$/
        },
        imgs: ".ttnr img",
        button: [4],
        insertImg: [".ttnr", 2],
        //customTitle: ".breadcrumbs span",
        customTitle: () => fn.title(" - 第一美女套图网"),
        category: "nsfw1"
    }, {
        name: "遛无写真格式",
        url: {
            h: [
                "www.096d.com",
                "www.0niz.com",
                "www.1nlm.com",
                "www.1plq.com",
                "www.1tu5.com",
                "www.1vtr.com",
                "www.3pxa.com",
                "www.3tck.com",
                "www.4tck.com",
                "www.54k5.com",
                "www.5pwc.com",
                "www.6evu.com",
                "www.6kpo.com",
                "www.6tck.com",
                "www.6vtr.com",
                "www.7k1a.com",
                "www.7tck.com",
                "www.7u8t.com",
                "www.09kt.com",
                "www.c0h.net",
                "www.df10.net",
                "www.eshh.net",
                "www.game1313.net",
                "www.te2zn.com",
                "www.tmm123.vip",
                "www.wangblog.net",
                "www.wjstbs.net",
                "www.wsqap.com",
                "www.zhaixiaonan.com"
            ],
            p: /^\/\d+\.html$/,
            e: "#post_content img,.article-content img,.entry-content img"
        },
        exclude: "//a[@rel='category tag'][contains(text(),'人物简历') or contains(text(),'宅男科技') or contains(text(),'时尚玩酷') or contains(text(),'身边事') or contains(text(),'追星一族') or contains(text(),'网红头条') or contains(text(),'大众娱乐') or contains(text(),'生活热点') or contains(text(),'影评剧透') or contains(text(),'娱乐时尚') or contains(text(),'吃喝玩乐') or contains(text(),'体育') or contains(text(),'亲子宠物') or contains(text(),'番号大全') or contains(text(),'番号推荐') or contains(text(),'最新番号') or contains(text(),'素人番号')]",
        imgs: () => fn.getImgA("#post_content img,.article-content img,.entry-content img", ".pagelist a,.pagination a,.article-paging a"),
        button: [4],
        insertImg: ["#post_content,.article-content,.entry-content", 2],
        autoDownload: [0],
        next: "a[rel=prev],.article-nav-prev a",
        prev: "a[rel=next],.article-nav-next a",
        customTitle: () => fn.dt({
            s: "h1",
            d: [
                /无圣光.+$/,
                /无水印.+$/,
                /无删减.+$/,
                /高品质.+$/,
                /超高清.+$/,
            ]
        }),
        css: ".article_container{padding:10px 0px!important}#post_content{padding:0px!important}@media only screen and (max-width:640px){.container{max-width:100% !important}}",
        category: "nsfw1"
    }, {
        name: "出物社区写真网",
        host: ["www.ywsq.cc"],
        reg: /^https?:\/\/www\.ywsq\.cc\/[^\/]+\/[^.]+\.html$/,
        imgs: () => fn.getImgA("#post_content img", ".pagelist a"),
        button: [4],
        insertImg: ["#post_content", 2],
        autoDownload: [0],
        next: ".post-previous a",
        prev: ".post-next a",
        customTitle: ".article_container>h1",
        css: ".article_container{padding:10px 0px!important}#post_content{padding:0px!important}@media only screen and (max-width:640px){.container{max-width:100% !important}}",
        category: "nsfw1"
    }, {
        name: "原创妹子图/尤物私房图/极品美女图/免费私房图/私房网红图/尤物妹妹图",
        //所有域名在環境變數urltz
        host: ["www.ycmzt.com", "www.ywsft.com", "www.jpmnt.com", "www.mfsft.com", "www.sfwht.com", "www.ywmmt.com"],
        url: {
            e: [".b", "#picg", ".pagelist"],
            p: /^\/[a-z]+\/[a-z]+\/\d+\/\d+\.html$/
        },
        init: () => {
            fn.gae(".b a").forEach(a => a.removeAttribute("target"));
            fn.gae("#picg a").forEach(a => (a.outerHTML = a.innerHTML));
            fn.remove("iframe", 2000);
        },
        imgs: async () => {
            let max = fn.gt(".pagelist font~*:last-child", 2);
            let url = siteUrl.replace(/(_\d+)?\.html$/, "");
            let links = fn.arr(max, (v, i) => i == 0 ? url + ".html" : url + `_${i + 1}.html`);
            let imgsArr = [];
            for (let [page, link] of links.entries()) {
                let dom = await new Promise(async resolve => {
                    for (let check = 1; check <= 100; check++) {
                        let res = await fetch(link);
                        if (res.status == 304 || res.status == 200) {
                            let buffer = await res.arrayBuffer();
                            let decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                            let htmlText = decoder.decode(buffer);
                            let dom = fn.doc(htmlText);
                            resolve(dom);
                            break;
                        } else {
                            fn.showMsg(`第${page + 1}頁${res.status}重試第${check}次`, 2900);
                            await delay(3000);
                        }
                    }
                });
                let imgs = fn.gae("#picg img[alt]", dom);
                let te = fn.gae("#picg img[alt]").at(-1);
                imgs.forEach(e => {
                    imgsArr.push(e.cloneNode(true));
                    if (page != 0) insertAfter(te, e.cloneNode(true));
                });
                if (page != 0) {
                    let ce = fn.gae("h1,.page .pagelist");
                    let re = fn.gae("h1,.page .pagelist", dom);
                    if (ce.length == re.length) {
                        ce.forEach((e, i) => (e.outerHTML = re[i].outerHTML));
                    }
                }
                await delay(200);
            }
            return imgsArr;
        },
        button: [4],
        insertImg: ["#picg", 2],
        autoDownload: [0],
        next: "//div[@class='b' and contains(text(),'上一')]/a",
        prev: "//div[@class='b' and contains(text(),'下一')]/a",
        customTitle: () => fn.dt({
            s: "h1",
            d: [
                /第\d+页|^- /g,
                /[\s-]+P\.\d/g,
                /:/g
            ]
        }),
        topButton: true,
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        css: "#imgc img{margin:0px auto!important}#picg{max-width: 1110px!important;margin: 0 auto;}#picg img:hover{transform:none !important}#picg img{filter:blur(0px)!important}body>br,#apic,#bzs7,.interestline+center,center+#pic,#qpai,#d4a,#divone,#xzpap1,#divpsgx,#bdivpx,#divfts,#divftsp,#app+div,#xzappsq,div.bg-text,#divpsg,#divStayTopright2,#bdssy,#qrcode2>.erweima-text,#qrcode2>center,#qrcode2>center+div,#d5tig,#pcapicb,#google_translate_element,#d5a>*:not([id]):not([class]),.slide>a+div,.slide>img+div,#xtjpp,#divftst,.interestline+.nav~span,.interestline+.nav~br{display:none !important}",
        category: "nsfw2"
    }, {
        name: "魅狸图片网/美女私房照/看妹图",
        url: {
            h: [
                /rosi8\.com$/,
                /sfjpg\.(com|net)$/,
                /sfmm\.cc$/,
                /kanmeitu\.net$/,
                /kanmeitu1\.cc$/
            ],
            p: /^\/\w+\/\d+\.html$/,
            e: "#picg img"
        },
        init: () => {
            fn.gae(".b a").forEach(a => a.removeAttribute("target"));
            fn.gae("#picg a").forEach(a => (a.outerHTML = a.innerHTML));
        },
        imgs: () => {
            let [, max] = fn.gt(".pagelist span,.pagelist a[title=Page]").match(/\/(\d+)/);
            return fn.getImgO("#picg img", max, 9, null, 200, ".page .pagelist", siteUrl, 0);
        },
        button: [4],
        insertImg: ["#picg", 2],
        autoDownload: [0],
        next: "//div[@class='b' and contains(text(),'上一')]/a",
        prev: "//div[@class='b' and contains(text(),'下一')]/a",
        customTitle: "h1",
        topButton: true,
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        css: "#imgc img{margin:0px auto!important}#picg{max-width: 1110px!important;margin: 0 auto;}#picg img:hover{transform:none !important}#picg img{filter:blur(0px)!important}body>br,.interestline+center,center+#pic,#xzpap1,#divpsgx,#bdivpx,#divfts,#divftsp,#app+div,#xzappsq,div.bg-text,#divpsg,#divStayTopright2,#bdssy,#qrcode2>center,#d5tig,#pcapicb,#pcapic,#google_translate_element,#d5a>*:not([id]):not([class]),union[id]{display:none !important}",
        category: "nsfw2"
    }, {
        name: "六色美图",
        host: ["www.06se.com"],
        reg: /^https?:\/\/www\.06se\.com\/\d+\.html/,
        imgs: ".article-content img",
        button: [4],
        insertImg: [
            [".wp-posts-content", 2, ".wp-posts-content"], 2
        ],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: ".article-title",
        css: ".modal-open{overflow:unset!important;}",
        hide: "#modal-system-notice,.container.fluid-widget,#zibpay_modal,#mini-imgbox,.modal-backdrop",
        category: "nsfw1"
    }, {
        name: "秀图湾",
        host: ["www.okxx.de", "okxx.de"],
        reg: /^https?:\/\/(www\.)?okxx\.de\/\?thread-\d+\.htm$/,
        url: {
            h: ["www.okxx.de", "okxx.de", "www.xiusz.de", "xiusz.de", "www.aiyes.de", "aiyes.de"],
            s: "thread"
        },
        init: () => fn.createImgBox(".message p:has(>img)", 1),
        imgs: ".message img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".message p:has(>img)"], 2
        ],
        customTitle: ".media-body>h4",
        category: "nsfw1"
    }, {
        name: "女神部落",
        url: {
            h: "girlsteam.club"
        },
        imgs: "#content img",
        button: [4],
        insertImg: ["#content", 2],
        customTitle: ".item_title>h1",
        category: "nsfw1"
    }, {
        name: "丝袜客",
        host: ["siwake.cc"],
        reg: /^https?:\/\/siwake\.cc\/post\//,
        init: () => {
            let e = fn.ge(".Content>.newfujian");
            if (e) {
                tempEles.push(e);
            }
        },
        imgs: ".Content>a",
        button: [4],
        insertImg: [".Content", 2],
        endColor: "white",
        insertImgAF: (parent) => {
            if (tempEles.length > 0) {
                for (let e of tempEles) {
                    insertBefore(parent.firstChild, e);
                }
            }
        },
        autoDownload: [0],
        next: "a.fas",
        prev: "a.next.fas",
        customTitle: ".title",
        css: "@media only screen and (max-width:480px){#wrapper  .single{padding:0!important}}",
        category: "nsfw1"
    }, {
        name: "丝袜客 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/siwake\.cc\//,
        autoPager: {
            ele: "#main.gallery",
            observer: "#main.gallery>.thumb",
            next: "a.next.fas",
            re: ".pagelist"
        },
        openInNewTab: "#main.gallery a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "爱妹子",
        url: {
            h: ["xx.knit.bid", "mm.187187.xyz", "999888.best"],
            p: /^\/([\w-]+\/)?article\/\d+\//i,
            e: ".item-image img,#img-box img"
        },
        init: () => fn.clearAllTimer(2),
        imgs: async () => {
            await fn.getNP(".item-image", ".next-page>a", null, ".pagination");
            return fn.gae(".item-image img,#img-box img");
        },
        button: [4],
        insertImg: [
            [".item-image,#img-box", 2, ".item-image,#img-box"], 2
        ],
        customTitle: ".focusbox-title",
        css: "a{white-space:unset!important}",
        category: "nsfw1"
    }, {
        name: "爱妹子 反反廣告提示",
        url: {
            h: ["xx.knit.bid", "mm.187187.xyz", "999888.best"]
        },
        init: () => fn.clearAllTimer(2),
        openInNewTab: ".excerpts-wrapper a:not([target=_blank])",
        category: "ad"
    }, {
        name: "美女写真",
        url: {
            h: "portrait.knit.bid",
            p: /^\/\w+\/\d+$/,
            e: ".container>.container>img"
        },
        imgs: async () => {
            let max = fn.gt("//li[a[text()='下页']]", 2);
            let links = fn.arr(max, (v, i) => siteUrl + "?page=" + (i + 1));
            return fn.getImgA(".container>.container>img", links, 300);
        },
        button: [4],
        insertImg: [
            [".container>.container>nav", 2, "nav[aria-label=pagination],.img-fluid"], 2
        ],
        customTitle: ".container h1",
        category: "nsfw1"
    }, {
        name: "美图网",
        url: {
            h: "meitu.knit.bid",
            p: /^\/(beauty|handsome)\/[^\/]+$/,
            e: ".details_item>img"
        },
        imgs: async () => {
            let [max] = fn.gau("a[href*=gotoPage]").at(-2).match(/\d+/);
            let links = fn.arr(max, (v, i) => siteUrl + "?page=" + (i + 1));
            return fn.getImgA(".details_item>img", links, 300);
        },
        button: [4],
        insertImg: [".details_item", 2],
        customTitle: () => fn.gt(".text-center>h1").replace("|", "-"),
        category: "nsfw1"
    }, {
        name: "美图网",
        url: {
            h: "meitu.knit.bid",
            p: /^\/(news|street)\/\d+$/
        },
        imgs: ".news-body img",
        customTitle: () => fn.gt(".text-center>h1").replace("|", "-"),
        category: "nsfw1"
    }, {
        name: "萌图社",
        host: ["www.446m.com", "446m.com"],
        reg: /^https?:\/\/(www\.)?446m\.com\/index\.php\/\w+\/\d+\.html$/,
        include: ".post-content",
        imgs: "span.post-item",
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: () => document.title.slice(0, -6),
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "萌萝社",
        host: ["www.042l.com", "042l.com"],
        reg: /^https?:\/\/(www\.)?042l\.com\/\w+\/\d+\.html$/,
        include: "//a[text()='显示全文']",
        init: () => tempEles.push(fn.ge(".tags")),
        imgs: () => {
            let url = fn.gu("//a[text()='显示全文']");
            return fn.fetchDoc(url).then(dom => fn.gae("#lightgallery .boximg", dom));
        },
        button: [4],
        insertImg: ["#lightgallery", 2],
        insertImgAF: (parent) => parent.append(...tempEles),
        autoDownload: [0],
        next: "//a[text()='上一篇']",
        prev: "//a[text()='下一篇']",
        customTitle: ".focusbox-title",
        category: "nsfw1"
    }, {
        name: "日式JK旧版",
        host: ["v2.jk.rs"],
        reg: /^https?:\/\/v2\.jk\.rs\/\d+\/\d+\/\d+\/\d+\.html$/,
        imgs: "div[data-fancybox]",
        button: [4],
        insertImg: ["#masonry", 2],
        insertImgAF: () => fn.css("#masonry{position:unset!important;height:unset!important}"),
        customTitle: () => fn.title(" - 日式JK"),
        fancybox: {
            v: 3,
            css: false
        },
        referer: "",
        category: "nsfw1"
    }, {
        name: "日式JK新版",
        host: ["www.jk.rs"],
        reg: /^https?:\/\/www\.jk\.rs\/\d+\/\d+\/\d+\/\d+\.html$/,
        exclude: ".post-hide-content",
        imgs: "a.glightbox",
        button: [4],
        insertImg: [
            [".masonry-list", 2, ".masonry-list"], 2
        ],
        insertImgAF: () => fn.css("#masonry{position:unset!important;height:unset!important}"),
        customTitle: () => fn.title(" – 日式JK"),
        referer: "",
        category: "nsfw1"
    }, {
        name: "妹妹美",
        host: ["mmm.red"],
        reg: /^https?:\/\/(www\.)?mmm\.red\/art\/\d+$/,
        exclude: ".login-tip",
        imgs: "div[data-fancybox][data-src]",
        autoDownload: [0],
        next: "//div[text()='上一篇']/following-sibling::a",
        prev: "//div[text()='下一篇']/following-sibling::a",
        customTitle: ".post-info-text",
        category: "nsfw1"
    }, {
        name: "胴体的诱惑/美图吧",
        host: ["dongti.blog.2nt.com", "meituba.blog.2nt.com"],
        reg: [
            /^https?:\/\/dongti\.blog\.2nt\.com\/blog-entry-\d+.html$/,
            /^https?:\/\/meituba\.blog\.2nt\.com\/blog-entry-\d+.html$/
        ],
        imgs: ".inner-contents img",
        button: [4],
        insertImg: [".inner-contents", 2],
        autoDownload: [0],
        next: "//a[div[@class='pager_entry-box next-justify']]",
        prev: "//a[div[@class='pager_entry-image-prev']]",
        customTitle: "#entry-title",
        category: "nsfw1"
    }, {
        name: "好圖屋",
        host: ["www.haotuwu.com", "m.haotuwu.com"],
        reg: /^https?:\/\/(www|m)\.haotuwu\.com\/\w+\/\d+(\/page\/\d+)?(\.html)?$/,
        include: ".suoyou",
        init: () => {
            let url = location.href;
            if (/\/page\/\d+/.test(url)) location.href = location.href.replace(/\/page\/\d+/, "");
            let a = fn.ge("#showimg a:has(img),.img-box a:has(img)");
            if (a) a.outerHTML = a.innerHTML;
        },
        imgs: () => {
            let [, max] = fn.gt(".suoyou").match(/\d+\/(\d+)/);
            let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl.replace(".html", "") + "/page/" + (i + 1) + ".html")
            return fn.getImgA("#showimg img,.img-box img", links, 2);
        },
        button: [4],
        insertImg: ["#showimg,.img-box", 2],
        autoDownload: [0],
        next: "//div[contains(text(),'上一篇')]/a | //span[contains(text(),'上一篇')]/following-sibling::a[1]",
        prev: "//div[contains(text(),'下一篇')]/a | //span[contains(text(),'下一篇')]/following-sibling::a[1]",
        customTitle: ".showtitle>h2,.imgTitle-name",
        hide: "#imgshow .flow-box:nth-child(n+1):nth-child(-n+2),union",
        category: "nsfw1"
    }, {
        name: "秀色女神",
        host: ["www.xsnvshen.co"],
        reg: /^https?:\/\/www\.xsnvshen\.(co|com)\/album\/\d+/,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("img[id^='imglist'][data-original]");
            return thumbnailSrcArray.map(e => e.replace("thumb_600x900/", ""));
        },
        button: [4],
        insertImg: ["//li[img[@id='bigImg']]", 2],
        customTitle: "h1",
        css: ".workShow li img{max-width:100%!important}",
        referer: "url",
        category: "nsfw1"
    }, {
        name: "秀色女神M",
        host: ["m.xsnvshen.co"],
        reg: /^https?:\/\/m\.xsnvshen\.(co|com)\/album\/\d+/,
        imgs: async () => {
            let [max] = fn.gt(".pg_current").match(/\d+$/);
            thumbnailSrcArray = await fn.getImg("#arcbox img.lazy", max, 6);
            return thumbnailSrcArray.map(e => e.replace("thumb_600x900/", ""));
        },
        button: [4],
        insertImg: [
            ["#arcbox", 0, "//div[@id='arcbox']/p[img]"], 2
        ],
        customTitle: "h1>a",
        css: "#arcbox img{margin:unset;min-width:unset}",
        referer: "url",
        category: "nsfw1"
    }, {
        name: "秀色女神news",
        host: ["www.xsnvshen.co", "m.xsnvshen.co"],
        reg: /^https?:\/\/(www|m)\.xsnvshen\.co\/news\/\d+/,
        imgs: "#arcbox img",
        button: [4],
        insertImg: [
            ["#arcbox>*:first-child", 1, "//p[img]"], 2
        ],
        customTitle: "h1",
        css: "#arcbox img{margin:unset;min-width:unset}",
        referer: "url",
        category: "nsfw1"
    }, {
        name: "优图坊",
        host: ["www.anfn.cc"],
        reg: /^https?:\/\/www\.anfun\.cc\/\d+\.html$/,
        imgs: "img[bigimg]",
        button: [4],
        insertImg: [".picshow", 2],
        customTitle: ".piccontext h2",
        category: "nsfw1"
    }, {
        name: "Secret Home",
        host: ["poiblog.com"],
        reg: /^https:\/\/poiblog\.com\/archives\//,
        imgs: ".post-content img",
        customTitle: ".post-title",
        category: "nsfw1"
    }, {
        name: "HotAsiaGirl分頁模式",
        url: {
            h: "hotgirl.asia",
            e: [".galeria_img", ".pagination"]
        },
        imgs: () => fn.getImgA(".galeria_img>img", ".pagination a[href]"),
        button: [4],
        insertImg: [".mx-auto", 1],
        customTitle: "h3",
        hide: ".galeria_img",
        category: "nsfw2"
    }, {
        name: "HotAsiaGirl幻燈片模式",
        url: {
            h: "hotgirl.asia"
        },
        imgs: "#carouselImageIndicators img",
        button: [4],
        insertImg: [".mx-auto", 2],
        customTitle: "h3",
        hide: ".galeria_img",
        category: "nsfw2"
    }, {
        name: "HotGirl World",
        host: ["www.hotgirl2024.com"],
        reg: /^https?:\/\/www\.hotgirl2024\.com\/g\/\w+\.html\//,
        imgs: () => fn.getImg(".article__image-list img", fn.gt(".pagination__total") || 1),
        button: [4],
        insertImg: [".article__image-list", 2],
        go: 1,
        customTitle: ".article-header__title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "HotGirl World 分類自動翻頁",
        enable: 1,
        reg: [
            /^https?:\/\/www\.hotgirl2024\.com\/(\?page=\d+)?$/,
            /^https?:\/\/www\.hotgirl2024\.com\/(category|agency|tag)\/\d+\.html\/(\?page=\d+)?$/,
            /^https?:\/\/www\.hotgirl2024\.com\/search\.html\/\?(page=\d+&)?q=/
        ],
        init: () => fn.gae(".blur-image").forEach(e => e.classList.remove("blur-image")),
        autoPager: {
            ele: ".articles-grid",
            next: ".pagination__item--active+a",
            re: ".pagination",
            lazySrc: "img[data-src]",
            pageNum: ".pagination__item--active",
            aF: () => _this.init(),
            bottom: screen.height * 2
        },
        openInNewTab: ".articles-grid a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "MaoJiuJiu/SkyBird/TightImg/SexCity",
        url: {
            h: ["www.maojiujiu.com", "www.skybirdx.com", "www.tightimg.com", "www.sexscity.com"],
            p: "/album/",
            e: "#item_list img"
        },
        imgs: () => fn.getImgA("#item_list img", ".pager>a:not(.current)"),
        capture: () => _this.imgs(),
        customTitle: "h1.title",
        setFancybox: "#item_list a:has(>img)",
        category: "nsfw1"
    }, {
        name: "Photos XTAPO",
        url: {
            h: "photos.xtapo.org",
            p: /^\/[^\/]+\/$/
        },
        init: () => fn.createImgBox(".dynamic-entry-content .code-block", 1),
        imgs: ".dynamic-entry-content img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".dynamic-entry-content .code-block,.dynamic-entry-content .code-block~*"], 2
        ],
        customTitle: "article h2",
        category: "nsfw1"
    }, {
        name: "Pibys",
        url: {
            h: "pibys.win",
            e: ".page-links"
        },
        init: () => fn.createImgBox(".entry-content img", 1),
        imgs: () => fn.getImgA(".entry-content img", ".page-links a"),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#FullPictureLoadMainImgBox~*"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Pibys",
        url: {
            h: "pibys.com",
            p: "/threads/"
        },
        init: () => fn.createImgBox(".btnSummary", 1),
        imgs: ".divSummary img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".btnSummary,.divSummary,.w3-row-padding:has(>div>.w3-margin-bottom),.w3-container:has(>.pagination)"], 2
        ],
        customTitle: "#posttitle",
        category: "nsfw1"
    }, {
        name: "1Y Beauties",
        host: ["www.1y.is"],
        reg: /^https?:\/\/www\.1y\.is\/[\w-]+\/[^\.]+\.html$/,
        imgs: () => fn.getImgA(".entry-content img", ".page-links a"),
        capture: () => _this.imgs(),
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "BeautyLeg",
        host: ["www.beautyleg6.com"],
        reg: /^https?:\/\/www\.beautyleg6\.com\/\w+\/\d+\/\d+\.html/i,
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".page a").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".contents img[alt]", max, 9);
        },
        button: [4],
        insertImg: [".contents", 2],
        autoDownload: [0],
        next: ".pre>a",
        prev: ".next>a",
        customTitle: ".content>h1",
        css: ".content .contents img{max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "BeautyLegM",
        host: ["m.beautyleg6.com"],
        reg: /^https?:\/\/m\.beautyleg6\.com\/view\.php\?aid=\d+/,
        imgs: async () => {
            let links = fn.arr(_unsafeWindow.totalpage, (v, i) => i == 0 ? siteUrl : siteUrl + "&pageno=" + (i + 1));
            return fn.getImgA("#bigImg", links);
        },
        button: [4],
        insertImg: [".show-simg", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("a.f-r.l3");
            return next ? next.href : null;
        },
        prev: 1,
        customTitle: ".showcontbt>h1",
        category: "nsfw1"
    }, {
        name: "Asianude4u",
        host: ["www.asianude4u.net"],
        reg: /^https?:\/\/www\.asianude4u\.net\/.+\/.+\/(#small-1)?$/,
        exclude: "//a[@rel='category tag' and text()='Videos'] | //a[@rel='category tag' and text()='Madonna-AV']",
        imgs: () => fn.ge(".wp-block-image a[href*=attachment_id]") ? fn.gae(".wp-block-image img[data-id]") : fn.gae(".wp-block-image>a,.mgl-img-container>a,.gallery a").map(e => e.href),
        button: [4],
        //insertImg: ["//li[img[@id='bigImg']]", 1],
        insertImg: [
            ["div.entry>*:last-child", 2], 2
        ],
        go: 1,
        customTitle: "h1.entry-title",
        css: "@media only screen and (max-width:409px){.entry{width:100%!important}}button.rmp_menu_trigger{z-index:100!important}",
        hide: ".single-box,.entry-img-300",
        category: "nsfw1"
    }, {
        name: "NICEGIRL4U",
        host: ["nicegirl4u.cyou"],
        reg: /^https?:\/\/nicegirl4u\.cyou\/[^\/]+\/$/,
        include: ".wp-block-image>img",
        init: () => fn.remove(".ads_custom"),
        imgs: async () => {
            let pag = fn.ge(".page-links");
            if (pag) {
                let max = fn.gt(".page-links>a:last-child");
                return fn.getImg(".wp-block-image>img", max, 14);
            } else {
                return fn.gae(".wp-block-image>img");
            }
        },
        capture: () => _this.imgs(),
        //button: [4],
        //insertImg: [
        //[".responsive-tabs-wrapper,.entry-meta", 2], 2
        //],
        //insertImgAF: () => fn.gae("figure.wp-block-image").forEach(e => (e.outerHTML = "")),
        go: 1,
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Nudegirls4u",
        host: ["nudegirls4u.com"],
        reg: /^https?:\/\/nudegirls4u\.com\/[^\/]+\/$/,
        imgs: ".rgg-imagegrid>a",
        button: [4],
        insertImg: [".rgg-container", 2],
        customTitle: ".entry-title",
        css: ".rgg-imagegrid{height:auto!important}",
        category: "nsfw1"
    }, {
        name: "Chinese Beauties",
        host: ["sxchinesegirlz.one"],
        url: {
            e: "//p[@class='gridlane-site-title']/a[text()='Chinese Beauties']",
            p: /^\/[^\/]+\/$/
        },
        imgs: () => fn.getImgA(".wp-block-image img", ".page-links>a"),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "爱看 INS",
        host: ["www.ikanins.com"],
        reg: /^https?:\/\/www\.ikanins\.com\/[\w-]+\//,
        imgs: "img[srcset]",
        button: [4],
        insertImg: [
            [".entry-content", 0, "//p[img]"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Jablehk",
        host: ["jablehk.com"],
        url: {
            h: "jablehk.com"
        },
        imgs: ".gallery-strips-lightbox-link>img[data-src]",
        thums: "figure.gallery-strips-item",
        button: [4],
        insertImg: [
            [".gallery-strips-wrapper", 2, ".gallery-strips-wrapper"], 2, 2000
        ],
        autoDownload: [0],
        next: ".item-pagination-link--next",
        prev: ".item-pagination-link--prev",
        go: 1,
        customTitle: "h1>strong",
        category: "nsfw1"
    }, {
        name: "True Pic",
        host: ["truepic.net"],
        reg: /^https?:\/\/truepic\.net\/[\w-]+\/$/,
        include: "//div[@class='entry-content']//p[img]",
        init: () => fn.createImgBox("//p[img]", 1),
        imgs: () => fn.getImgA("//p/img", ".pagination_split_post a"),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//p[img]"], 2
        ],
        go: 1,
        customTitle: ".entry-content h2",
        category: "nsfw1"
    }, {
        name: "TangMoc",
        host: ["tangmoc.com"],
        reg: /^https?:\/\/tangmoc\.com\/blog\/show\/\w+\/.+/,
        init: () => fn.remove("//span[@id='install-pwa-box'] | //div[@class='row mt-3'] | //div[ins[@class='adsbygoogle']] | //div[@class='mt-3'][@id] | //div[@class='row my-5'] | //iframe[@id]"),
        imgs: () => fn.ge(".btn-warning+.btn-secondary") ? fn.getImgA("a[href*=media]>.media-preview", "a.btn-secondary") : fn.gae("a[href*=media]>.media-preview"),
        button: [4],
        insertImg: ["//media[article]", 2],
        go: 1,
        customTitle: () => fn.dt({
            s: "h1",
            d: [
                "View - ",
                /[\s-]+$/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "TangMoc去廣告",
        host: ["tangmoc.com"],
        reg: /^https?:\/\/tangmoc\.com\//,
        init: () => fn.addMutationObserver(() => fn.remove("//span[@id='install-pwa-box'] | //div[@class='row mt-3'] | //div[ins[@class='adsbygoogle']] | //div[@class='mt-3'][@id] | //div[@class='row my-5'] | //iframe[@id]")),
        category: "ad"
    }, {
        name: "Fapello",
        host: ["fapello.com"],
        reg: /^https?:\/\/fapello\.com\/[^\/]+\/$/,
        init: async () => {
            if (fn.ge("#showmore")) {
                let ele = fn.ge("#showmore");
                let max = ele.dataset.max;
                let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl + `page-${i + 1}/`);
                tempEles = await fn.getEle(links, "#content>div");
            } else {
                tempEles = fn.gae("#content>div");
            }
        },
        imgs: () => {
            let imgSrcs = tempEles.map(node => {
                if (fn.ge("img[src*='icon-play.svg']", node)) {
                    let videoSrc = fn.ge("img", node).src.replace("https://fapello.com/", "https://cdn.fapello.com/").replace("_300px", "").replace(/\.jpg$/i, ".mp4");
                    videoSrcArray.push(videoSrc);
                    return null;
                } else {
                    thumbnailSrcArray.push(fn.ge("img", node).src);
                    let imgSrc = fn.ge("img", node).src.replace("_300px", "");
                    return imgSrc;
                }
            }).filter(item => item).sort();
            thumbnailSrcArray.sort();
            videoSrcArray.sort();
            return imgSrcs;
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["#content", 3],
        insertImgAF: () => {
            fn.run("jQuery(window).off()");
            fn.remove("#showmore,#next_page");
        },
        customTitle: () => fn.dt({
            t: fn.title("/", 1),
            d: " - Fapello"
        }),
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "Fapello.su",
        host: ["fapello.su"],
        reg: /^https?:\/\/fapello\.su\/[^\/]+\/$/,
        init: async () => {
            const $ = _unsafeWindow.jQuery;
            let total = Number(fn.gt("//div[strong[text()='Media']]").match(/\d+/)[0]); //媒體總數
            console.log("媒體總數", total);
            const model_bid = fn.lp.replaceAll("/", "");
            let ele = fn.ge("#showmore");
            let max = ele.dataset.max;
            fn.showMsg(displayLanguage.str_05, 0);
            let ajaxNum = 0;
            let resArr = fn.arr(max, (v, i) => new Promise(resolve => {
                $.ajax({
                    url: `/ajax/model_new/${model_bid}/page-${i + 1}/photos`,
                    dataType: "html",
                    success: (data) => {
                        fn.showMsg(`${displayLanguage.str_06}${ajaxNum+=1}/${max}`, 0);
                        resolve(data);
                    }
                });
            }));
            let tempDom1;
            let picNum;
            await Promise.all(resArr).then(async arr => {
                await delay(1000);
                fn.hideMsg();
                ajaxNum = 0;
                let html = "";
                arr.forEach(str => (html += str));
                tempDom1 = fn.doc(html);
                picNum = [...tempDom1.images].length; //圖片數量
                console.log("圖片數量", picNum);
                thumbnailSrcArray = [...tempDom1.images].map(e => e.dataset.src);
                console.log("縮圖地址", thumbnailSrcArray);
            });
            let videoNum = total - picNum;
            let videoPages = Math.ceil(videoNum / 16);
            fn.showMsg(displayLanguage.str_05, 0);
            let resArr2 = fn.arr(videoPages, (v, i) => new Promise(resolve => {
                $.ajax({
                    url: `/ajax/model_new/${model_bid}/page-${i + 1}/videos`,
                    dataType: "html",
                    success: (data) => {
                        fn.showMsg(`${displayLanguage.str_06}${ajaxNum+=1}/${videoPages}`, 0);
                        resolve(data);
                    }
                });
            }));
            let tempDom2;
            await Promise.all(resArr2).then(async arr => {
                await delay(1000);
                fn.hideMsg();
                ajaxNum = 0;
                let html = "";
                arr.forEach(str => (html += str));
                tempDom2 = fn.doc(html);
                let videoUrls = fn.gae("iframe.saint-iframe", tempDom2).map(e => e.src);
                console.log("iframeVideoUrls", videoUrls);
                fn.showMsg(displayLanguage.str_05, 0);
                let getVideoUrlsArr = videoUrls.map((url, i, arr) => {
                    return fn.xhrDoc(url).then(dom => {
                        fn.showMsg(`${displayLanguage.str_06}${ajaxNum+=1}/${arr.length}`, 0);
                        return fn.ge("source[type]", dom)?.src ?? null;
                    });
                });
                await Promise.all(getVideoUrlsArr).then(async mp4Arr => {
                    await delay(1000);
                    mp4Arr = mp4Arr.filter(item => item);
                    fn.hideMsg();
                    console.log("MP4地址", mp4Arr);
                    videoSrcArray = mp4Arr;
                });
            });
        },
        imgs: () => thumbnailSrcArray.map(e => e.replace(".md.", ".")),
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["#content", 3],
        insertImgAF: () => {
            fn.run("scrollMore=()=>{};");
            fn.remove("#showmore,#next_page,.content-action-buttons");
        },
        downloadVideo: true,
        customTitle: ".container h2",
        category: "nsfw2"
    }, {
        name: "Fapachi",
        host: ["fapachi.com"],
        reg: /^https?:\/\/fapachi\.com\/[^\/]+$/,
        imgs: async () => {
            if (captureSrcArray.length) return captureSrcArray;
            let medias = Number(fn.gt("//p[contains(text(),'Media')]").match(/\d+/)[0]);
            if (medias > 24) {
                let max = Math.ceil(medias / 24);
                let links = fn.arr(max, (v, i) => siteUrl + "/page/" + (i + 1));
                thumbnailSrcArray = await fn.getImgA(".model-media-prew img", links).then(arr => arr.filter(src => src.includes("/models/")).sort());
                return thumbnailSrcArray.map(e => e.replace("/300px/", "/full/").replace("_300px", ""));
            } else {
                thumbnailSrcArray = fn.getImgSrcArr(".model-media-prew img").filter(src => src.includes("/models/")).sort();
                return thumbnailSrcArray.map(e => e.replace("/300px/", "/full/").replace("_300px", ""));
            }
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["//div[div[contains(@class,'model-media-prew')]]", 3],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "Faponic/Fapellas",
        host: ["faponic.com", "fapellas.com"],
        reg: /^https?:\/\/(faponic\.com|fapellas\.com)\/[^\/]+\/$/,
        init: async () => {
            if (fn.ge("#showmore")) {
                let ele = fn.ge("#showmore");
                let max = ele.dataset.max;
                let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl + `page-${i + 1}/`);
                tempEles = await fn.getEle(links, ".photo-item>img");
            } else {
                tempEles = fn.gae(".photo-item>img");
            }
        },
        imgs: () => tempEles.map(e => e.src).sort(),
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["#content", 3],
        insertImgAF: () => {
            fn.run("scrollMore=()=>{};");
            fn.remove("#showmore,#next_page");
        },
        customTitle: ".author-content>a",
        category: "nsfw2"
    }, {
        name: "Fapullo",
        host: ["fapullo.com"],
        reg: /^https?:\/\/fapullo\.com\/[^\/]+\/$/,
        init: async () => {
            if (fn.ge("#load_more")) {
                let ele = fn.ge("#load_more");
                let max = ele.dataset.max;
                let links = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl + `page-${i + 1}/`);
                tempEles = await fn.getEle(links, ".thumb_img");
            } else {
                tempEles = fn.gae(".thumb_img");
            }
        },
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(tempEles).sort();
            return thumbnailSrcArray.map(e => e.replace("_400px", ""));
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["#media", 3],
        insertImgAF: () => {
            fn.run("scrollMore=()=>{};");
            fn.remove("#load_more");
        },
        customTitle: () => fn.title("/", 1),
        category: "nsfw2"
    }, {
        name: "#TheFappening",
        url: {
            h: "fap.thefappening.one",
            p: /^\/[^\/]+\/$/,
            e: ".entry-title"
        },
        imgs: ".gallery-item a[target]",
        customTitle: () => fn.gt(".entry-title").replaceAll("/", "-"),
        category: "nsfw2"
    }, {
        name: "The Fappening Plus",
        host: ["thefappening.plus"],
        reg: /^https?:\/\/thefappening\.plus\/[^\/]+\/$/,
        imgs: async () => {
            await fn.getNP(".gallery__item", "//a[text()='Next']", null, ".fusion-meta-info");
            thumbnailSrcArray = fn.gae(".gallery_thumb").map(e => e.src).reverse();
            return thumbnailSrcArray.map(e => e.replace(/_s(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: () => fn.gt(".entry-title").replaceAll("/", "-"),
        category: "nsfw2"
    }, {
        name: "TheFappening",
        host: ["thefappeningblog.com"],
        reg: /^https?:\/\/thefappeningblog\.com\/[^\/]+\/(#more-\d+)?$/,
        include: "//a[noscript][not(@class)]",
        imgs: "//a[noscript]",
        button: [4],
        insertImg: [
            ["//a[noscript]", 2, "//a[noscript]"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "TheFappening",
        host: ["thefappeningblog.com"],
        reg: /^https?:\/\/thefappeningblog\.com\/gallery\/[^\/]+\/$/,
        imgs: async () => {
            await fn.getNP(".item_content", ".nav-next>a", null, ".nav-single");
            thumbnailSrcArray = fn.gae(".item_img>img").map(e => e.src).reverse();
            return thumbnailSrcArray.map(e => e.replace(/_\d+px(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.gt(".entry-title").replaceAll("/", "-"),
        category: "nsfw2"
    }, {
        name: "Fapomania",
        host: ["fapomania.com"],
        reg: /^https?:\/\/fapomania\.com\/[^\/]+\/$/,
        init: () => fn.createImgBox(".previzakosblo", 2),
        imgs: async () => {
            const last = (dom) => !fn.ge(".leftocontar .previzako", dom);
            await fn.getNP(".leftocontar .previzako", "//a[contains(text(),'Next')]", last, ".morebutaro");
            thumbnailSrcArray = fn.gae(".leftocontar .previzakoimag>img:not([src$='leaks.png'])").map(e => e.src).reverse();
            return thumbnailSrcArray.map(e => e.replace(/_\d+px(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".leftocontar .previzakosblo,.morebutaro"], 2
        ],
        customTitle: () => fn.gt(".leftocontar>h1").replaceAll("/", "-"),
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "nsfw2"
    }, {
        name: "NudoStar.TV",
        host: ["nudostar.tv"],
        reg: /^https?:\/\/nudostar\.tv\/models\/[^\/]+\/$/,
        imgs: async () => {
            await fn.getNP("#list_videos_common_videos_list_items>.item", ".next>a", null, "#list_models_models_list_pagination");
            thumbnailSrcArray = fn.gae("#list_videos_common_videos_list img.thumb").map(e => e.src).reverse();
            return thumbnailSrcArray.map(e => e.replace(/_\d+px(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [".list-videos", 2],
        customTitle: () => fn.gt(".headline>h1").replaceAll("/", "-"),
        hide: ".zkido_div",
        category: "nsfw2"
    }, {
        name: "Nudogram",
        host: ["nudogram.com"],
        reg: /^https?:\/\/nudogram\.com\/models\/[^\/]+\/$/,
        imgs: async () => {
            await fn.getNP("#list_videos_common_videos_list_items>.item", "//li[span]/following-sibling::li[1]/a", null, ".pagination");
            thumbnailSrcArray = fn.gae("#list_videos_common_videos_list div.img>img").map(e => e.src).reverse();
            return thumbnailSrcArray.map(e => e.replace(/_\d+(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [".list-videos", 2],
        customTitle: () => fn.gt(".headline>h2").replaceAll("/", "-"),
        category: "nsfw2"
    }, {
        name: "HentaiDude TV",
        host: ["hentaidude.tv"],
        link: "https://hentaidude.tv/category/cosplay/",
        reg: /^https?:\/\/hentaidude\.tv\/[\w-]+\/[^\/]+\/$/,
        include: [
            ".entry-content a.swipebox",
            ".entry-title"
        ],
        imgs: ".post-thumb img,.entry-content a.swipebox",
        customTitle: ".entry-title",
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "Hotleaks/Thotsbay/Hotleak/Leakedzone/BestThots/Thotporn",
        host: ["hotleaks.tv", "thotsbay.tv", "hotleak.vip", "leakedzone.com", "bestthots.com", "thotporn.tv"],
        reg: () => /^https?:\/\/(hotleaks\.tv|thotsbay\.tv|hotleak\.vip|leakedzone\.com|bestthots\.com|thotporn\.tv)\/[\w\.-]+(\/photo)?$/i.test(fn.url) && !/^\/home/.test(fn.lp),
        init: () => {
            if (location.href.split("/").length === 4 && !fn.lh.includes("bestthots")) {
                location.href = location.href + "/photo";
            } else {
                EClick("#photos-tab");
            }
        },
        imgs: async () => {
            if (/\/photo/.test(location.href)) fn.clearAllTimer();
            let ptext = fn.gt("#photos-tab");
            let [, m] = ptext.match(/\(([\d\.K]+)\)/);
            let num;
            if (/\./.test(m) && /K/.test(m)) {
                num = (Number(m.replace(/\.|K/g, "")) + 1) * 100;
            } else if (/K/.test(m)) {
                num = Number(m.replace(/K/g, "")) * 1000 + 100;
            } else {
                num = Number(m);
            }
            let pages = Math.ceil(num / 48);
            let actorName = siteUrl.split("/")[3];
            let imgsSrcArr = [];
            let fetchNum = 0;
            fn.showMsg(displayLanguage.str_05, 0);
            for (let i = 1; i <= pages; i++) {
                let json = await fetch(`/${actorName}?page=${i}&type=photos&order=0`, {
                    "headers": {
                        "x-requested-with": "XMLHttpRequest"
                    }
                }).then(res => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${pages}`, 0);
                    return res.json();
                });
                if (json.length == 0) break;
                let images;
                if (fn.lh == "leakedzone.com") {
                    images = json.map(e => e.thumbnail.replace("_300.", "."));
                } else if (fn.lh == "bestthots.com") {
                    images = json.map(e => e.image);
                } else {
                    images = json.map(e => e.player);
                }
                let thumbnails = json.map(e => e.thumbnail);
                imgsSrcArr = imgsSrcArr.concat(images);
                thumbnailSrcArray = thumbnailSrcArray.concat(thumbnails);
                if (json.length < 48) break;
            }
            return imgsSrcArr;
        },
        button: [4],
        insertImg: ["#photos", 3],
        customTitle: ".actor-name>h1,.actor-title-port",
        category: "nsfw2"
    }, {
        name: "Hot Girl Pix",
        host: ["www.hotgirlpix.com"],
        reg: /^https?:\/\/www\.hotgirlpix\.com\/p\//,
        imgs: () => fn.getImgA("article img", "#singlePostPagination a", 300),
        button: [4],
        insertImg: ["article", 2],
        customTitle: "#singlePostTitle",
        hide: "#modalAdblock,.alignCenter,.gcseSearchPlaceHolder",
        category: "nsfw1"
    }, {
        name: "Hot Girl Pix AD",
        host: ["www.hotgirlpix.com"],
        reg: /^https?:\/\/www\.hotgirlpix\.com\//,
        hide: "#modalAdblock",
        category: "ad"
    }, {
        name: "自拍图库",
        host: ["自拍图库.com", "zipaipic.com"],
        url: {
            t: "自拍图库",
            p: /\/content_\d+\.html$/
        },
        init: () => fn.clearAllTimer(),
        imgs: ".showimg",
        button: [4],
        insertImg: ["#imgviewer", 2],
        go: 1,
        autoDownload: [0],
        next: "//a[text()='下一组']",
        prev: "//a[text()='上一组']",
        customTitle: () => fn.gt({
            s: ".ttle",
            d: /\n|\d+p/gi
        }),
        referer: "",
        hide: "a[rel]",
        category: "nsfw2"
    }, {
        name: "美拍 - 我自拍",
        host: ["5zipai.com", "7aipai.com", "9zipai.net", "global.3zipai.net"],
        url: {
            h: "zipai",
            p: /^\/selfies\/\d+\/\d+\.html$/
        },
        init: () => fn.clearAllTimer(),
        imgs: async () => {
            await fn.waitEle("#showCon img");
            videoSrcArray = fn.gae("#showCon video").map(e => /\.mp4/.test(e.src) ? e.src : null).filter(item => item);
            thumbnailSrcArray = fn.gae("#showCon img").map(e => /zipai/.test(e.src) ? e.src.replace(/&w=\d+/, "&w=100") : null).filter(item => item);
            return fn.gae("#showCon img").map(e => /zipai/.test(e.src) ? e.src.replace(/&output.+/, "") : null).filter(item => item);
        },
        button: [4],
        insertImg: ["#showCon", 2],
        go: 1,
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: 1,
        customTitle: ".item_title>h1",
        referer: "",
        css: ".content_left img{cursor:unset}",
        hide: ".affs",
        category: "nsfw2"
    }, {
        name: "52自拍",
        host: ["shaonvtu.xyz"],
        url: {
            h: "shaonvtu.xyz",
            s: "albums"
        },
        imgs: ".images img",
        button: [4],
        insertImg: [".images", 2],
        customTitle: ".content h1",
        category: "nsfw2"
    }, {
        name: "吃瓜大队",
        host: ["cgdd.net"],
        reg: /^https?:\/\/cgdd\.net\/\d+\.html$/i,
        imgs: () => {
            videoSrcArray = fn.gae(".article-content video>source").map(e => e.src);
            return fn.gae(".article-content img");
        },
        capture: () => _this.imgs(),
        customTitle: ".article-title>a",
        setFancybox: ".article-content img",
        downloadVideo: true,
        hide: ".m-navbar~*:not([id^=Full],[class^='fancybox'],.viewer-container)",
        category: "nsfw2"
    }, {
        name: "套圖TAOTU.ORG",
        host: ["taotu.org"],
        reg: /^https?:\/\/(\w{2}\.)?taotu\.org\/[\w-]+\//,
        include: "a[data-fancybox=gallery]",
        imgs: "a[data-fancybox=gallery]",
        thums: "a[data-fancybox=gallery] img",
        button: [4],
        insertImg: [
            ["#wrapper-footer", 2], 2
        ],
        autoDownload: [0],
        next: ".next a",
        prev: ".prev a",
        customTitle: ".suit_title>h1",
        go: 1,
        hide: "#right-bottom,#ad,.ad",
        category: "nsfw2"
    }, {
        name: "福利乐园",
        host: ["www.fulily.com"],
        reg: /^https?:\/\/www\.fulily\.com\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: ".article-content img",
        button: [4],
        insertImg: [".article-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev a",
        prev: ".article-nav-next a",
        customTitle: ".article-title",
        category: "nsfw2"
    }, {
        name: "Taotuxp.com/www.taotucd.com",
        host: ["www.taotucc.com", "www.taotucd.com"],
        reg: /^https?:\/\/www\.taotuc(c|d)\.com\/\d+\.html/,
        imgs: () => fn.getImg("#post_content img[alt]", fn.gt(".pagelist>*:last-child"), 7),
        button: [4],
        insertImg: ["#post_content", 1],
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: "h1",
        category: "nsfw1"
    }, {
        name: "美图海",
        url: {
            h: "www.meituhai.com",
            p: "/album/"
        },
        exclude: ".vip-tip",
        imgs: "#gallery img",
        button: [4],
        insertImg: ["#gallery", 2],
        customTitle: ".home_title",
        category: "nsfw1"
    }, {
        name: "美推网",
        url: {
            h: [/meinvtui\.com$/, "bbs.2tu.me"],
            p: ".html",
            e: ".pp.hh,.contimglist"
        },
        imgs: () => {
            let max = fn.gt(".pages>a,.page a").match(/\d+/g).at(-1);
            max = Number(max);
            return fn.getImg(".pp.hh img[alt],.contimglist img[alt]", max, 9);
        },
        button: [4],
        insertImg: [".pp.hh,.contimglist", 2],
        autoDownload: [0],
        next: "//b[text()='上一篇:']/following-sibling::a | //a[@class='f-l l2'][@href]",
        prev: "//b[text()='下一篇:']/following-sibling::a | //a[@class='f-l l3'][@href]",
        customTitle: ".des>h1,.contmbx-title",
        category: "nsfw1"
    }, {
        name: "推图网",
        reg: /^https?:\/\/(www|m)\.tuiimg\.com\/meinv\/\d+\//,
        link: "https://m.tuiimg.com/meinv/",
        init: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.url.replace("www.tuiimg.com", "m.tuiimg.com");
            await fn.xhrDoc(url, {
                headers: {
                    "Referer": url,
                    "User-Agent": Mobile_UA
                }
            }).then(dom => {
                let [, , , max, , next] = JSON.parse(fn.gst("_pd", dom).match(/_pd[\s=]+([^;]+)/)[1]);
                let [path] = fn.ge("#content img", dom).src.match(/.+\//);
                globalImgArray = fn.arr(max, (v, i) => path + (i + 1) + ".jpg");
                if (isNumber(next)) {
                    tempNextLink = fn.url.replace(/\d+/, next);
                }
            });
        },
        imgs: () => globalImgArray,
        button: [4],
        insertImg: ["#content", 2],
        autoDownload: [0],
        next: () => tempNextLink,
        prev: 1,
        customTitle: "#main>h1,.main>h1",
        hide: "#page",
        category: "nsfw1"
    }, {
        name: "18AV",
        url: {
            h: "18av.mm-cg.com",
            e: ["//script[contains(text(),'Large_cgurl')]", ".sel_enlarge_page,.sel_enlarge"]
        },
        imgs: () => _unsafeWindow.Large_cgurl,
        button: [4],
        insertImg: ["#show_cg_html,#showcg_container", 2],
        customTitle: ".archive-title>h1,h1",
        hide: ".ut1_img_content",
        category: "nsfw1"
    }, {
        name: "Xgirls",
        host: ["xgirlscollection.com", "img3xgirls.com"],
        reg: /^https?:\/\/(xgirlscollection\.com|img3xgirls\.com)\/(collection|album)\/\d+/,
        imgs: () => fn.getImg("img[id].collection-image,.album-image[data-pin-media]", (fn.gt(".pagination>*:last-child", 2) || 1)),
        button: [4],
        insertImg: ["//div[img[@data-pin-url]]", 1],
        customTitle: ".container>h1",
        category: "nsfw1"
    }, {
        name: "SexyAsianGirl",
        host: ["www.sexyasiangirl.xyz"],
        reg: /^https?:\/\/www\.sexyasiangirl\.xyz\/album\/\d+\.html/,
        init: () => fn.remove("//article/div[a[img]]"),
        imgs: () => fn.getImg("img.block", fn.gt("//a[text()='Next']", 2) || 1),
        button: [4],
        insertImg: ["//div[img[@title]]", 2],
        customTitle: "header>h2",
        category: "nsfw2"
    }, {
        name: "尤物丧志/HotAsianX/色图/亚色图库/福利姬美图/秀人图/UGIRLS/mm131美女图片/酱图图/極品妹子圖/爽图吧/涩图社/美乳小姐姐写真/三上悠亚写真图片/AHottie/CoserGirl",
        url: {
            h: [
                /^youwu\./,
                /^hotasianx\./,
                /^setu\./,
                /^yase\./,
                /^fuligirl\./,
                /^xiurentu\./,
                /^ugirls\./,
                "mm131.click",
                /jtttututu/,
                "jipin.pics",
                "stuba.netlify.app",
                "setushe.pics",
                "meiru.neocities.org",
                "sanshang.neocities.org",
                "cosergirl.neocities.org",
                /ahottie/
            ],
            e: ["img.block", "//div[img[@title]]", "#main>h1,header>h1"]
        },
        imgs: () => fn.getImg("img.block", fn.gt("a[rel=next]", 2) || 1),
        button: [4],
        insertImg: ["//div[img[@title]]", 2],
        next: "//span[contains(text(),'上一篇')]/following-sibling::a[1]",
        customTitle: () => fn.dt({
            s: "#main>h1,header>h1",
            d: [
                /\(\d+[\w\s\\\/\.+-/]+\)?|\[\d+[\w\s\\\/\.+-/]+\]?|(\d+[\w\s\\\/\.+-/]+)?|【\d+[\w\s\\\/\.+-/]+】?|\d+P/gi,
                /\s?\d+P\+?\d+V/,
                /未分类性感写真|^.+人体|AI图区/,
                /(\d+月\d+打赏群(自购)?资源)/gi,
                /🐾/g
            ]
        }),
        hide: "div.flex.m-1:has(>a[style]),.my-2:has(>a[target][referrerpolicy][style]),iframe[id][class][width][height][style]",
        category: "nsfw2"
    }, {
        name: "胴体的秘密/CosPlayer/AsianSexyBody/国模人体写真图片/福利图库",
        host: ["dongti.netlify.app", "cosplayer.neocities.org", "asiansexybody.netlify.app", "guomo.neocities.org", "fulituku.neocities.org"],
        url: {
            h: /netlify\.app|neocities\.org/,
            p: "/posts/"
        },
        imgs: "#gallery img",
        button: [4],
        insertImg: ["#gallery", 2],
        autoDownload: [0],
        next: "//span[text()='Prev:']/following-sibling::a[1]",
        prev: "//span[text()='Next:']/following-sibling::a[1]",
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "浪女吧",
        host: ["langnv.neocities.org"],
        reg: /^https?:\/\/langnv\.neocities\.org\/posts\/\d+\/$/,
        imgs: "#images img",
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: "#prevpost>a",
        prev: "#nextpost>a",
        customTitle: ".title",
        category: "nsfw2"
    }, {
        name: "色图喵",
        host: ["setumeow.com"],
        reg: /^https?:\/\/setumeow\.com\/p\//,
        imgs: ".gallery img",
        button: [4],
        insertImg: [".gallery", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "美图鉴赏/美图鉴赏ACG",
        host: ["www.lspimg.com", "acg.lspimg.com"],
        reg: /^https?:\/\/(www|acg)\.lspimg\.com\/archives\/\d+/,
        imgs: "div[data-src]",
        button: [4],
        insertImg: ["#masonry", 2],
        customTitle: () => fn.lh === "www.lspimg.com" ? fn.title(" - 美图鉴赏") : null,
        css: "#masonry{position:unset!important;height:unset!important}",
        hide: "#popup",
        category: "nsfw2"
    }, {
        name: "秀人图吧",
        host: ["www.502x.com"],
        reg: /^https?:\/\/www\.502x\.com\/\w+\/\d+\.html/,
        //imgs: () => fn.getImg("#image_div img", (fn.gt("a.prev", 2) || 1), 9),
        imgs: () => fn.getImgA("#content img", ".post_au>a"),
        button: [4],
        insertImg: ["#image_div", 2],
        customTitle: ".item_title>h1",
        css: ".image_div a img{cursor:unset}",
        hide: ".affs",
        category: "nsfw1"
    }, {
        name: "VVCON美瞳网",
        url: {
            h: "www.vvcon.cn",
            p: /^\/\d+\.html$/,
            e: "//a[@class='post-list-cat-item b2-radius'][contains(text(),'Cosplay图集')]"
        },
        imgs: ".talk_pic img",
        button: [4],
        insertImg: [".talk_pic", 2],
        customTitle: ".entry-header>h1",
        category: "nsfw1"
    }, {
        name: "VVCON美瞳网",
        url: {
            h: "www.vvcon.cn",
            p: /^\/\d+\.html$/,
            e: "//a[@class='post-list-cat-item b2-radius'][contains(text(),'Cosplay图集')]"
        },
        imgs: ".entry-content p:has(>img)>img",
        button: [4],
        insertImg: [
            [".entry-content p:has(>img)", 1, ".entry-content p:has(>img)"], 2
        ],
        customTitle: ".entry-header>h1",
        category: "nsfw1"
    }, {
        name: "HoeHot",
        url: {
            h: "hoehot.com",
            p: "/gallery/"
        },
        imgs: async () => {
            fn.createImgBox(".infinite-scroll-component__outerdiv", 1);
            if (captureSrcArray.length > 0) {
                fn.clearAllTimer();
                return captureSrcArray;
            }
            fn.showMsg(displayLanguage.str_05, 0);
            let srcs = [];
            let [, , galleryId] = fn.lp.split("/");
            let cursorId = "";
            let loop = true;
            const getData = (cid, gid) => fetch(`/api/model-media?cursor=${cid}&galleryId=${gid}`).then(res => res.json()).then(json => {
                const num = json.medias.length;
                if (num > 0) {
                    cursorId = json.medias.at(-1).id;
                    json.medias.forEach(e => {
                        thumbnailSrcArray.push(e.urlThumb);
                        srcs.push(e.url);
                    });
                }
                if (num < 30 || num === 0) {
                    loop = false;
                }
            });
            while (loop) {
                await getData(cursorId, galleryId);
            }
            fn.clearAllTimer();
            return srcs;
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".infinite-scroll-component__outerdiv:has(.container-img)"], 3
        ],
        customTitle: "main .my-1>h1",
        openInNewTab: ".infinite-scroll-component a:not([target=_blank])",
        hide: "main a[rel]",
        category: "nsfw2"
    }, {
        name: "HoeHot 清除無用請求",
        url: {
            h: "hoehot.com"
        },
        init: () => fn.addMutationObserver(() => setTimeout(() => fn.clearAllTimer(), 2000)),
        openInNewTab: ".infinite-scroll-component a:not([target=_blank])",
        hide: "main a[rel]",
        category: "none"
    }, {
        name: "OSOSEDKI",
        host: ["ososedki.com"],
        reg: /^https?:\/\/ososedki\.com\/([a-z]{2}\/)?photos\//,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("a[data-fancybox] img").sort((a, b) => a.match(/(\d+)\.\w+$/)[1] - b.match(/(\d+)\.\w+$/)[1]);
            return fn.gau("a[data-fancybox]").sort((a, b) => a.match(/(\d+)\.\w+$/)[1] - b.match(/(\d+)\.\w+$/)[1]);
        },
        button: [4],
        insertImg: ["//div[div[@id='masonry']]", 2],
        customTitle: () => fn.ge("//meta[@property='og:description']").content,
        category: "nsfw2"
    }, {
        name: "COSPLAYASIAN/COSPLAYTHOTS/COSPLAYRULE34/WAIFUBITCHES/COSPLAY BOOBS/COSPLAYLEAKS/VIPTHOTS/HENTAI BITCHES/LEAKSFANS/CHARMINGASS/LEAKS PIE/CHERRY LEAKS/SWEETLEAKS/OCOSPLAY/WEB CHARMING/COSPLAY KITTYS/TITSPIE/COSPLAY SOSEDKI",
        url: {
            h: [
                "cosplayasian.com",
                "cosplaythots.com",
                "cosplayrule34.com",
                "waifubitches.com",
                "cosplayboobs.com",
                "cosplayleaks.com",
                "vipthots.com",
                "hentaibitches.com",
                "leaksfan.com",
                "charmingass.com",
                "leakspie.com",
                "cherryleaks.com",
                "sweetleaks.com",
                "ocosplay.com",
                "webcharming.com",
                "cosplaykittys.com",
                "titspie.com",
                "cosplaysosedki.com"
            ],
            p: ["/gallery/", /\/photos?\//, "/picture/", "/album/", "/post/", "/image/", "/img/", /\/pics?\//, "/p/", "/g/"]
        },
        init: () => fn.createImgBox(".grid,div.row:has(>.bg-dark)", 2),
        imgs: "a[data-fancybox],.grid-item>img,.grid-item->img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".grid,div.row:has(>.bg-dark)"], 2
        ],
        customTitle: () => fn.ge("h1.text-uppercase:not(.mt-2)").textContent.replace(/^[\w\s]+:/i, "").trim(),
        hide: "noindex:has(>div>center),div:has(>center>noindex)",
        category: "nsfw2"
    }, {
        name: "NudoStar",
        url: {
            h: "nudostar.com",
            p: /^\/[^\/]+\//,
            e: [".pagination-single", "//p/a[img]"]
        },
        init: () => fn.createImgBox(".pagination-single", 1),
        imgs: () => {
            videoSrcArray = fn.gae("video.wp-video-shortcode>source").map(e => e.src);
            return fn.gae("//p/a[img]");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//p[a[img]] | //div[@class='wp-video']"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: "a.previous-post",
        prev: "a.next-post",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "TNApics",
        host: ["www.tnapics.com"],
        reg: /^https:\/\/www\.tnapics\.com\/[\w-]+\/$/,
        imgs: "a[data-fslightbox]",
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "Fapdungeon",
        host: ["fapdungeon.com"],
        reg: /^https?:\/\/fapdungeon\.com\/\w+\/[^\/]+\/$/,
        include: ".entry-content img.size-full",
        init: () => fn.addMutationObserver(() => fn.remove("div[class][style*='z-index']")),
        imgs: () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            return fn.gae(".entry-content img.size-full").map(e => e.src);
        },
        capture: () => _this.imgs(),
        customTitle: ".entry-title",
        referer: "https://fapdungeon.com/",
        setFancybox: ".entry-content img",
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "Ibradome",
        host: ["ibradome.com"],
        reg: /^https?:\/\/ibradome\.com\/\w+\/photos\/\d+\//i,
        imgs: () => {
            let url = fn.gu("a.gallery-view");
            return fn.fetchDoc(url).then(dom => fn.gau("a.ohidden", dom));
        },
        capture: () => _this.imgs(),
        customTitle: ".art-title",
        category: "nsfw2"
    }, {
        name: "Fapopedia",
        url: {
            h: "fapopedia.net",
            p: /^\/[^\/]+\/$/,
            e: "a[name='photos']"
        },
        init: () => fn.createImgBox(".shrt-blk", 2),
        imgs: async () => {
            await fn.getNP("//h2[i]/following-sibling::div[1][@class='shrt-blk']/div", "//a[text()='Next ']", null, ".nv-blk");
            thumbnailSrcArray = fn.gae("//h2[i]/following-sibling::div[1][@class='shrt-blk']//img").map(e => e.src).sort();
            return fn.getImgA(".lrg-pc>a", "//h2[i]/following-sibling::div[1][@class='shrt-blk']//a").then(arr => arr.sort());
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//h2[i]/following-sibling::div[1][@class='shrt-blk']|//div[@class='nv-blk']"], 2
        ],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "gotanynudes.com",
        host: ["gotanynudes.com"],
        reg: /^https?:\/\/gotanynudes\.com\/[^\/]+\/$/i,
        imgs: () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            return fn.getImgSrcset(".entry-content  img");
        },
        capture: () => _this.imgs(),
        customTitle: ".entry-title",
        downloadVideo: true,
        setFancybox: ".entry-content img",
        referer: "https://gotanynudes.com/",
        category: "nsfw2"
    }, {
        name: "Thotslife.com",
        host: ["thotslife.com"],
        reg: /^https?:\/\/thotslife\.com\/[^\/]+\/$/i,
        imgs: () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            return fn.getImgSrcset(".entry-content img");
        },
        capture: () => _this.imgs(),
        customTitle: ".entry-title",
        downloadVideo: true,
        setFancybox: ".entry-content img",
        referer: "https://thotslife.com/",
        category: "nsfw2"
    }, {
        name: "Nude Cosplay Albums",
        url: {
            h: "nudecosplaygirls.com",
            p: /^\/[^\/]+\/$/
        },
        imgs: ".entry-content img.msacwl-img,#post img,.gallery-item img,figure.wp-block-image img",
        button: [4],
        insertImg: [".entry-content,#post", 2],
        customTitle: ".entry-title",
        css: ".entry-content>img{width:auto!important;height:auto!important;max-width:100%!important;display:block!important;margin:0 auto !important}#secondary{display:none!important}h1.g1-mega{text-align:center}",
        category: "nsfw2"
    }, {
        name: "Jizz to Nude Girls",
        url: {
            h: "jizzy.org",
            p: /^\/[^\/]+\/$/,
            e: ".entry-content img"
        },
        imgs: () => fn.getImgSrcArr(".entry-content img").filter(src => !src.includes("18xmob")),
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "VoyeurFlash.com",
        host: ["voyeurflash.com"],
        reg: /^https?:\/\/voyeurflash\.com\/[^\/]+\/$/,
        imgs: () => {
            let [eos, ets] = [".gallery_thumb,.wp-block-image>a>img:not([srcset])", ".wp-block-image>img[srcset]"];
            let eo = fn.ge(eos);
            let et = fn.ge(ets);
            if (!!eo) {
                return fn.gae(eos);
            } else if (!!et) {
                return fn.getImgSrcset(ets);
            } else {
                return [];
            }
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "Leaked Models",
        host: ["leakedmodels.com"],
        reg: /^https?:\/\/leakedmodels\.com\/[^\/]+\/$/,
        include: "//a[span[@class='faux-button'][text()='View']][@class='more-link']",
        init: () => fn.createImgBox("#site-content", 2),
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("img.size-large").sort();
            let links = fn.gau("//a[span[@class='faux-button'][text()='View']][@class='more-link']");
            return fn.getImgA("img.wp-image", links).then(arr => arr.sort());
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "ThotHD Albums / Thothub Albums",
        host: ["thothd.com", "thothub.to", "thothub.lol"],
        reg: [
            /^https?:\/\/thothd\.com\/([a-z]{2}\/)?albums\/\d+\/[^\/]+\/$/,
            /^https?:\/\/thothub\.(to|lol)\/albums\/\d+\/[^\/]+\/$/
        ],
        include: "a[data-fancybox-type]",
        imgs: "a[data-fancybox-type]",
        thums: "a[data-fancybox-type] .thumb",
        button: [4],
        insertImg: [".images", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "The Hentai World",
        link: "https://thehentaiworld.com/hentai-cosplay-images/",
        url: {
            h: "thehentaiworld.com",
            p: /^\/[^\/]+\/[^\/]+\/$/,
            e: "#miniThumbContainer"
        },
        init: () => fn.createImgBox("#miniThumbContainer", 2),
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("#miniThumbContainer img[itemprop='thumbnail']");
            return thumbnailSrcArray.map(e => e.replace(/-\d+x\d+(\.\w+)/, "$1"));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#miniThumbContainer,#doujin,div.ad"], 2
        ],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "Cosplayers GoneWild",
        host: ["cosplayersgonewild.net"],
        reg: /^https?:\/\/cosplayersgonewild\.net\/albums\/\d+\/$/,
        init: async () => {
            await fn.waitEle("#main-carousel-list img");
            fn.createImgBox(".grid", 2);
        },
        imgs: "#main-carousel-list img",
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: "h1.text-3xl",
        category: "nsfw1"
    }, {
        name: "奈奈COS",
        host: ["www.nncos.com"],
        reg: /^https?:\/\/(www\.)?nncos\.com\/\d+\.html$/,
        imgs: ".entry-content img",
        referrerpolicy: "no-referrer",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: "Coser:"
        }),
        category: "nsfw1"
    }, {
        name: "Gallery Epic",
        host: ["galleryepic.com"],
        reg: /^https?:\/\/galleryepic\.com\/(zh|en)\/(cosplay|album)\/\d+$/,
        init: async () => {
            await fn.waitEle("img[variant='thumbnail']");
            await fn.wait(() => {
                let button = fn.ge("//button[text()='加载更多' or text()='More']");
                if (!!button) {
                    EClick(button);
                }
                return !button;
            });
        },
        imgs: "img[variant='thumbnail']",
        button: [4],
        insertImg: ["//div[@class='flex flex-col items-center'][div[div[a[img]]]] | //div[@class='flex flex-col items-center'][div[div[img]]]", 2],
        customTitle: ".justify-between h2",
        category: "nsfw1"
    }, {
        name: "Gallery Epic Cosplays 分類自動翻頁",
        reg: /^https?:\/\/galleryepic\.com\/(zh|en)\/cosplays\/\d+$/,
        autoPager: {
            ele: ".grid:has(>.relative)",
            observer: ".grid>.relative",
            next: "a[aria-label='Go to next page']:not([tabindex])",
            re: "nav[role=navigation]",
            showTitle: 0,
            bF: (dom) => {
                fn.gae(".animate-pulse", dom).forEach(e => {
                    e.nextSibling.className = "h-auto w-auto object-cover transition-all hover:scale-105 aspect-[3/4]";
                    e.nextSibling.dataset.src = e.nextSibling.src;
                    e.remove();
                });
            },
            aF: (dom) => {
                let last = fn.gae(".grid:has(>.relative)").at(-1);
                fn.gae("img[data-src]", last).forEach(img => {
                    img.src = loading_bak;
                    fn.imagesObserver.observe(img);
                });
            }
        },
        category: "autoPager"
    }, {
        name: "Gallery Epic cosers 分類自動翻頁",
        reg: /^https?:\/\/galleryepic\.com\/(zh|en)\/cosers\/\d+\??$/,
        autoPager: {
            ele: ".grid:has(>.flex)",
            observer: ".grid>.flex",
            next: "a[aria-label='Go to next page']:not([tabindex])",
            re: "nav[role=navigation]",
            showTitle: 0,
            bF: (dom) => {
                fn.gae(".animate-pulse", dom).forEach(e => {
                    e.nextSibling.removeAttribute("class");
                    e.nextSibling.dataset.src = e.nextSibling.src;
                    e.remove();
                });
            },
            aF: (dom) => {
                let last = fn.gae(".grid:has(>.flex)").at(-1);
                fn.gae("img[data-src]", last).forEach(img => {
                    img.src = loading_bak;
                    fn.imagesObserver.observe(img);
                });
            }
        },
        category: "autoPager"
    }, {
        name: "Gallery Epic Coser 分類自動翻頁",
        reg: /^https?:\/\/galleryepic\.com\/(zh|en)\/coser\/\d+\/\d+\??$/,
        autoPager: {
            ele: ".grid:has(>.relative)",
            observer: ".grid>.relative",
            next: "a[aria-label='Go to next page']:not([tabindex])",
            re: "nav[role=navigation]",
            showTitle: 0,
            bF: (dom) => {
                fn.gae(".animate-pulse", dom).forEach(e => {
                    e.nextSibling.className = "h-auto w-auto object-cover transition-all hover:scale-105 aspect-[3/4]";
                    e.nextSibling.dataset.src = e.nextSibling.src;
                    e.remove();
                });
            },
            aF: (dom) => {
                let last = fn.gae(".grid:has(>.relative)").at(-1);
                fn.gae("img[data-src]", last).forEach(img => {
                    img.src = loading_bak;
                    fn.imagesObserver.observe(img);
                });
            }
        },
        category: "autoPager"
    }, {
        name: "Nude Bird/Nude Cosplay",
        url: {
            h: ["nudebird.biz", "nudecosplay.biz"],
            p: /^\/[^\/]+\/$/,
            e: "//p[a[img]]",
        },
        init: () => {
            let video = fn.ge(".online-video");
            if (video) {
                let x = fn.ge("//p[a[img]]");
                fn.gae(".online-video").forEach(e => insertBefore(x, e));
            }
        },
        imgs: ".thecontent a,.content-inner>p>a",
        button: [4],
        insertImg: ["//p[a[img]]", 2],
        customTitle: () => fn.dt({
            s: "h1",
            d: "nudecosplay.biz"
        }),
        category: "nsfw1"
    }, {
        name: "Cosplaytele",
        url: {
            h: "cosplaytele.com",
            p: /^\/[^/]+\/$/,
        },
        imgs: "figure.gallery-item a",
        button: [4],
        insertImg: [".gallery", 2],
        endColor: "white",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "Cosplay18",
        url: {
            h: "cosplay18.pics",
            p: /^\/[^/]+\/$/,
        },
        imgs: ".single-page img",
        button: [4],
        insertImg: [
            [".single-page", 0, ".single-page>ul"], 2
        ],
        endColor: "white",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "Sexy Asian Model Pics",
        url: {
            h: "www.sexyasianmodelpics.com",
            p: "/album/",
        },
        init: () => {
            let ps = fn.gae(".entry-content>p");
            if (ps.length > 0) {
                ps.forEach(p => {
                    let img = fn.ge("img", p);
                    if (!img) {
                        tempEles.push(p.cloneNode(true));
                    }
                });
            }
        },
        imgs: () => fn.getImgA(".pcontent-imgbox>img", ".post-links>a"),
        button: [4],
        insertImg: [".entry-content", 2],
        insertImgAF: (parent) => {
            if (tempEles.length > 0) {
                for (let e of tempEles) {
                    insertBefore(parent.firstChild, e);
                }
            }
        },
        autoDownload: [0],
        next: ".post-pre a",
        prev: ".post-nextv a",
        customTitle: ".entry-header>h1",
        category: "nsfw1"
    }, {
        name: "Erohere",
        url: {
            h: "erohere.online",
            p: /^\/erohere\d+\/$/,
        },
        init: () => fn.createImgBox("#album_masonry", 2),
        imgs: async () => {
            const getImgSrcs = imgArr => imgArr.map(img => fn.lo + img.getAttribute("srcset").split(",")[0].replace(/\s{1,2}\d+w$/, ""));
            let piclinks;
            let pages = fn.ge(".pagelist");
            if (pages) {
                let max = fn.gt(".pagelist .next", 2);
                let pagelinks = fn.arr(max, (v, i) => i == 0 ? fn.lp : fn.lp + (i + 1));
                let albumE = await fn.getEle(pagelinks, "#album_masonry");
                thumbnailSrcArray = albumE.map(e => fn.getImgSrcArr("img", e))?.flat();
                piclinks = albumE.map(e => fn.gau("a", e))?.flat();
            } else {
                thumbnailSrcArray = fn.getImgSrcArr("#album_masonry img");
                piclinks = fn.gau("#album_masonry a");
            }
            let imgE = await fn.getEle(piclinks, ".img_responsive>img");
            return getImgSrcs(imgE);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#album_masonry,.pagelist-container"], 2
        ],
        customTitle: ".album_head>h1",
        hide: ".download-container",
        category: "nsfw1"
    }, {
        name: "yoel.uno",
        reg: /^https?:\/\/yoel\.uno\/[^\/]+\/$/,
        include: "a[href*='vipr.im']",
        imgs: () => {
            let links = fn.gau("a[href*='vipr.im']");
            return fn.getImageHost(links);
        },
        eye: 0,
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "JimmysOnline.com",
        host: ["www.jimmysonline.com"],
        reg: /^https?:\/\/www\.jimmysonline\.com\/[^\/]+\/$/,
        include: "a.aigpl-img-link[data-mfp-src]",
        imgs: () => fn.gae("a.aigpl-img-link[data-mfp-src]").map(a => a.dataset.mfpSrc),
        button: [4],
        insertImg: [".aigpl-gallery", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "gaidam18",
        host: ["gaidam18.com"],
        reg: /^https?:\/\/gaidam18\.com\/[^\/]+\/$/,
        include: "figure.gallery-item,.entry-content>div>a[href*='blogger'],.entry-content img[src*='/wp-content/uploads/']",
        imgs: () => {
            if (fn.ge(".gallery-item img")) {
                return fn.gae(".gallery-item img");
            } else if (fn.ge(".entry-content>div>a[href*='blogger']")) {
                return fn.gae(".entry-content>div>a[href*='blogger']").map(a => {
                    let url = a.href;
                    let urlArr = url.split("/");
                    urlArr[urlArr.length - 2] = "s16000";
                    return urlArr.join("/");
                });
            } else if (fn.ge(".entry-content img[src*='/wp-content/uploads/']")) {
                return fn.gae(".entry-content img[src*='/wp-content/uploads/']");
            } else {
                return [];
            }
        },
        button: [4],
        insertImg: [".gallery,.entry-content", 2],
        customTitle: () => fn.dt({
            s: "h1.entry-title",
            d: "Ảnh sex "
        }),
        hide: "[class^='float']",
        category: "nsfw2"
    }, {
        name: "Game-happy-life",
        url: {
            h: "gamehappylife.top",
            p: /^\/[^\/]+\/$/,
            e: "figure.wp-block-image"
        },
        imgs: () => fn.getImgA("figure.wp-block-image>a,figure.wp-block-image>img", ".page-links>a"),
        button: [4],
        insertImg: ["figure.wp-block-image", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: "h1.entry-title",
        category: "nsfw1"
    }, {
        name: "XikXak",
        url: {
            h: "www.xikxak.com",
            p: /^\/\d+$/
        },
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: "h1.entry-title",
        category: "nsfw1"
    }, {
        name: "Xiunice.com/4kero",
        url: {
            h: ["xiunice.com", "4kero.com"]
        },
        init: () => fn.createImgBox(".wp-block-gallery", 1),
        imgs: ".wp-block-gallery img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".wp-block-gallery"], 2
        ],
        autoDownload: [0],
        next: ".nav-previous .prev>a",
        prev: ".nav-previous .next>a",
        customTitle: "h1.tdb-title-text,h1.entry-title",
        category: "nsfw2"
    }, {
        name: "Cosplay69",
        host: ["www.cosplay69.net", "cosplay69.net"],
        url: () => fn.checkUrl({
            h: "cosplay69.net",
            p: /^\/[^\/]+\/$/,
            e: "//a[@rel='category tag'][text()='Album']"
        }) && !["sssins.com", "nicezzz.com"].some(t => document.documentElement.innerText.includes(t)),
        init: async () => {
            await fn.waitEle(".entry-content img");
            fn.addMutationObserver(() => {
                document.documentElement.style.overflow = "";
                document.body.classList.remove("has-header-ad", "tie-popup-is-opend");
                fn.remove("#tie-popup-adblock");
            });
            let iframe = fn.ge(".iframe-container,iframe[scrolling]");
            if (iframe) {
                let x = fn.ge(".entry-content");
                fn.gae(".iframe-container,iframe[scrolling]").forEach(e => insertBefore(x, e));
            }
            if (fn.ge(".gallery")) {
                fn.createImgBox(".gallery", 1);
            } else {
                fn.createImgBox(".entry-content p:has(>img),.entry-content ul", 1);
            }
        },
        imgs: () => fn.fetchDoc(fn.url).then(dom => fn.gae("a[data-fancybox],.gallery-item a,.entry-content img[alt]:not(.crp_thumb,[src*='/banner'])", dom)),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".gallery,.entry-content p:has(>img:not(.crp_thumb)),.entry-content ul"], 2
        ],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "Cosplay69",
        reg: /^https?:\/\/(www\.)?cosplay69\.net\//,
        init: () => {
            fn.addMutationObserver(() => {
                document.documentElement.style.overflow = "";
                document.body.classList.remove("has-header-ad", "tie-popup-is-opend");
                fn.remove("#tie-popup-adblock");
            });
        },
        category: "ad"
    }, {
        name: "X Cosplay",
        host: ["xcosplay.top"],
        reg: /^https?:\/\/xcosplay\.top\/[^\/]+\/$/,
        init: () => fn.createImgBox("p:has(>.g1-img-wrap)", 2),
        imgs: () => fn.gae(".g1-img-wrap>img").map(e => e.src.replace(/-\d+x\d+\.jpg$/, ".jpg")),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "p:has(>.g1-img-wrap)"], 2
        ],
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: "h1.entry-title",
        category: "nsfw1"
    }, {
        name: "Ero Cosplay",
        host: ["www.erocosplay.org"],
        reg: /^https?:\/\/www\.erocosplay\.org\/[^\/]+\/$/,
        include: "#reader",
        init: () => fn.waitEle("#reader img"),
        imgs: () => {
            let textCode = fn.gst("pages").match(/pages[\s=]+([^;]+)/)[1].replaceAll("\n", "");
            return fn.run(textCode);
        },
        button: [4],
        insertImg: ["#reader", 2],
        insertImgAF: () => {
            document.removeEventListener("keydown", _unsafeWindow.handleKeyboardEvent);
        },
        autoDownload: [0],
        next: () => {
            let selector = `[data-href="${fn.url}"]`;
            let currentE = fn.ge(selector);
            let next = currentE?.nextElementSibling;
            if (next?.nodeName === "OPTION") {
                return next.dataset.href;
            } else {
                return null;
            }
        },
        prev: 1,
        customTitle: ".entry-title",
        css: "#reader{width:auto!important;height:auto!important}",
        hide: "#mode,#botmenureader,.popSc",
        category: "nsfw1"
    }, {
        name: "Ero Cosplay AAD",
        host: ["www.erocosplay.org"],
        reg: /^https?:\/\/www\.erocosplay\.org\//,
        hide: ".popSc",
        category: "ad"
    }, {
        name: "CG Cosplay",
        host: ["cgcosplay.org"],
        reg: /^https?:\/\/cgcosplay\.org\/\d+\/$/,
        include: [
            ".gallery",
            ".gallery a",
            ".elementor-heading-title"
        ],
        //exclude: "//a[text()='Login' or text()='Log in here']",
        init: () => {
            let video = fn.ge(".fluid_video_wrapper");
            if (video) {
                let x = fn.ge(".gallery");
                fn.gae(".fluid_video_wrapper").forEach(e => insertBefore(x, e));
            }
        },
        imgs: ".gallery .gallery-item a:has(>img:not([src$='/banner']))",
        //button: [4],
        //insertImg: [".gallery", 3],
        //autoDownload: [0],
        next: ".nav-previous a[rel=prev]",
        prev: ".nav-next a[rel=next]",
        customTitle: ".elementor-heading-title",
        hide: "#page+[id][class]:has(.adblock_title),.code-block",
        category: "nsfw1"
    }, {
        name: "CG Cosplay AAD",
        reg: /^https?:\/\/cgcosplay\.org\//,
        hide: "#page+[id][class]:has(.adblock_title)",
        category: "ad"
    }, {
        name: "Asupan",
        host: ["asupan.art", "www.korenime.org"],
        reg: /^https?:\/\/(asupan\.art|www\.korenime\.org)\/id\/\d+$/,
        init: () => fn.createImgBox(".gallery", 2),
        imgs: ".gallery img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".gallery"], 2
        ],
        customTitle: "h1>span",
        category: "nsfw1"
    }, {
        name: "AsiaOnTop",
        host: ["asiaontop.com", "asiaon.top"],
        reg: /^https?:\/\/(asiaontop\.com|asiaon\.top)\/[^\/]+\/$/,
        include: ".modula-items",
        init: () => fn.addMutationObserver(() => fn.remove("#mdpDeblocker-css")),
        imgs: "a[data-image-id]",
        button: [4],
        insertImg: [
            [".modula-items", 2, ".modula-items"], 2
        ],
        autoDownload: [0],
        next: "a#prepost",
        prev: "a#nextpost",
        customTitle: () => fn.gt(".single_post_title_main").replace(":", " -"),
        go: 1,
        category: "nsfw2"
    }, {
        name: "AsiaOnTop",
        reg: /^https?:\/\/(asiaontop\.com|asiaon\.top)\//,
        init: () => fn.addMutationObserver(() => fn.remove("#mdpDeblocker-css")),
        css: "[data-aos^=fade][data-aos^=fade]{opacity:1!important;transition-property:unset!important}[data-aos=fade-up]{transform:unset!important}",
        hide: ".mdpDeblocker-wrapper,.mdpDeblocker-blackout.active",
        category: "ad"
    }, {
        name: "Mitaku",
        url: {
            h: "mitaku.net",
            e: "a.msacwl-img-link[data-mfp-src]"
        },
        imgs: () => fn.ge("a.msacwl-img-link[data-mfp-src]") ? fn.gae("a.msacwl-img-link[data-mfp-src]").map(a => a.dataset.mfpSrc).slice(1, -1) : fn.gae(".msacwl-img").slice(1, -1),
        button: [4],
        insertImg: [
            [".article-content", 2], 2
        ],
        go: 1,
        autoDownload: [0],
        next: ".previous>a",
        prev: ".next>a",
        customTitle: () => fn.dt({
            s: "h1.entry-title",
            d: /.[\smitaku]{6,7}\.net./
        }),
        category: "nsfw2"
    }, {
        name: "EroAsian",
        url: {
            h: "eroasian.net",
            p: /^\/photo-set\//
        },
        init: () => {
            let info = fn.ge(".wp-block-group");
            if (info) {
                let te = fn.ge(".cm-entry-summary");
                insertBefore(te, info);
            }
        },
        exclude: "a.msacwl-img-link",
        imgs: () => fn.getImgA(".cm-entry-summary img", ".pagination a"),
        button: [4],
        insertImg: [".cm-entry-summary", 2],
        autoDownload: [0],
        next: ".previous>a",
        prev: ".next>a",
        customTitle: ".cm-entry-title",
        category: "nsfw2"
    }, {
        name: "EroAsian",
        url: {
            h: "eroasian.net",
            p: "/photo-set/",
            e: "a.msacwl-img-link"
        },
        init: () => {
            let info = fn.ge(".wp-block-group");
            if (info) {
                let te = fn.ge(".cm-entry-summary");
                insertBefore(te, info);
            }
            fn.createImgBox(".cm-entry-summary", 0);
        },
        imgs: () => fn.gae("a.msacwl-img-link[data-mfp-src]").map(a => {
            if (/^http/.test(a.dataset.mfpSrc)) {
                return a.dataset.mfpSrc;
            } else {
                return fn.lo + a.dataset.mfpSrc;
            }
        }).slice(1, -1),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        go: 1,
        autoDownload: [0],
        next: ".previous>a",
        prev: ".next>a",
        customTitle: ".cm-entry-title",
        category: "nsfw2"
    }, {
        name: "Byoru",
        host: ["byoru.net"],
        reg: /^https?:\/\/byoru\.net\/[^\/]+\/$/,
        init: () => {
            let eles = fn.gae("//p[contains(text(),'Download')] | //p[contains(text(),'Password')]");
            if (eles.length > 0) {
                let x = fn.ge(".s-post-content");
                for (let e of eles) {
                    insertBefore(x, e);
                }
            }
        },
        imgs: () => {
            if (fn.ge(".msacwl-slide>a")) {
                return fn.gae(".msacwl-slide>a").map(a => a.dataset.mfpSrc).sort((a, b) => a.match(/(\d+)\.\w+$/)[1] - b.match(/(\d+)\.\w+$/)[1]);
            } else if (fn.ge("figure.wp-block-image img[data-src]")) {
                return fn.gae("figure.wp-block-image img[data-src]").map(e => e.dataset.src.replace(/-\d+x\d+(\.\w+)/, "$1")).sort((a, b) => {
                    try {
                        return a.match(/(\d+)\.\w+$/)[1] - b.match(/(\d+)\.\w+$/)[1];
                    } catch {
                        try {
                            return a.match(/\((\d+)\)\.\w+$/)[1] - b.match(/\((\d+)\)\.\w+$/)[1];
                        } catch {
                            return a;
                        }
                    }
                });
            } else if (fn.ge(".galeria_img>img")) {
                return fn.gae(".galeria_img>img");
            } else if (fn.ge(".s-post-content img[title][data-lazyloaded]")) {
                return fn.gae(".s-post-content img[title][data-lazyloaded]").map(e => e.src);
            } else if (fn.ge(".s-post-content img")) {
                return fn.gae(".s-post-content img");
            } else {
                return [];
            }
        },
        capture: () => _this.imgs(),
        //button: [4],
        //insertImg: [".s-post-content", 2],
        autoDownload: [0],
        next: "a.next-page-link",
        prev: "a.prev-page-link",
        customTitle: () => fn.dt({
            s: "h1.entry-title",
            d: /Byoru – | \(Cosplay\)/g
        }),
        category: "nsfw1"
    }, {
        name: "Hình ảnh gái",
        url: {
            h: "hinhanhgai.com"
        },
        SPA: () => ["/image/", "/article/"].some(p => document.URL.includes(p)),
        observerURL: true,
        imgs: () => {
            if (document.URL.includes("/image/")) {
                let id = document.URL.split("/").at(-1);
                fn.showMsg(displayLanguage.str_05, 0);
                return fetch(`/api/photo/${id}`).then(res => res.json()).then(json => {
                    fn.hideMsg();
                    return json.files.map(e => e.full_url);
                });
            } else if (document.URL.includes("/article/")) {
                return fn.gae(".content img");
            } else {
                return [];
            }
        },
        capture: () => _this.imgs(),
        autoDownload: [0],
        next: () => {
            let next = fn.ge("a.next[href^='/image/']");
            return next ? next.href : null;
        },
        prev: 1,
        customTitle: () => {
            if (document.URL.includes("/image/")) {
                let id = document.URL.split("/").at(-1);
                return fetch(`/api/photo/${id}`).then(res => res.json()).then(json => fn.dt({
                    t: json.name
                }));
            } else if (document.URL.includes("/article/")) {
                return fn.dt({
                    s: "h1.title"
                });
            } else {
                return null;
            }
        },
        hide: "#m_website_float,#m_website_center,#m_image_content_title,.aside_right_ad,#p_image_content_title,#p_website_float,#p_website_center,#p_website_right_float",
        category: "nsfw1"
    }, {
        name: "LUV.VN",
        url: {
            h: "luv.vn",
            p: /^\/[^\/]+\/$/
        },
        imgs: () => fn.getImgSrcset(".wp-block-image img"),
        capture: () => _this.imgs(),
        customTitle: ".jeg_post_title",
        category: "nsfw1"
    }, {
        name: "✫ Ảnh đẹp ✫/Ảnh đẹp",
        url: {
            h: ["tuyetnhan.com", "tuyetnhan.co"],
            p: /^\/[^\/]+\/$/
        },
        imgs: () => fn.getImgSrcset(".entry-content img:not([src*='/logo'])"),
        capture: () => _this.imgs(),
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: ".entry-title,.card_title",
        hide: "#cboxOverlay,#cboxWrapper",
        category: "nsfw1"
    }, {
        name: "Gai.vn",
        url: {
            h: "gai.vn"
        },
        SPA: () => ["#content .gai-thumb>.vn-box", "a[data-fancybox='slide']"].every(s => !!fn.ge(s)) || !!fn.ge(".FullPictureLoadImage"),
        observerURL: true,
        imgs: async () => {
            if (!["#content .gai-thumb>.vn-box", "a[data-fancybox='slide']"].every(s => !!fn.ge(s))) return [];
            await fn.getNP(".gai-thumb", "li.page-item.active+li:not(.disabled)>a");
            fn.remove("//div[nav[@aria-label='Page navigation']]");
            return fn.gae("a[data-fancybox='slide']");
        },

        button: [4],
        insertImg: ["#content", 2],
        customTitle: ".nav-breadcrumb>.nav-breadcrumb-item:last-child",
        fancybox: {
            blacklist: 1
        },
        category: "nsfw1"
    }, {
        name: "imgcup.com",
        host: ["imgcup.com"],
        reg: /^https?:\/\/imgcup\.com\/[^\.]+\.html$/,
        init: () => fn.createImgBox(".penci-post-gallery-container", 2),
        imgs: ".item-gallery-masonry>a",
        thums: ".item-gallery-masonry>a img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".penci-post-gallery-container"], 2
        ],
        autoDownload: [0],
        next: ".prev-post-inner>a",
        prev: ".next-post-inner>a",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "MissKON.com",
        host: ["misskon.com"],
        reg: /^https?:\/\/misskon\.com\/[^\/]+\/$/,
        imgs: () => fn.getImg(".entry img[decoding]", fn.gt(".page-link>*:last-child"), 4),
        button: [4],
        insertImg: ["//p[img[@decoding]]", 2],
        go: 1,
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "Cosymodel",
        url: {
            h: "cosymodel.com",
            p: /^\/[^\/]+\/$/
        },
        imgs: ".tdb_single_content .tdb-block-inner img",
        button: [4],
        insertImg: [".tdb_single_content .tdb-block-inner", 2],
        autoDownload: [0],
        next: ".tdb-post-prev a",
        prev: ".tdb-post-next a",
        customTitle: ".tdb-title-text",
        category: "nsfw1"
    }, {
        name: "Xiuren",
        host: ["xiuren.biz"],
        reg: /^https?:\/\/xiuren\.biz\/[^\/]+\/$/,
        include: ".content-inner a[data-lbwps-srcsmall],.content-inner a[rel=noopener]",
        imgs: ".content-inner a[data-lbwps-srcsmall],.content-inner a[rel=noopener]",
        button: [4],
        insertImg: [".content-inner", 2],
        autoDownload: [0],
        next: "a.post.prev-post",
        prev: "a.post.next-post",
        customTitle: "h1.jeg_post_title",
        category: "nsfw1"
    }, {
        name: "Asigirl.com",
        url: {
            h: "asigirl.com",
            p: /^\/[^\/]+\/$/
        },
        init: () => fn.createImgBox("#asigirl-gallery", 1),
        imgs: "#asigirl-gallery a",
        thums: "#asigirl-gallery a>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#asigirl-gallery"], 2
        ],
        go: 1,
        customTitle: () => {
            if (fn.ge("#content-header-title")) {
                return fn.dt({
                    s: "#content-header-title"
                });
            } else if (fn.ge("meta[property='og:image:alt']")) {
                return fn.attr("meta[property='og:image:alt']", "content");
            } else {
                return document.title;
            }
        },
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "nsfw1"
    }, {
        name: "Asigirl.com 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/asigirl\.com\//,
        autoPager: {
            ele: ".oxy-posts",
            observer: ".oxy-posts>*",
            next: "span.current+a:not(.next)",
            re: ".oxy-easy-posts-pages",
            pageNum: "span.current"
        },
        category: "autoPager"
    }, {
        name: "4KHD",
        host: ["www.4khd.com", "cfntz.xxtt.info", "ckdfv.xxtt.info", "svqds.xxtt.info"],
        url: {
            e: "//a[@rel='home'][text()='4KHD']",
            p: /^\/content\/\d+\/[^\.\/]+\.html$/
        },
        imgs: async () => {
            thumbnailSrcArray = await fn.getImgA("figure.wp-block-image>a>img,#basicExample>a>img,.entry-content>p>a>img", ".page-link-box a").then(arr => arr.map(e => e.replace(/\?w=\d+$/, "?w=100")));
            let bigSrcArray = thumbnailSrcArray.map(e => e.replace(/\/w\d+-rw\//, "/w7680-rw/").replace("?w=100", ""));
            if (fn.lh === "www.4khd.com") {
                if (bigSrcArray[0].startsWith("https://img.4khd.com")) {
                    let host = new URL(bigSrcArray[0]).host;
                    return bigSrcArray.map(src => src.replace(host, "i0.wp.com/" + host));
                }
                return bigSrcArray;
            } else {
                let oldImgOrigin = new URL(bigSrcArray[0]).origin;
                let newImgOrigin = "https://i0.wp.com/img.4khd.com";
                return bigSrcArray.map(src => src.replace(oldImgOrigin, newImgOrigin));
            }
        },
        button: [4],
        insertImg: [
            [".page-link-box,.wp-block-post-content>*:last-child,#khd", 1, "#basicExample,.wp-block-image,.entry-content>p:not(#FullPictureLoadEnd),.page-link-box"], 2
        ],
        customTitle: "h3.wp-block-post-title",
        css: ".FullPictureLoadImage{max-width:100%!important}",
        hide: ".centbtd,.popup,.wp-container-13",
        category: "nsfw2"
    }, {
        name: "4KHD AAD",
        url: {
            e: "//a[@rel='home'][text()='4KHD']"
        },
        hide: ".centbtd,.popup,.wp-container-13",
        category: "ad"
    }, {
        name: "AsianPink",
        host: ["asianpink.net"],
        reg: /^https?:\/\/asianpink\.net\/[^\/]+\/$/,
        imgs: "a.e-gallery-item",
        button: [4],
        insertImg: ["//div[div[a[contains(@class,'e-gallery-item')]]][@class='elementor-widget-container']", 2],
        go: 1,
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: "h1.elementor-heading-title",
        category: "nsfw1"
    }, {
        name: "Buon Dua/MISS BABY",
        url: {
            h: ["buondua.com", "buondua.us", "missbaby.top"],
            e: ".article-fulltext img[alt]"
        },
        init: () => {
            fn.remove("//div[text()='Sponsored ads']");
            fn.remove(".search-form~*");
        },
        imgs: () => fn.getImg(".article-fulltext img[alt]", fn.gt(".pagination-list>span:last-child>a").match(/\d+/)[0]),
        button: [4],
        insertImg: [".article-fulltext", 2],
        customTitle: ".article-header>h1",
        category: "nsfw2"
    }, {
        name: "BaoBua.Net",
        host: ["www.baobua.net"],
        reg: /^https?:\/\/www\.baobua\.net\/post\//,
        imgs: () => fn.getImg(".wp-block-image img[alt]", (fn.gt(".nav-links>*:last-child") || 1), 6),
        button: [4],
        insertImg: [".entry-content.read-details", 2],
        customTitle: () => fn.title("|", 1),
        category: "nsfw2"
    }, {
        name: "blog.baobua.net",
        host: ["blog.baobua.net"],
        link: "https://blog.baobua.net/mlem",
        url: {
            h: "baobua.net",
            e: ".article-body"
        },
        imgs: "a.fancybox",
        button: [4],
        insertImg: [".article-body", 2],
        customTitle: () => fn.title("@BaoBua", 1),
        css: "#fix_scale img:hover{transform:none!important}",
        category: "nsfw2"
    }, {
        name: "HOTGIRLchina格式",
        host: [
            "hotgirlchina.com",
            "anhnguoimau.com",
            "anhnguoidep.com",
            "anhnguoilon.com",
            "xinh.pro",
            "anhkhieudam.com",
            "hinhsexviet.com",
            "anhmienphi.com"
        ],
        reg: [
            /^https?:\/\/hotgirlchina\.com\/.+(photos?|videos?|anh)?\/?/,
            /^https?:\/\/anhnguoimau\.com\/\d+\/[^\/]+\/$/,
            /^https?:\/\/anhnguoidep\.com\/[^\/]+\/$/,
            /^https?:\/\/anhnguoilon\.com\/[^\/]+\/$/,
            /^https?:\/\/xinh\.pro\/[^\/]+\/$/,
            /^https?:\/\/anhkhieudam\.com\/[^\/]+\/$/,
            /^https?:\/\/hinhsexviet\.com\/[^\/]+\/$/,
            /^https?:\/\/anhmienphi\.com\/[^\/]+\/$/
        ],
        include: ".entry-inner img[alt]",
        init: () => {
            let share = fn.ge(".entry.share");
            if (share) share.classList.remove("share");
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt("span.pages").match(/\d+$/);
            } catch {
                max = 1
            }
            return fn.getImg(".entry-inner img[alt]", max, 4);
        },
        button: [4],
        insertImg: [
            [".pagination", 1, ".entry-inner>p:not(#FullPictureLoadEnd),.separator"], 2
        ],
        customTitle: () => fn.dt({
            s: ".post-title",
            d: /\(\d+\s?photos\s?\)|(\s?\(\d+\s?photos?\s?\+\s?\d+\s?videos?\))|\([0-9\s]+ảnh[0-9\s\+]+video\)|\([0-9\s]+ảnh.*\)|\/mitaku\.net\//i
        }),
        hide: ".boxzilla-container,.boxzilla-overlay,.sharrre-container",
        category: "nsfw1"
    }, {
        name: "HOTGIRLchina 格式 AD",
        reg: /^https?:\/\/(hotgirlchina\.com|anhnguoimau\.com|anhnguoidep|anhnguoilon\.com|xinh\.pro|anhkhieudam\.com|hinhsexviet\.com|anhmienphi\.com)\//,
        hide: ".boxzilla-container,.boxzilla-overlay,.sharrre-container",
        category: "ad"
    }, {
        name: "FoamGirl",
        url: {
            h: "foamgirl.net",
            p: ".html",
            e: "a.imageclick-imgbox"
        },
        imgs: () => {
            let max;
            try {
                [, max] = fn.gt(".mbx-nav-right").match(/\d+\/(\d+)/);
            } catch {
                max = 1;
            }
            return fn.getImg("a.imageclick-imgbox", max, 9);
        },
        button: [4],
        insertImg: [
            ["#image_div>*:last-child", 1, "#image_div br,a.imageclick-imgbox"], 2
        ],
        customTitle: () => fn.dt({
            s: ".item_title>h1",
            d: /\n/g
        }),
        hide: ".affs",
        category: "nsfw2"
    }, {
        name: "photo.camcam.cc",
        host: ["photo.camcam.cc"],
        reg: /^https?:\/\/photo\.camcam\.cc\/[^/]+\/$/,
        init: () => fn.createImgBox(".entry-content"),
        imgs: "a.rgg-img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".rgg-container"], 2
        ],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: ".page-title",
        category: "nsfw2"
    }, {
        name: "3600000 Beauty",
        host: ["3600000.xyz"],
        reg: /^https?:\/\/3600000\.xyz\/[^\/]+\/$/,
        imgs: () => {
            let [a, img] = ["//a[img[@file]]", ".entry-content img.ls_lazyimg[file]"];
            if (fn.ge(a)) {
                return fn.gae(a);
            } else if (fn.ge(img)) {
                return fn.gae(img).map(e => e.getAttribute("file"));
            } else {
                return [];
            }
        },
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Big Boobs Asia",
        host: ["www.tokyobombers.com"],
        reg: /^https?:\/\/www\.tokyobombers\.com\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: () => {
            if (fn.ge(".gallery img[srcset]")) {
                return fn.getImgSrcset(".gallery img[srcset]");
            } else {
                return fn.gae("a[itemprop='contentURL']");
            }
        },
        button: [4],
        insertImg: [".gallery", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Erogirl",
        url: {
            h: "erogirl.net"
        },
        SPA: () => {
            if (document.URL.includes("/p/") && !fn.ge(".FullPictureLoadImage")) {
                return fn.fetchDoc(document.URL).then(dom => {
                    let data = fn.gt("#__NEXT_DATA__", 1, dom);
                    let json = JSON.parse(data);
                    siteJson = json;
                    debug("\n此頁JSON資料\n", siteJson);
                    return json;
                });
            } else if (fn.ge(".FullPictureLoadImage")) {
                return true;
            } else {
                return false;
            }
        },
        observerURL: true,
        imgs: () => {
            thumbnailSrcArray = siteJson.props.pageProps.post.content.data.map(e => e.attributes.formats.thumbnail.url);
            return siteJson.props.pageProps.post.content.data.map(e => e.attributes.formats.serving_2560.url);
        },
        button: [4],
        insertImg: [".content-img", 2],
        endColor: "white",
        insertImgAF: () => {
            let loop = setInterval(() => !fn.ge(".FullPictureLoadImage") ? fn.immediateInsertImg() : null, 500);
            setTimeout(() => clearInterval(loop), 10000);
        },
        customTitle: () => siteJson?.props?.pageProps?.post?.title,
        category: "nsfw2"
    }, {
        name: "Cosplay DB",
        host: ["cosplaydb.blogspot.com"],
        reg: /^https?:\/\/cosplaydb\.blogspot\.com\/\d+\/\d+\/[\w-]+\.html/,
        imgs: ".post-body img",
        button: [4],
        insertImg: [".post-body", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "jangjoo",
        host: ["jangjooart.blogspot.com"],
        reg: /^https?:\/\/jangjooart\.blogspot\.com\/\d+\/\d+\/[\w-]+\.html/,
        imgs: ".post-body img",
        button: [4],
        insertImg: [".post-body", 2],
        autoDownload: [0],
        next: ".blog-pager-older-link",
        prev: ".blog-pager-newer-link",
        customTitle: ".post_item h1",
        category: "nsfw1"
    }, {
        name: "Photo Beach",
        host: ["photobeach.blogspot.com"],
        reg: /^https?:\/\/photobeach\.blogspot\.com\/\d+\/\d+\/[\w-]+\.html/,
        imgs: ".entry-content a:has(>img),br~a,br~img",
        button: [4],
        insertImg: [
            [".entry-content a:has(>img)", 1, ".entry-content a:has(>img):not[class^='Full'],.entry-content a~br"], 2
        ],
        category: "nsfw2"
    }, {
        name: "Everia.club",
        host: ["everia.club", "torayaki.com", "evevoa.com"],
        url: {
            e: ["//div[@id='site-logo']//a[@rel='home'][text()='EVERIA.CLUB']", ".wp-block-image img,.entry-content img"]
        },
        imgs: () => {
            let [img, a] = [".wp-block-image img", ".separator>a.no-lightbox"]
            if (!!fn.ge(img)) {
                return fn.gae(img);
            } else if (!!fn.ge(a)) {
                return fn.gae(a);
            } else {
                return fn.gae(".entry-content img");
            }
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "Everia club",
        url: {
            h: "www.everiaclub.com"
        },
        imgs: ".mainleft img",
        button: [4],
        insertImg: [".mainleft", 2],
        customTitle: ".mainleft h1",
        category: "nsfw2"
    }, {
        name: "SexyGirl",
        host: ["www.sexygirl.cc", "sexygirl.cc"],
        reg: [
            /^https?:\/\/(www\.)?sexygirl\.cc\/a\/\d+\.html$/,
            /^https?:\/\/(www\.)?sexygirl\.cc\/photo\/([\w-]+\/)?a\/\d+\.html$/,
            /^https?:\/\/(www\.)?sexygirl\.cc\/(\w{2}\/)?photo\/\d+\.html$/,
        ],
        imgs: "div>img.img-f1luid,div>img.img-fluid",
        button: [4],
        insertImg: ["//div[img]", 2],
        next: "//a[text()='Previous']",
        prev: "//a[text()='Next']",
        category: "nsfw2"
    }, {
        name: "Căng Cực",
        host: ["cangcuc.com"],
        reg: /^https?:\/\/cangcuc\.com\/[^\/]+\/[^\/]+\/$/,
        imgs: ".royal_grid a",
        button: [4],
        insertImg: [
            [".royal_grid", 2, ".royal_grid"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: ".widget-previous-post a",
        prev: ".widget-next-post a",
        customTitle: "h1.title",
        category: "nsfw1"
    }, {
        name: "Porn Pics",
        host: ["www.pornpics.com"],
        reg: /^https?:\/\/www\.pornpics\.\w+\/.*galleries\//,
        imgs: "#tiles a.rel-link",
        thums: "#tiles a.rel-link>img",
        button: [4],
        insertImg: ["#main", 3],
        customTitle: ".title-section h1",
        category: "nsfw2"
    }, {
        name: "HD Porn Pictures",
        host: ["hdpornpictures.net"],
        reg: /^https?:\/\/hdpornpictures\.net\/id\/\d+\//,
        imgs: () => {
            let imgs = fn.gau("#tiles a.rel-link");
            thumbnailSrcArray = imgs.map(e => e + "?w=300");
            return imgs;
        },
        button: [4],
        insertImg: ["#main", 3],
        customTitle: () => fn.title(" - HD Porn Pictures"),
        category: "nsfw2"
    }, {
        name: "Freebigtit",
        host: ["www.freebigtitpornpics.com"],
        reg: /^https?:\/\/www\.freebigtitpornpics\.com\/content\/\d+\//,
        imgs: "//ul[@id='dylan']//a[img[@data-src]]",
        thums: "ul#dylan a>img[data-src]",
        button: [4],
        insertImg: [
            ["#dylan", 2], 1
        ],
        go: 1,
        category: "nsfw2"
    }, {
        name: "NongMo.Zone",
        host: ["www.ilovexs.com", "ilovexs.com"],
        reg: [
            /^https?:\/\/(www\.)?ilovexs\.com\/post_id\/\d+\//,
            /^https?:\/\/(www\.)?ilovexs\.com\/post\/[^\/]+\//,
        ],
        imgs: ".separator img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "idol.gravureprincess.date",
        host: ["idol.gravureprincess.date"],
        reg: /^https?:\/\/idol\.gravureprincess\.date\/\d+\/\d+\/.+\.html/,
        imgs: ".separator img",
        button: [4],
        insertImg: [
            [".entry-content", 0], 2
        ],
        go: 1,
        autoDownload: [0],
        next: "a.blog-pager-older-link",
        prev: "a.blog-pager-newer-link",
        customTitle: ".post-title",
        category: "nsfw2"
    }, {
        name: "劍心回憶",
        host: ["kenshin.hk"],
        link: "https://kenshin.hk/category/jnews/photoalbum/",
        reg: /^https?:\/\/kenshin\.hk\/\d+\/\d+\/\d+\/[^/]+\/(#small-1)?$/,
        include: "//div[@class='entry-utility']/a[1][text()='寫真組圖'] | //div[@class='cat-tags']/a[1][text()='寫真組圖']",
        init: async () => {
            let p = fn.ge("//p[contains(text(),'寫真')]");
            if (p) {
                let tE = fn.ge(".entry-content,.post-page-content");
                insertBefore(tE, p);
            }
            let links = fn.gau("//a[button[contains(text(),'寫真')]]");
            await fn.getEle(links, ".entry-content>p>img,.post-page-content>p>img,.videoWrapper", ".entry-content,.post-page-content");
            let v = fn.ge(".videoWrapper");
            if (v) {
                let tE = fn.ge(".entry-content,.post-page-content");
                insertBefore(tE, v);
            }
        },
        imgs: ".entry-content>img,.post-page-content>img",
        button: [4],
        insertImg: [".entry-content,.post-page-content", 2],
        go: 1,
        customTitle: () => fn.dt({
            s: "h1.entry-title,h2.post-title",
            d: /【寫真】|\s?\(\d+P,片\)/gi
        }),
        category: "nsfw1"
    }, {
        name: "J M G T",
        host: ["www.qiuyeshudian.com"],
        reg: /^https?:\/\/www\.qiuyeshudian\.com\/[^\/]+\/$/,
        imgs: () => {
            thumbnailSrcArray = fn.gae(".feature-box img,.entry-content img").map(e => e.dataset.src ?? e.src);
            return thumbnailSrcArray.length > 1 ? thumbnailSrcArray.map(e => e.replace(/\?w=\d+&ssl=1/, "").replace(/\?resize.+/, "")) : [];
        },
        button: [4],
        insertImg: [".entry-content", 2],
        go: 1,
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: () => fn.dt({
            s: "article h1",
            d: /(\d+Photos)\s|\(\d+Photos\)\s|\d+Photos\s|\d+\spics|\(选登\)|(选登\d+P)/
        }),
        category: "nsfw1"
    }, {
        name: "Gravia",
        host: ["www.gravia.site", "gravia.site"],
        reg: /^https?:\/\/(www\.)?gravia\.site\/box\/show\.php\?id=\d+$/,
        init: () => fn.createImgBox(".slideshow.for_box", 2),
        imgs: ".slideshow .item>img",
        thums: ".thums img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".slideshow.for_box"], 2
        ],
        customTitle: () => fn.dt({
            s: ".container>h1",
            d: /\s?【\d+枚】/
        }),
        css: "img.small{max-width:100% !important;max-height:auto !important}",
        hide: ".cmd_bar.wide",
        category: "nsfw1"
    }, {
        name: "AI.img/AI2D",
        host: ["aiimg.fun", "ai2d.fun"],
        reg: [
            /^https?:\/\/aiimg\.fun\/note\/public\.php\?id=\d+/,
            /^https?:\/\/ai2d\.fun\/note\/public\.php\?id=\d+/,
            /^https?:\/\/ai2d\.fun\/ubox\/rom\.php\?id=\d+/
        ],
        exclude: ".not_found.small",
        init: () => fn.createImgBox(".thums", 2),
        imgs: async () => {
            await fn.getNP(".thums>.item", ".pager>a.now+a", null, ".pager");
            thumbnailSrcArray = fn.getImgSrcArr(".thums img");
            return fn.gae("div.item[org_img_url]");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".thums,.slideshow,.pager,.search_range"], 2
        ],
        customTitle: () => fn.gt("h1").replace(/\s\(\d+枚\)/, "").replaceAll("/", "/"),
        category: "nsfw2"
    }, {
        name: "NEWSグラビアアイドル.net",
        host: ["news.idolsenka.net"],
        reg: /^https?:\/\/news\.idolsenka\.net\/archives\/\d+/,
        imgs: () => fn.gae(`
        .entry-content img:not([alt^='DMM'],[alt*='OFF'],[alt^='FANZA']),
        .blog-content img:not([alt^='DMM'],[alt*='OFF'],[alt^='FANZA'])
        `).map(img => {
            let src = img.src;
            if (src.includes("wp.com")) {
                src = src.replace(/\?resize.+$/, "") + "?ssl=1";
            }
            if (src.includes("blogger.")) {
                let srcArr = src.split("/");
                srcArr[srcArr.length - 2] = "s16000";
                src = srcArr.join("/");
            }
            return src;
        }),
        capture: () => _this.imgs(),
        //button: [4],
        //insertImg: [".entry-content", 2],
        customTitle: ".entry-title,.blog-single-title",
        setFancybox: ".entry-content a[href*='blogger.'],.blog-content a[href*='blogger.']",
        category: "nsfw1"
    }, {
        name: "グラビア週刊誌 9/グラビア週刊誌 5/グラビア週刊誌 6",
        host: ["gravurezasshi9.doorblog.jp", "magazinejapanese5.blog.jp", "magazinejapanese6.blog.jp"],
        reg: /^https?:\/\/(gravurezasshi9\.doorblog\.jp|magazinejapanese(5|6)\.blog\.jp)\/archives\/\d+\.html(\?ref=)?/,
        imgs: ".article-body-inner>a,#article-contents>a",
        thums: ".article-body-inner>a>img,#article-contents>a>img",
        button: [4],
        insertImg: [".article-body-inner,#article-contents", 2],
        autoDownload: [0],
        next: "//li[text()='前の記事: ']/a | //a[text()='前の記事']",
        prev: "//li[text()='次の記事: ']/a | //a[text()='次の記事']",
        customTitle: "h1.article-title>a,.article-header>h1",
        category: "nsfw1"
    }, {
        name: "グラビア週刊誌 9/グラビア週刊誌 5/グラビア週刊誌 6 - 分類自動翻頁",
        host: ["gravurezasshi9.doorblog.jp", "magazinejapanese5.blog.jp", "magazinejapanese6.blog.jp"],
        reg: [
            /^https?:\/\/(gravurezasshi9\.doorblog\.jp|magazinejapanese(5|6)\.blog\.jp)\/(\?p=\d+)?$/,
            /^https?:\/\/(gravurezasshi9\.doorblog\.jp|magazinejapanese(5|6)\.blog\.jp)\/archives\/([\d-]+|cat_\d+)\.html(\?p=\d+)?$/
        ],
        autoPager: {
            ele: ".autopagerize_page_element,.article-list-outer",
            observer: "article.article,.article-list-outer>li",
            next: "//li[@class='current']/following-sibling::li[1]/a | //a[span[text()='次へ']]",
            re: ".pager,.pager_fixed,.fractional-page",
            pageNum: () => nextLink.match(/\?p=(\d+)/)[1]
        },
        openInNewTab: ".autopagerize_page_element a[href]:not([target=_blank]),.article-list-outer a[href]:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "エロマニア 猿!",
        host: ["nisokudemosandal.blog.jp"],
        reg: /^https?:\/\/nisokudemosandal\.blog\.jp\/archives\/\d+\.html$/,
        imgs: ".article-body a[title]:has(>img)",
        autoDownload: [0],
        next: "//li[@class='prev']/a | //a[text()='前の記事']",
        prev: "//li[@class='next both']/a | //a[text()='次の記事']",
        customTitle: ".article-title",
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "Gravure Idols",
        host: ["gravureidols.top"],
        reg: /^https?:\/\/gravureidols\.top\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: ".content-inner>div:not(.apss-social-share) a",
        button: [4],
        insertImg: [
            ["//p[a[img]]", 2, "//p[a[img]]"], 1
        ],
        go: 1,
        autoDownload: [0],
        next: ".jeg_prevnext_post a",
        prev: ".jeg_prevnext_post a",
        customTitle: ".jeg_post_title",
        category: "nsfw1"
    }, {
        name: "水着グラビア",
        host: ["www.mizugigurabia.com"],
        reg: /^https?:\/\/www\.mizugigurabia\.com\/\?p=\d+$/,
        init: () => {
            fn.clearAllTimer();
            fn.remove("#content-top");
        },
        imgs: () => fn.getImgSrcset(".article img[srcset]"),
        capture: () => _this.imgs(),
        customTitle: ".entry-title",
        setFancybox: ".article a:has(>img[srcset])",
        category: "nsfw2"
    }, {
        name: "エロ役場",
        host: ["eroyakuba.com"],
        reg: /^https?:\/\/eroyakuba\.com\/[^/]+\/(#.*)?$/,
        imgs: () => fn.getImgSrcset(".entry-thumbnail img,.flexitem_content img[srcset],.entry-content img[srcset]"),
        capture: () => _this.imgs(),
        setFancybox: ".entry-thumbnail img,.flexitem_content img[srcset],.entry-content img[srcset]",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "エロ画像まとめ",
        host: ["geinou-nude.com"],
        reg: /^https?:\/\/geinou-nude\.com\/[^\/]+\/(#.*)?$/,
        imgs: ".post_thum>img,.post_content a[href*='/uploads/']",
        autoDownload: [0],
        next: "a.nav_link_l",
        prev: "a.f_row_r",
        customTitle: "h1.post_title",
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "裏ピク",
        host: ["www.urapic.com"],
        reg: /^https?:\/\/www\.urapic\.com\/blog-entry-\d+\.html$/,
        imgs: "//div[@class='entry-body']//a[img[@title]] | //div[@class='entry_body']//a[img[@title]]",
        customTitle: () => fn.gt(".entry-title,.entry_title>h1").replace(/[w]+$/, ""),
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "復刻書林",
        host: ["reprint-kh.com"],
        reg: /^https?:\/\/reprint-kh\.com\/archives\/\d+$/,
        //init: async () => await fn.clearElementEvent(),
        imgs: async () => {
            if (fn.ge(".gallery-row")) {
                await fn.getNP(".gallery-row", "//a[span[text()='次のページ']]");
            }
            if (fn.ge(".ngg-gallery-thumbnail-box")) {
                await fn.getNP(".ngg-gallery-thumbnail-box", "span.current+a");
            }
            thumbnailSrcArray = fn.getImgSrcArr(".tiled-gallery a img,.ngg-gallery-thumbnail-box a img");
            return fn.gae(".tiled-gallery a,.ngg-gallery-thumbnail-box a");
        },
        button: [4],
        insertImg: [
            [".single-post-main>.share,.single-post-main .content", 2], 2
        ],
        insertImgAF: (parent) => {
            for (let node of [...parent.childNodes]) {
                if (node.id === "FullPictureLoadOptionsButtonParentDiv") {
                    break;
                }
                node.remove();
            }
        },
        go: 1,
        autoDownload: [0],
        next: ".previous_post>a",
        prev: ".next_post>a",
        customTitle: () => fn.dt({
            s: ".single-post-title",
            d: /\d+photos/
        }),
        category: "nsfw2"
    }, {
        name: "力武靖写真集",
        host: ["lolita.lady.jp"],
        reg: /^https?:\/\/lolita\.lady\.jp\/\w+\/book\.html/,
        imgs: ".grid img",
        button: [4],
        insertImg: [
            [".grid", 1, ".grid"], 2
        ],
        autoDownload: [0],
        next: "div[align=right] a",
        prev: "div[align=left] a",
        customTitle: "#wrapper h3",
        category: "nsfw2"
    }, {
        name: "Rikitake.com",
        host: ["rikitake.com"],
        reg: /^https?:\/\/rikitake\.com\/g\/\d+$/,
        imgs: () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            return fn.gae("a[data-lightbox]");
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            d: "|Rikitake.com"
        }),
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "マブい女画像集",
        host: ["mabui-onna.com"],
        reg: /^https?:\/\/mabui-onna\.com\/blog-entry-\d+\.html/,
        init: () => {
            let texts = fn.gae("//div[@class='entry_body']//div[not(br)][not(a[img])][not(@class='fc2_footer')][not(@class='topentry_text')][not(@class='fc2button-clap')][not(@class='entry_footer')][not(@class='entry_data')]");
            if (texts.length > 0) {
                let te = fn.ge(".topentry_text,.entry_body");
                texts.forEach(e => insertBefore(te, e));
            }
            fn.createImgBox(".entry_body", 1);
        },
        imgs: ".topentry div>a:not([href*='.html'],[href*='.dmm.']),.wrapper section div>a:not([href*='.html'],[href*='.dmm.'])",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "div:has(>a[target]>img[alt]),div[id^='bnc_ad']"], 2
        ],
        insertImgAF: () => {
            let e = fn.ge("div:has(>a[href*='.dmm.'])");
            if (e) {
                let x = fn.ge(".entry_body");
                insertBefore(x, e);
            }
        },
        autoDownload: [0],
        next: "a.pager_next,.next_entry>a",
        prev: "a.pager_prev,.prev_entry>a",
        customTitle: () => fn.gt(".topentry_title span,.entry_title h1>strong").replace(/\d+枚/, "").replace(/\s\s/g, " ").trim(),
        category: "nsfw1"
    }, {
        name: "美女の集い",
        host: ["bizyonotudoi.com"],
        reg: /^https?:\/\/bizyonotudoi\.com\/d\/\d+\.html$/,
        imgs: ".thumb-img-area>img",
        button: [4],
        insertImg: [".kizi-thumb-list", 2],
        customTitle: ".page-title",
        hide: "#pagemap-navi",
        category: "nsfw1"
    }, {
        name: "ぷるるんお宝画像庫",
        link: "http://blog.livedoor.jp/pururungazou/",
        reg: /^https?:\/\/blog\.livedoor\.jp\/pururungazou\/archives\/\d+\.html$/,
        imgs: () => {
            videoSrcArray = fn.gae("video[src]").map(e => e.src);
            return fn.gae(`
            .entry-content img[src*='/pururungazou/imgs/'],
            .entry-content img[src*='/media/'],
            .article-body img[src*='/pururungazou/imgs/'],
            .article-body img[src*='/media/'],
            a[title][href*='thetv.jp/i/']
            `).map(e => {
                if (e.nodeName === "A") {
                    return e.href.replace(/\?w=.+$/, "");
                } else {
                    return e.src.replace(/-s(\.\w+)$/, "$1");
                }
            });
        },
        capture: () => _this.imgs(),
        customTitle: ".entry-title,.article-title",
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "Love Asian Babes",
        host: ["amazon-love.com"],
        reg: /^https?:\/\/amazon-love\.com\/[^.]+\.html$/,
        imgs: () => {
            let max = fn.gt("//a[text()='Next Page »']", 2) || 1;
            return fn.getImg(".entry-content img", max, 7);
        },
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: "span.prev>a",
        prev: "span.next>a",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Permanent Bachelor",
        host: ["www.saladpuncher.com"],
        reg: /^https?:\/\/www\.saladpuncher\.com\/\d+\/\d+\/[^\/]+\//,
        init: () => fn.createImgBox(".entry-container", 2),
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".rsTmb>img");
            return thumbnailSrcArray.map(e => e.replace(/-\d+x\d+(\.\w+)$/, "$1"))
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: ".posttitle",
        category: "nsfw1"
    }, {
        name: "IVPhoto_Gravure",
        host: ["ivphoto.tistory.com"],
        reg: /^https?:\/\/ivphoto\.tistory\.com\/(m\/)?\d+/,
        imgs: ".imageblock img",
        button: [4],
        insertImg: [".entry-content,.blogview_content", 3],
        customTitle: ".tit_blogview,.hgroup h1",
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "MIC MIC IDOL",
        host: ["www.micmicidol.club"],
        reg: /^https?:\/\/www\.micmicidol\.club\/\d+\/\d+\/.+\.html$/,
        imgs: async () => {
            let imgsSrcArr = fn.gae(".entry-content a[href*=blog]").map(a => {
                let arr = a.href.split("/");
                if (arr.length === 9) {
                    arr[7] = "s16000";
                    return arr.join("/");
                } else {
                    return a.href;
                }
            });
            thumbnailSrcArray = imgsSrcArr.map(e => e.replace("/s16000/", "/w100/"));
            return imgsSrcArr;
        },
        button: [4],
        insertImg: [
            [".entry-content", 0, ".entry-content a[href*=blog]:not([data-fancybox]),.entry-content br"], 2
        ],
        customTitle: ".entry-title",
        topButton: true,
        css: ".post img{max-width:100% !important}.post-body{margin:0px!important;}",
        category: "nsfw2"
    }, {
        name: "MIC MIC IDOL - 分類自動翻頁",
        host: ["www.micmicidol.club"],
        reg: [
            /^https?:\/\/www\.micmicidol\.club\/(\?m=1)?$/,
            /^https?:\/\/www\.micmicidol\.club\/search/
        ],
        init: () => fn.run("$('.snips-image').unbind();$('.snips-image img').unbind();"),
        autoPager: {
            ele: ".blog-posts",
            next: "a.blog-pager-older-link",
            http: "https",
            observer: ".post.hentry",
            re: "#blog-pager",
            stop: (dom) => !fn.ge(".date-outer", dom),
            aF: () => {
                fn.gae("//div[@class='snips-image']/a[not(img)]").forEach(a => {
                    let script = fn.ge("script", a);
                    if (script) {
                        let code = script.innerText;
                        if (/document\.write/.test(code)) {
                            let [, url, , alt] = code.split('"');
                            let img = new Image();
                            img.src = url.replace("/s72-c/", "/w400/").replace("=s72-c", "=w400");
                            img.alt = alt;
                            insertAfter(script, img);
                        }
                    }
                });
            },
            pageNum: () => /start=/.test(nextLink) ? Number(nextLink.match(/start=(\d+)/)[1]) / 50 + 1 : 1
        },
        openInNewTab: ".date-outer a[href]:not([target=_blank])",
        category: "autoPager"
    }, {
        //TMD寫好不到一天就取消SPA
        name: "Kemono SPA",
        enable: 0,
        links: [
            "https://kemono.su/artists",
            "https://kemono.su/fantia/user/17148"
        ],
        url: {
            h: ["kemono.su"]
        },
        init: () => fn.waitEle("#main"),
        SPA: () => document.URL.includes("/user/") && !!fn.ge(".card-list") || document.URL.includes("/post/"),
        observerURL: true,
        getPostJson: (url) => {
            return fetch("https://kemono.su/api/v1" + new URL(url).pathname).then(res => res.json()).then(json => {
                let {
                    previews,
                    videos
                } = json;
                let thums = previews.map(e => "//img.kemono.su/thumbnail/data" + e.path);
                let images = previews.map(e => e.server + "/data" + e.path + "?f=" + e.name);
                videos = videos.map(e => e.server + "/data" + e.path + "?f=" + e.name);
                return {
                    thums,
                    images,
                    videos
                }
            });
        },
        fn: async () => {
            if (checkGeting() && !!fn.ge(".card-list")) return;
            isFetching = true;
            isGotAll = false;
            let url = location.href.replace(location.search, "");
            let small = fn.gt(".paginator small");
            let postsTotal = small.match(/\d+/g).at(-1);
            let pagesTotal = Math.ceil(Number(postsTotal) / 50);
            let api = "https://kemono.su/api/v1" + new URL(document.URL).pathname + "/posts-legacy";
            let pageLinks = fn.arr(pagesTotal, (v, i) => i == 0 ? api : api + `?o=${i * 50}`);
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            let resArr = [];
            for (let [i, url] of pageLinks.entries()) {
                let res = await fetch(url).then(res => res.json()).then(json => {
                    fn.showMsg(`${displayLanguage.str_06}${i + 1}/${pageLinks.length}`, 0);
                    return json.results.map(e => document.URL + "/post/" + e.id);
                });
                resArr.push(res);
            }
            Promise.all(resArr).then(async arr => {
                let postUrls = arr.flat();
                resArr = [];
                fn.showMsg(displayLanguage.str_05, 0);
                for (let [i, url] of postUrls.entries()) {
                    let res = await _this.getPostJson(url);
                    resArr.push(res);
                    fn.showMsg(`${displayLanguage.str_06}${i + 1}/${postUrls.length}`, 0);
                }
                Promise.all(resArr).then(arr => {
                    thumbnailSrcArray = arr.map(obj => obj.thums).flat();
                    videoSrcArray = arr.map(obj => obj.videos).flat();
                    globalImgArray = arr.map(obj => obj.images).flat();
                    debug("thumbnailSrcArray", thumbnailSrcArray);
                    debug("videoSrcArray", videoSrcArray);
                    debug("globalImgArray", globalImgArray);
                    fn.hideMsg();
                    isGotAll = true;
                    isFetching = false;
                });
            });
        },
        imgs: async () => {
            if (isGotAll) return globalImgArray;
            if (fn.ge(".card-list")) {
                fn.createImgBox(".site-section", 2);
                let links = fn.gau(".card-list__items a");
                let resArr = [];
                fn.showMsg(displayLanguage.str_05, 0);
                for (let [i, url] of links.entries()) {
                    let res = await _this.getPostJson(url);
                    resArr.push(res);
                    fn.showMsg(`${displayLanguage.str_06}${i + 1}/${links.length}`, 0);
                }
                return Promise.all(resArr).then(arr => {
                    thumbnailSrcArray = arr.map(obj => obj.thums).flat();
                    videoSrcArray = arr.map(obj => obj.videos).flat();
                    return arr.map(obj => obj.images).flat();
                });
            } else if (document.URL.includes("/post/")) {
                fn.createImgBox(".post__body", 2);
                fn.showMsg(displayLanguage.str_05, 0);
                return _this.getPostJson(document.URL).then(obj => {
                    thumbnailSrcArray = obj.thums;
                    videoSrcArray = obj.videos;
                    return obj.images;
                });
            }
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "span[itemprop=name],.post__title",
        downloadVideo: true,
        fetch: 1,
        fancybox: {
            blacklist: 1
        },
        category: "nsfw2"
    }, {
        name: "Kemono/Coomer",
        links: [
            "https://kemono.su/artists",
            "https://coomer.su/artists",
            "https://kemono.su/fantia/user/17148",
            "https://coomer.su/fansly/user/365239425979916288",
            "https://coomer.su/onlyfans/user/arty42575619"
        ],
        url: {
            h: ["kemono.su", "coomer.su"],
            p: "/user/",
            e: [".site-section", ".card-list"]
        },
        fn: () => {
            if (checkGeting()) return;
            isFetching = true;
            let url = location.href.replace(location.search, "");
            let small = fn.gt(".paginator small");
            let postsTotal = small.match(/\d+/g).at(-1);
            let pagesTotal = Math.ceil(Number(postsTotal) / 50);
            let pageLinks = fn.arr(pagesTotal, (v, i) => i == 0 ? url : url + `?o=${i * 50}`);
            fn.getEle(pageLinks, ".card-list__items a", null, null, 0).then(eles => {
                let postLinks = eles.map(a => a.href);
                fn.getEle(postLinks, "a.fileThumb,video>source", null, null, 0).then(files => {
                    let images = [];
                    files.forEach(e => {
                        if (e.tagName === "A") {
                            let img = fn.ge("img", e);
                            let src = img.dataset.src ?? img.src;
                            thumbnailSrcArray.push(src);
                            images.push(e.href);
                        } else if (e.tagName === "SOURCE") {
                            videoSrcArray.push(e.src);
                        }
                    });
                    globalImgArray = images;
                    isFetching = false;
                });
            });
        },
        init: () => fn.createImgBox(".site-section", 2),
        imgs: () => {
            let links = fn.gau(".card-list__items a");
            return fn.getEle(links, "a.fileThumb,video>source", null, null, 0).then(eles => {
                let images = [];
                eles.forEach(e => {
                    if (e.tagName === "A") {
                        let img = fn.ge("img", e);
                        let src = img.dataset.src ?? img.src;
                        thumbnailSrcArray.push(src);
                        images.push(e.href);
                    } else if (e.tagName === "SOURCE") {
                        videoSrcArray.push(e.src);
                    }
                });
                return images;
            });
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "span[itemprop=name]",
        downloadVideo: true,
        fetch: 1,
        fancybox: {
            blacklist: 1
        },
        category: "nsfw2"
    }, {
        name: "Kemono/Coomer",
        url: {
            h: ["kemono.su", "coomer.su"],
            p: "/post/",
            e: "a.fileThumb"
        },
        init: () => fn.createImgBox(".post__body", 2),
        imgs: () => {
            videoSrcArray = fn.gae("video>source").map(e => e.src);
            thumbnailSrcArray = fn.gae("a.fileThumb>img").map(e => e.dataset.src ?? e.src);
            return fn.gae("a.fileThumb");
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        autoDownload: [0],
        next: "a.next",
        prev: "a.prev",
        customTitle: ".post__title",
        downloadVideo: true,
        fetch: 1,
        fancybox: {
            blacklist: 1
        },
        category: "nsfw2"
    }, {
        name: "Nekohouse",
        links: [
            "https://nekohouse.su/artists",
            "https://nekohouse.su/fantia/user/18"
        ],
        url: {
            h: "nekohouse.su",
            p: "/user/",
            e: [".site-section", ".card-list"]
        },
        fn: () => {
            if (checkGeting()) return;
            isFetching = true;
            let url = location.href.replace(location.search, "");
            let small = fn.gt(".paginator small");
            let postsTotal = small.match(/\d+/g).at(-1);
            let pagesTotal = Math.ceil(Number(postsTotal) / 50);
            let pageLinks = fn.arr(pagesTotal, (v, i) => i == 0 ? url : url + `?o=${i * 50}`);
            fn.getEle(pageLinks, ".card-list__items a").then(eles => {
                let postLinks = eles.map(a => a.href);
                fn.getEle(postLinks, "div.fileThumb[href],a[download]").then(files => {
                    let images = [];
                    files.forEach(e => {
                        if (e.tagName === "DIV") {
                            let img = fn.ge("img", e);
                            let src = img.dataset.src ?? img.src;
                            thumbnailSrcArray.push(src);
                            images.push(fn.lo + e.getAttribute("href"));
                        } else if (e.tagName === "A") {
                            let url = e.href;
                            if (/\.(mp4|mov)/i.test(url)) {
                                videoSrcArray.push(url);
                            } else if (/\.(rar|zip|7z|cbz)/i.test(url)) {
                                fileUrlArray.push(url);
                            }
                        }
                    });
                    globalImgArray = images;
                    isFetching = false;
                });
            });
        },
        init: () => fn.createImgBox("#main", 2),
        imgs: () => {
            let links = fn.gau(".card-list__items a");
            return fn.getEle(links, "div.fileThumb[href],a[download]").then(eles => {
                let images = [];
                eles.forEach(e => {
                    if (e.tagName === "DIV") {
                        let img = fn.ge("img", e);
                        let src = img.dataset.src ?? img.src;
                        thumbnailSrcArray.push(src);
                        images.push(fn.lo + e.getAttribute("href"));
                    } else if (e.tagName === "A") {
                        let url = e.href;
                        if (/\.(mp4|mov)/i.test(url)) {
                            videoSrcArray.push(url);
                        } else if (/\.(rar|zip|7z|cbz)/i.test(url)) {
                            fileUrlArray.push(url);
                        }
                    }
                });
                return images;
            });
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "span[itemprop=name]",
        fetch: 1,
        category: "nsfw2"
    }, {
        name: "Nekohouse",
        url: {
            h: "nekohouse.su",
            p: "/post/",
            e: "div.fileThumb[href]"
        },
        init: () => fn.createImgBox(".scrape__body", 2),
        imgs: () => {
            let urls = fn.gau("a[download]");
            if (urls.length > 0) {
                urls.forEach(url => {
                    if (/\.(mp4|mov)/i.test(url)) {
                        videoSrcArray.push(url);
                    } else if (/\.(rar|zip|7z|cbz)/i.test(url)) {
                        fileUrlArray.push(url);
                    }
                });
            }
            thumbnailSrcArray = fn.gae("div.fileThumb>img").map(e => e.dataset.src ?? e.src);
            return fn.gae("div.fileThumb[href]").map(e => fn.lo + e.getAttribute("href"));
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: ".scrape__title",
        fetch: 1,
        category: "nsfw2"
    }, {
        name: "套图之家",
        host: ["www.taotuhome.com", "taotuhome.com"],
        reg: /^https?:\/\/(www\.)?taotuhome\.com\/\d+\.html/i,
        imgs: () => fn.getImg(".single-content img[alt]", (fn.gt(".page-links>*:last-child", 2) || 1), 7),
        button: [4],
        insertImg: [".single-content", 2],
        autoDownload: [0],
        next: "a[rel=prev]:not([href^=j])",
        prev: "a[rel=next]:not([href^=j])",
        customTitle: () => fn.gt(".entry-title").replace("-套图之家", ""),
        category: "nsfw1"
    }, {
        name: "套图之家",
        host: ["www.taotuzj.com"],
        reg: /^https?:\/\/www\.taotuzj\.com\/\w+\/\d+\.html$/i,
        imgs: () => {
            let [, max] = fn.gu("//a[text()='尾页']").match(/_(\d+)\.html$/);
            let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url.replace(".html", "") + `_${i + 1}.html`);
            return fn.getImgA(".content img[alt]", links);
        },
        button: [4],
        insertImg: [".content", 2],
        customTitle: () => fn.title(/-套图之家.*$/),
        category: "nsfw1"
    }, {
        name: "套图之家M",
        host: ["m.taotuzj.com"],
        reg: /^https:\/\/m\.taotuzj\.com\/\w+\/\d+\.html$/i,
        imgs: () => {
            let [max] = fn.gt("a.allpage").match(/\d+$/);
            let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url.replace(".html", "") + `_${i + 1}.html`);
            return fn.getImgA(".content img[alt]", links);
        },
        button: [4],
        insertImg: [".content", 2],
        customTitle: () => fn.title(/-套图之家.*$/),
        category: "nsfw1"
    }, {
        name: "俊美图",
        host: ["www.meijuntu.com", "www.junmeitu.com", "www.jeya.de", "www.jeya.jp"],
        url: {
            h: [
                /^(www\.)?meijuntu\.com$/,
                /^(www\.)?junmeitu\.com$/,
                /^(www\.)?jeya\.\w+$/,
            ],
            p: /\/([a-z]{2}\/)?\w+\/\w+\.html$/i,
            e: ".pictures img"
        },
        imgs: async () => {
            let imgsArr = [];
            let max = fn.gt("#pages>*:last-child", 2) || 1;
            let url = siteUrl.replace(/(-\d+)?\.html$/, "");
            let links = fn.arr(max, (v, i) => url + "-" + (i + 1) + ".html");
            for (let [page, link] of links.entries()) {
                let dom = await new Promise(async resolve => {
                    for (let check = 1; check <= 100; check++) {
                        let res = await fetch(link);
                        if (res.status == 304 || res.status == 200) {
                            let buffer = await res.arrayBuffer();
                            let decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                            let htmlText = decoder.decode(buffer);
                            let dom = fn.doc(htmlText);
                            resolve(dom);
                            break;
                        } else {
                            fn.showMsg(`第${page + 1}頁${res.status}重試第${check}次`, 2900);
                            await delay(3000);
                        }
                    }
                });
                let imgs = fn.gae(".pictures img", dom);
                let te = fn.gae(".pictures img").at(-1);
                imgs.forEach(e => {
                    imgsArr.push(e.cloneNode(true));
                    if (page != 0) insertAfter(te, e.cloneNode(true));
                });
                if (page != 0) {
                    let ce = fn.gae("#pages");
                    let re = fn.gae("#pages", dom);
                    if (ce.length == re.length) {
                        ce.forEach((e, i) => (e.outerHTML = re[i].outerHTML));
                    }
                }
                await delay(1000);
            }
            return imgsArr;
        },
        button: [4],
        insertImg: [".pictures", 1],
        autoDownload: [0],
        next: "//span[contains(text(),'下一')]/following-sibling::a",
        prev: "//span[contains(text(),'上一')]/following-sibling::a",
        customTitle: "h1.title",
        hide: ".pre_picture,.next_picture",
        category: "nsfw1"
    }, {
        name: "妹子图",
        host: ["mt316.com"],
        reg: /^https?:\/\/(www\.)?mt316\.com\/\w+\/\d+\.html$/,
        imgs: ".m-list-content img",
        button: [4],
        insertImg: [".m-list-content", 2],
        autoDownload: [0],
        next: ".sxpage_l>a",
        prev: 1,
        customTitle: ".m-list-tools>h2",
        css: ".m-list-content img{max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "心动美图",
        host: ["www.wai76.com", "www.wai77.com"],
        reg: /^https?:\/\/www\.wai\d{2}\.com\/[^\/]+\//,
        include: ".entry-content div[data-src]",
        imgs: () => {
            let links = [fn.url];
            if (fn.ge(".page-links a")) {
                links = fn.gau(".page-links a");
                links = [fn.url, ...links];
            }
            return fn.getEle(links, ".entry-content div[data-src]").then(divs => {
                thumbnailSrcArray = divs.map(e => fn.ge("img", e)?.src);
                return divs;
            });
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "美女集合",
        host: ["meinvjihe.cc"],
        reg: /^https?:\/\/meinvjihe\.cc\/thread-\d+\.htm$/,
        imgs: ".message>img",
        button: [4],
        insertImg: [".message", 2],
        customTitle: ".media-body>span.break-all",
        category: "nsfw1"
    }, {
        name: "美女库",
        host: ["www.meinvku.org.cn"],
        reg: /^https?:\/\/www\.meinvku\.org\.cn\/album\/\d+(\/)?(\.html)?$/,
        imgs: async () => {
            let firstImg = fn.attr("#img_src img", "src");
            let [imgDir] = firstImg.match(/.+\//);
            let [, max] = fn.gt("//span[contains(text(),'页次')]").match(/\/(\d+)/);
            let arr = fn.arr(max, (v, i) => imgDir + (i + 1) + ".jpg");
            let a = fn.ge("#img_src");
            if (a) a.outerHTML = `<div class="CustomPictureBox">${fn.ge("img", a).outerHTML}</div>`;
            return arr;
        },
        button: [4],
        insertImg: [".CustomPictureBox", 1],
        css: ".CustomPictureBox>img{max-width:100%}",
        category: "nsfw1"
    }, {
        name: "图宅网/咔咔西三/YouFreeX",
        url: {
            h: ["www.tuzac.com", "www.kkc3.com", "www.youfreex.com"],
            p: "/file/"
        },
        imgs: async () => {
            let a = fn.ge("#the-photo-link");
            if (a) a.outerHTML = a.innerHTML;
            let max = fn.attr("#auto-play", "total");
            let [id] = fn.attr("#auto-play", "data").match(/\d+/);
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            return fn.arr(max, (v, i) => fetch(`/api/?ac=get_album_images&id=${id}&num=${i + 1}`).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                return json.src;
            }));
        },
        button: [4],
        insertImg: ["#task,#fdp-photo,#fdp-photo-old", 2],
        customTitle: () => fn.dt({
            s: ".fc-text-content>h1",
            d: /(\[\d+P\]|\n|\(\d+P\))/gi
        }),
        css: ".content-container .content{margin-right:0px!important}",
        hide: ".ad-container,.fdp-click-area,.ad-side-right,.footer",
        category: "nsfw2"
    }, {
        name: "图宅网/咔咔西三/YouFreeX",
        url: {
            h: ["www.tuzac.com", "www.kkc3.com", "www.youfreex.com"]
        },
        hide: ".ad-container",
        category: "ad"
    }, {
        name: "七仙子图片",
        host: ["www.qixianzi.com"],
        reg: /^https?:\/\/www\.qixianzi\.com\/\w+\/\d+\.html$/,
        imgs: async () => {
            let a = fn.ge(".picture_content>a");
            if (a) a.outerHTML = a.innerHTML;
            await fn.getNP(".picture_content img", "//a[text()='下一页']", null, ".pagination", 0, null, 0);
            return fn.gae(".picture_content img");
        },
        button: [4],
        insertImg: [".picture_content", 2],
        endColor: "white",
        next: "//li[contains(text(),'上一篇')]/a",
        prev: "//li[contains(text(),'下一篇')]/a",
        customTitle: "h1.diy-h1",
        category: "nsfw1"
    }, {
        name: "七仙子图片M",
        host: ["www.qixianzi.com"],
        link: "https://www.qixianzi.com/e/wap/",
        reg: /^https?:\/\/www\.qixianzi\.com\/e\/wap\/show\.php\?/,
        imgs: ".arcmain img",
        button: [4],
        insertImg: [".arcmain", 1],
        customTitle: ".header>span",
        category: "nsfw1"
    }, {
        name: "嘿~色女孩",
        host: ["heysexgirl.com"],
        reg: /^https?:\/\/heysexgirl\.com\/archives\/\d+$/,
        imgs: () => {
            let max = fn.gt(".page-links>*:last-child");
            return fn.getImg(".entry-content p>a,.entry-content p>img", max, "4");
        },
        button: [4],
        insertImg: [".entry-container", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: "h1.page-title",
        category: "nsfw2"
    }, {
        name: "嘿~色女孩 分類自動翻頁",
        enable: 1,
        reg: [
            /^https?:\/\/heysexgirl\.com\/(page\/\d+)?$/,
            /^https?:\/\/heysexgirl\.com\/archives\/category\/\w+(\/page\/\d+)?$/
        ],
        init: () => fn.waitEle(".blog-posts-wrapper[style]"),
        autoPager: {
            mode: 1,
            waitEle: ".blog-posts-wrapper[style]",
            ele: ".blog-posts-wrapper",
            observer: ".blog-posts-wrapper",
            next: "span.current+a",
            re: ".nav-links",
            pageNum: () => nextLink.match(/\d+$/)[0]
        },
        openInNewTab: ".blog-posts-wrapper a:not([target=_blank])",
        css: ".blog-posts-wrapper article.has-post-thumbnail .entry-container{margin:0 auto 0 !important}",
        category: "autoPager"
    }, {
        name: "2LSP",
        host: ["2lsp.xyz"],
        reg: /^https?:\/\/2lsp\.xyz\/[^/]+\/$/,
        include: ".entry-content img[data-srcset]",
        exclude: ".content-hide-tips",
        init: () => fn.clearAllTimer(),
        observerClick: ".swal2-close",
        imgs: () => fn.gae(".entry-content img[data-srcset]").map(e => e.dataset.srcset),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev>a",
        prev: ".article-nav-next>a",
        customTitle: "h1.entry-title",
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "nsfw1"
    }, {
        name: "2LSP",
        host: ["2lsp.xyz"],
        reg: /^https?:\/\/2lsp\.xyz\//,
        observerClick: ".swal2-close",
        category: "none"
    }, {
        name: "性趣套图",
        host: ["tt.539765.xyz", "tt.xqtt.de"],
        url: {
            e: ["//div[@class='logo']/a[text()='性趣套图']", ".entry img"],
            p: "/e/action/ShowInfo.php"
        },
        imgs: async () => {
            if (fn.ge("embed[src*='sendvid']")) {
                let links = fn.gae("embed").map(e => e.src);
                let resArr = links.map(url => fn.xhrDoc(url).then(dom => fn.ge("video>source", dom).src));
                videoSrcArray = await Promise.all(resArr);
            }
            return fn.getImg(".entry img", fn.gt("a[title=总数]"), 8)
        },
        button: [4],
        insertImg: ["//div[@class='entry']//img/parent::*", 1],
        autoDownload: [0],
        next: "//p[contains(text(),'上一')]/a",
        prev: "//p[contains(text(),'下一')]/a",
        customTitle: ".contitle",
        css: ".main-content{margin-left:0px!important;}body{background:#ededed!important;}",
        hide: "aside.side",
        category: "nsfw2"
    }, {
        name: "苍井优图",
        host: ["34.28tyu.com", "w33.28rty.com", "33.28ery.com", "www.28wer.com", "www.028kkp.com", "sldlxz.com", "34.yuxiangcao.com", "282471.xyz", "284019.xyz"],
        url: {
            e: "//div[@class='logo']/a[text()='苍井优图']",
            p: "/e/action/ShowInfo.php"
        },
        imgs: "img[id^='aimg'],.entry img",
        button: [4],
        insertImg: [".entry", 2],
        autoDownload: [0],
        next: "//p[contains(text(),'上一')]/a",
        prev: "//p[contains(text(),'下一')]/a",
        customTitle: ".contitle",
        category: "nsfw2"
    }, {
        name: "YY美女图片/美眉大宝贝",
        host: ["www.yyzhenshun.com", "bb.meinvnews.com"],
        reg: /^https?:\/\/(www\.yyzhenshun\.com|bb\.meinvnews\.com)\/\d+\.html/i,
        imgs: () => {
            if (fn.ge(".ep-pages a")) {
                let [, max] = fn.gu("//a[text()='尾页']").match(/(\d+)\.html$/);
                return fn.getImg(".wzy_body img", max, 3);
            } else {
                return fn.gae(".wzy_body img[alt]");
            }
        },
        button: [4],
        insertImg: ["//p[img] | //p[strong[img]] | //div[@class='wzy_body']", 2],
        autoDownload: [0],
        next: "//li[contains(text(),'上一篇')]/a",
        prev: "//li[contains(text(),'下一篇')]/a",
        customTitle: ".wzy_tit",
        css: "header{margin-top:0px!important}.wzy_body{text-indent:unset!important}@media (max-width:768px){.wzy_body{margin:0px!important}}@media (max-width:768px){.neiye{margin:0px!important}}",
        hide: "body>section[id],a[href*=download]",
        category: "nsfw1"
    }, {
        name: "AVJB/The AV Porn",
        host: ["avjb.com", "theavporn.com"],
        link: "https://avjb.github.io/,https://avjb.com/albums/,https://theavporn.com/albums/",
        reg: /^https?:\/\/(avjb\.com|avjb\.fun|av\d{2,3}\.fun|bav\d{2,3}\.xyz|bbav\d{3}\.com|onebookcms\.com|theavporn\.com|thedemovideos\.com|thepa\d+\.\w+|the\d+\.\w+)\/(\w{2}\/)?albums\/\d+\/[\w-]+\//i,
        init: () => {
            new MutationObserver((mutations, observer) => {
                if (fn.ge(".chatra--webkit")) {
                    fn.ge(".chatra--webkit").remove();
                    observer.disconnect();
                }
            }).observe(document.body, MutationObserverConfig);
        },
        imgs: ".images>a",
        thums: ".images>a>img",
        button: [4],
        insertImg: [
            [".images", 2, ".images"], 2
        ],
        customTitle: ".headline>h1",
        hide: ".sponsor,.chatra--webkit",
        category: "nsfw2"
    }, {
        name: "AVJB 去廣告",
        reg: /^https?:\/\/(avjb\.com|avjb\.fun|av\d{2}\.fun|bav\d{2}\.xyz|bbav\d{3}\.com|onebookcms\.com|theavporn\.com|thedemovideos\.com|thepa\d+\.\w+|the\d+\.\w+)\//i,
        init: () => {
            new MutationObserver((mutations, observer) => {
                if (fn.ge(".chatra--webkit")) {
                    fn.ge(".chatra--webkit").remove();
                    observer.disconnect();
                }
            }).observe(document.body, MutationObserverConfig);
        },
        hide: ".sponsor,.chatra--webkit",
        category: "ad"
    }, {
        name: "Asian To Lick",
        host: ["asiantolick.com"],
        reg: /^https?:\/\/asiantolick\.com\/post/,
        init: () => fn.createImgBox(".spotlight-group", 2),
        imgs: () => {
            thumbnailSrcArray = fn.gae("div[data-src]>img").map(e => e.src);
            return fn.gae("div[data-src]").map(e => e.dataset.src);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".spotlight-group"], 2
        ],
        customTitle: "h1",
        hide: "#touch_to_see",
        category: "nsfw2"
    }, {
        name: "Models Vibe",
        host: ["www.modelsvibe.com"],
        reg: /^https?:\/\/www\.modelsvibe\.com\/[^/]+\/$/,
        include: ".td-post-content img",
        init: () => {
            let ele = fn.ge("//p[br and not(contains(text(),'[ad_1]'))]");
            if (!!ele) {
                ele = ele.cloneNode(true);
                fn.gae("img", ele).forEach(img => img.remove());
                let tE = fn.ge(".td-post-content");
                insertBefore(tE, ele);
            }
            let ele2 = fn.ge("//p[contains(text(),'Number of pictures')]");
            if (!!ele2) {
                if (ele2.previousSibling.tagName == "P") {
                    ele2.previousSibling.innerHTML = ele2.previousSibling.innerHTML + "<br>" + ele2.innerText;
                    let e = ele2.previousSibling;
                    let te = ele2.previousSibling.parentNode;
                    insertBefore(te, e);
                }
            }
        },
        imgs: () => {
            if (fn.ge(".page-nav")) {
                let max = fn.gt(".page-nav>*:last-child", 2);
                return fn.getImg(".td-post-content img", max, 4);
            } else if (fn.ge(".td-post-content img[srcset]")) {
                return fn.getImgSrcset(".td-post-content img");
            } else {
                return fn.gae(".td-post-content img");
            }
        },
        button: [4],
        insertImg: [".td-post-content .tdb-block-inner", 2],
        go: 1,
        customTitle: "h1.tdb-title-text",
        css: ".tdb_header_menu .tdb-menu .tdb-mega-menu-inactive,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive{pointer-events:auto!important}.tdb_header_menu .tdb-menu .tdb-mega-menu-inactive > ul,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive>ul{visibility:unset!important;opacity:1!important}.tdb_header_menu .tdb-normal-menu ul .tdb-menu-item{list-style-type:auto!important}",
        category: "nsfw1"
    }, {
        name: "Models Vibe - 分類自動翻頁",
        reg: /^https?:\/\/www\.modelsvibe\.com\/(albums\/.+)?(page\/\d+\/)?$/,
        init: () => {
            /page\/\d+\//.test(fn.lp) ? currentPageNum = Number(fn.lp.match(/\/page\/(\d+)/)[1]) : currentPageNum = 1;
        },
        autoPager: {
            ele: ".td_flex_block:not(.td-flex-radius),.td_block_inner.tdb-block-inner",
            observer: ".td-cpt-post",
            next: () => {
                let url = siteUrl.replace(/page\/\d+\/?/, "") + `page/${currentPageNum += 1}/`;
                return url;
            },
            re: ".page-nav,.td-load-more-wrap",
            stop: (dom) => !!fn.ge(".td-404-title", dom),
            bF: (dom) => {
                fn.gae("span[data-img-url]", dom).forEach(span => {
                    span.classList.add("td-animation-stack-type0-2");
                    span.style.backgroundImage = `url("${span.dataset.imgUrl}")`;
                });
            },
            pageNum: () => currentPageNum
        },
        openInNewTab: ".td-cpt-post a:not([target=_blank])",
        css: ".tdi_60.td-a-rec{display:none!important;}.tdb_header_menu .tdb-menu .tdb-mega-menu-inactive,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive{pointer-events:auto!important}.tdb_header_menu .tdb-menu .tdb-mega-menu-inactive > ul,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive>ul{visibility:unset!important;opacity:1!important}.tdb_header_menu .tdb-normal-menu ul .tdb-menu-item{list-style-type:auto!important}",
        category: "autoPager"
    }, {
        name: "Models Vibe - 修正選單CSS和去廣告",
        reg: /^https?:\/\/www\.modelsvibe\.com\//,
        css: ".tdi_60.td-a-rec{display:none!important;}.tdb_header_menu .tdb-menu .tdb-mega-menu-inactive,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive{pointer-events:auto!important}.tdb_header_menu .tdb-menu .tdb-mega-menu-inactive > ul,.tdb_header_menu .tdb-menu .tdb-menu-item-inactive>ul{visibility:unset!important;opacity:1!important}.tdb_header_menu .tdb-normal-menu ul .tdb-menu-item{list-style-type:auto!important}",
        category: "ad"
    }, {
        name: "Digital AI Gallery",
        host: ["larose.vip"],
        reg: /^https?:\/\/larose\.vip\/[^\/]+\/$/,
        init: () => fn.createImgBox(".entry-content p:has(>img)", 1),
        imgs: ".entry-content img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".entry-content p:has(>img)"], 2
        ],
        go: 1,
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: () => fn.dt({
            s: ".wp-block-post-title",
            d: " – Larose.VIP"
        }),
        category: "nsfw2"
    }, {
        name: "Goddess247/BestPrettyGirl/Girl Sweetie/Girl Dreamy/BestGirlSexy",
        url: () => fn.checkUrl({
            h: ["goddess247.com", "bestprettygirl.com", "girlsweetie.com", "girldreamy.com", "bestgirlsexy.com"]
        }) && !/^\/tag\/|^\/category\//.test(fn.lp),
        init: () => fn.createImgBox("//p[img] | //img[@class='aligncenter size-full']", 1),
        imgs: ".elementor-widget-container p img[alt],.elementor-widget-container img.aligncenter.size-full,.elementor-widget-theme-post-content img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//p[img] | //img[@class='aligncenter size-full']"], 2
        ],
        go: 1,
        customTitle: () => fn.title(/ - Goddess247| - BestPrettyGirl| - Girl Sweetie| - Girl Dreamy| - BestGirlSexy/),
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "WordPress樣板",
        links: [
            "https://niwatori.my.id/category/uncategorized/",
            "https://quenbox.top/?cat=1",
            "https://nekobox.top/index.php/category/blog/"
        ],
        url: {
            e: [".entry-content", ".wp-block-gallery img", ".post-navigation .nav-links"]
        },
        imgs: () => fn.getImgSrcset(".wp-block-gallery img"),
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Sexy Girl Pictures",
        url: {
            h: "beautypics.org",
            p: /^\/archives\/\d+$/,
            e: ".page-content img"
        },
        imgs: () => {
            if (fn.ge(".page-content img[srcset]")) {
                return fn.getImgSrcset(".page-content img[srcset]");
            } else {
                return fn.gae(".page-content img");
            }
        },
        button: [4],
        insertImg: [".page-content", 2],
        customTitle: () => fn.title(" – Sexy Girl Pictures"),
        category: "nsfw1"
    }, {
        name: "SexyGirl",
        host: ["sexygirl.one"],
        reg: /^https?:\/\/sexygirl\.one\/\w+\/[^\/]+\/$/,
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".s-title",
        category: "nsfw1"
    }, {
        name: "Girl Atlas",
        host: ["www.koipb.com", "koipb.com"],
        url: {
            h: "koipb.com",
            p: "/album"
        },
        init: () => fn.createImgBox(".gallery", 1),
        imgs: ".gallery a[data-fancybox]",
        thums: ".gallery img",
        customTitle: ".header-title",
        fancybox: {
            blacklist: 1
        },
        category: "nsfw1"
    }, {
        name: "Danryoku",
        host: ["danryoku.com"],
        reg: /^https?:\/\/danryoku\.com\/[^\/]+\/$/,
        imgs: ".dynamic-entry-content img",
        button: [4],
        insertImg: [".dynamic-entry-content", 2],
        go: 1,
        customTitle: "h1.gb-headline",
        category: "nsfw1"
    }, {
        name: "MINISUKA",
        host: ["minisuka.top"],
        reg: /^https?:\/\/minisuka\.top\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: ".wp-block-gallery img",
        button: [4],
        insertImg: [
            [".entry-content", 0, ".wp-block-gallery"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "eyval.net",
        host: ["www.eyval.net"],
        reg: /^https?:\/\/www\.eyval\.net\/\d+\/\d+\/[\w-]+\.html/,
        imgs: async () => {
            let imgsSrcArr = fn.gae(".entry-content a[href*=blog]").map(a => {
                let arr = a.href.split("/");
                if (arr.length === 9) {
                    arr[7] = "s16000";
                    return arr.join("/");
                } else {
                    return a.href;
                }
            });
            thumbnailSrcArray = imgsSrcArr.map(e => e.replace("/s16000/", "/w100/"));
            return imgsSrcArr;
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "eyval.net - 分類自動翻頁",
        host: ["www.eyval.net"],
        reg: /^https?:\/\/www\.eyval\.net\//,
        autoPager: {
            mode: 1,
            ele: ".blog-posts>.date-outer",
            next: "a.blog-pager-older-link",
            observer: ".blog-posts>.date-outer",
            re: "#blog-pager",
            stop: (dom) => !fn.ge(".date-outer", dom),
            pageNum: () => (currentPageNum += 1)
        },
        openInNewTab: ".date-outer a[href]:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "PhimVu/Kutekorean.Com",
        host: ["m.phimvuspot.com", "m.kutekorean.com"],
        reg: [
            /^https?:\/\/m\.phimvuspot\.com\/\w+\/\w+\.cfg/i,
            /^https?:\/\/m\.kutekorean\.com\/[^\.]+\.html/i
        ],
        imgs: async () => {
            let max;
            try {
                [max] = fn.gt("h1.post-title").match(/\d+$/);
            } catch {
                max = 1;
            }
            return /\?m=1/.test(siteUrl) ? await fn.getImg(".post-content img", max, "8") : await fn.getImg(".post-content img", max);
        },
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: () => fn.dt({
            s: ".post-title",
            d: [
                /[\s\|]+Page[\s\d\/]+/,
                "E-CUP"
            ]
        }),
        category: "nsfw2"
    }, {
        name: "Poringa!",
        host: ["www.poringa.net", "m.poringa.net"],
        reg: /^https?:\/\/(www|m)\.poringa\.net\/posts\//i,
        imgs: ".post-content img,.content-post-img>img",
        button: [4],
        insertImg: [".post-content,.content.short", 3],
        customTitle: ".post-title,h1.title",
        category: "nsfw2"
    }, {
        name: "HayVn.Net",
        url: {
            h: "www.hayvn.net",
            p: /^\/\d+\/\d+\/[^\.]+\.html$/,
            e: ".separator>a"
        },
        imgs: () => fn.gau(".separator>a").map(u => u.replace("/s1600/", "/s16000/")),
        button: [4],
        insertImg: [
            [".separator", 1, ".separator"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "HayVn.Net",
        url: {
            h: "www.hayvn.net"
        },
        imgs: ".entry-content img",
        customTitle: ".entry-title",
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "YeuGai.Net",
        host: ["yeugai.org"],
        reg: /^https?:\/\/yeugai\.org\/[^\/]+\/$/i,
        init: async () => {
            await fn.waitEle(".mirror-image img");
            fn.run("jQuery(document).off();");
            let e = fn.ge(".relpost-thumb-wrapper");
            let f = fn.ge(".penci-entry-footer");
            if (e && f) {
                insertBefore(f, e);
            }
        },
        imgs: () => {
            videoSrcArray = fn.gau("video>source[type='video/mp4']+a[href*='.mp4']");
            if (fn.ge(".mirror-image img[src*=blog]")) {
                let imgsSrcArr = fn.gae(".mirror-image img[src*=blog]").map(e => {
                    let arr = e.src.split("/");
                    if (arr.length === 9) {
                        arr[7] = "s16000";
                        return arr.join("/");
                    } else {
                        return e.src;
                    }
                });
                thumbnailSrcArray = imgsSrcArr.map(e => e.replace("/s16000/", "/w100/"));
                return imgsSrcArr;
            } else {
                return fn.gae(".mirror-image img");
            }
        },
        capture: () => _this.imgs(),
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /^Ảnh.+Xinh\s|^Clip.+Em\s/
        }),
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "sekushipic",
        host: ["sekushipic.blogspot.com"],
        reg: /^https?:\/\/sekushipic\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        imgs: ".separator>a",
        thums: ".separator img",
        button: [4],
        insertImg: [
            [".separator", 1, ".separator,.separator~br"], 2
        ],
        autoDownload: [0],
        next: "a.blog-pager-older-link",
        prev: "a.blog-pager-newer-link",
        customTitle: ".entry-title",
        hide: ".post-header",
        category: "nsfw1"
    }, {
        name: "IDOL AREA",
        host: ["idolarea.blogspot.com"],
        reg: /^https?:\/\/idolarea\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        imgs: ".separator>a",
        thums: ".separator img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "Nude Models",
        reg: () => !hasTouchEvent && fn.lh === "blognudemodels.blogspot.com",
        init: () => fn.waitEle("#gadget-dock"),
        imgs: ".separator>a",
        capture: ".separator>a",
        SPA: () => document.URL.includes(".html"),
        customTitle: "title",
        observerTitle: true,
        category: "nsfw2"
    }, {
        name: "Nude Models",
        reg: /^https?:\/\/blognudemodels\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html\?m=1$/,
        init: () => fn.waitEle(".separator img"),
        imgs: ".separator>a",
        button: [4],
        insertImg: [
            [".separator", 1, ".separator,.separator~br"], 2
        ],
        customTitle: "title",
        category: "nsfw2"
    }, {
        name: "Curvy Asian",
        host: ["curvyasian.blogspot.com"],
        reg: /^https?:\/\/curvyasian\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        imgs: "#blogger-gallery a.item-link",
        thums: "#blogger-gallery a.item-link img",
        button: [4],
        insertImg: ["#blogger-gallery", 2],
        autoDownload: [0],
        next: "a.blog-pager-older-link",
        prev: "a.blog-pager-newer-link",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "500 Brothers",
        host: ["500brothersfun.blogspot.com"],
        reg: /^https?:\/\/500brothersfun\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        init: () => fn.createImgBox(".separator", 1),
        imgs: () => fn.gau(".separator>a").map(u => u.replace("/s1600/", "/s16000/")),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".separator~br,.separator"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "min: archive/True Pic",
        host: ["min-bin.blogspot.com", "truepichk.blogspot.com"],
        reg: /^https?:\/\/(min-bin|truepichk)\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        imgs: () => fn.gau(".separator>a").map(u => u.replace("/s1600/", "/s16000/")),
        button: [4],
        insertImg: [".post-body", 2],
        autoDownload: [0],
        next: "a.blog-pager-older-link",
        prev: "a.blog-pager-newer-link",
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "Tabakus Gallery",
        reg: /^https?:\/\/tabakus\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        init: async () => {
            await fn.waitEle(".separator img");
            fn.createImgBox(".separator:has(>a>img[height])", 1);
        },
        imgs: ".separator>a:has(>img[height])",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".separator:has(>a>img),.separator~br"], 2
        ],
        customTitle: ".post_item>h1",
        category: "nsfw2"
    }, {
        name: "Graphis",
        host: ["20sanctuary-grahpis.blogspot.com"],
        reg: /^https?:\/\/20sanctuary-grahpis\.blogspot\.com\/\d+\/\d+\/[^\.]+\.html/,
        imgs: () => {
            thumbnailSrcArray = fn.gae(".separator>a img").map(e => e.src.replace("/s320/", "/w100/"));
            return fn.gau(".separator>a").map(u => u.replace("/s1600/", "/s16000/"));
        },
        button: [4],
        insertImg: [".post-body", 2],
        customTitle: ".post_item>h1,.entry-titleS",
        category: "nsfw2"
    }, {
        name: "Asia Idols",
        host: ["asiaidols.wordpress.com"],
        reg: /^https?:\/\/asiaidols\.wordpress\.com\/\d+\/\d+\/\d+\/[^\/]+\/$/,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("img[alt='image host']");
            let imageHostLinks = fn.gau("//a[img[@alt='image host']]");
            return fn.getImageHost(imageHostLinks);
        },
        button: [4],
        insertImg: [".entry-content", 3],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "Asia Porn Photo/Asses Photo/Nuded Photo",
        host: ["www.asiapornphoto.com", "www.assesphoto.com", "www.nudedxxx.com"],
        reg: /^https?:\/\/www\.(asiapornphoto|assesphoto|nudedxxx)\.com\/[^\.]+\.shtml$/,
        init: () => fn.createImgBox(".image-container", 1),
        imgs: ".image-container img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".image-container"], 2
        ],
        customTitle: ".container h1",
        category: "nsfw2"
    }, {
        name: "BingMM",
        url: {
            h: "bingmm.com"
        },
        SPA: () => document.URL.includes(".html"),
        observerURL: true,
        imgs: async () => {
            fn.createImgBox(".entry-content p:has(>img)", 1);
            return fn.gae(".entry-content img");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".entry-content p:has(>img)"], 2
        ],
        autoDownload: [0],
        next: () => fn.gu("a[rel=prev]"),
        prev: 1,
        customTitle: "#post-title",
        category: "nsfw1"
    }, {
        name: "Chinese Nude Art Photos",
        host: ["chinesenudeart.blogspot.com"],
        reg: /^https?:\/\/chinesenudeart\.blogspot\.com\/\d+\/\d+\/[\w-]+\.html/i,
        imgs: ".entry-content a[href]",
        thums: ".entry-content a[href]>img",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: "a.blog-pager-older-link",
        prev: "a.blog-pager-newer-link",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: [
                "Chinese beautiful model Amanda -",
                "Beautiful Chinese girl -",
                "Beautiful Chinese girl ",
                "Chinese Beautiful girl -",
                " |18+ Nude model Amateur"
            ]
        }),
        css: "@media only screen and (max-width:479px){#outer-wrapper{margin:0px!important;width:100%!important}}",
        category: "nsfw1"
    }, {
        name: "CUTE GIRLS ADDICT",
        host: ["cutegirlsaddict.blogspot.com"],
        reg: /^https?:\/\/cutegirlsaddict\.blogspot\.com\/\d+\/\d+\/[a-z0-9-]+\.html/i,
        imgs: async () => {
            thumbnailSrcArray = fn.gae(".separator>a>img").map(e => {
                let arr = e.src.split("/");
                arr[7] = "w100";
                return arr.join("/");
            });
            let srcArr = fn.gau(".separator>a");
            let firstSrcArr = srcArr[0].split("/");
            if (firstSrcArr.length === 9) {
                firstSrcArr[7] = "s16000";
                let testMaxSrc = firstSrcArr.join("/");
                let obj = await fn.checkImgStatus(testMaxSrc);
                debug("\n確認圖片狀態\n", obj);
                if (obj.ok) {
                    srcArr = srcArr.map(src => {
                        let arr = src.split("/");
                        arr[7] = "s16000";
                        return arr.join("/");
                    });
                    return srcArr;
                } else {
                    return srcArr;
                }
            } else {
                return srcArr;
            }
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: "h1.post-title,h3.entry-title",
        category: "nsfw1"
    }, {
        name: "4KUP",
        host: ["4kup.net"],
        reg: /^https?:\/\/4kup\.net\/(?!getlink)[^\/]+\/$/,
        exclude: "//button[text()='Click here to continue']",
        imgs: "a.thumb-photo",
        thums: "a.thumb-photo>img",
        button: [4],
        insertImg: ["#gallery", 2],
        go: 1,
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: "a[rel=next]",
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "Space of Miss Beautiful",
        url: {
            h: "spacemiss.com",
            e: [".td-post-content .tdb-block-inner.td-fix-index", ".tdb-title-text"]
        },
        init: async () => {
            let img = await fn.waitEle(".td-post-content .tdb-block-inner.td-fix-index img");
            let video = fn.ge(".td-post-content .tdb-block-inner.td-fix-index>center:has(>iframe)");
            let p = fn.ge("p.has-text-align-center");
            if (p) {
                tempEles.push(p.cloneNode(true));
            }
            if (img && video) {
                tempEles.push(video);
            }
        },
        imgs: () => {
            videoSrcArray = fn.gae("video>source[type='video/mp4']").map(e => e.src);
            return fn.gae(".td-post-content .tdb-block-inner.td-fix-index img").map(e => decodeURIComponent(e.src));
        },
        button: [4],
        insertImg: [".td-post-content .tdb-block-inner.td-fix-index", 2, 1000],
        insertImgAF: (parent) => {
            if (tempEles.length > 0) {
                for (let e of tempEles) {
                    insertBefore(parent.firstChild, e);
                }
            }
        },
        go: 1,
        customTitle: () => fn.gt(".tdb-title-text").replace(/\d+P[\d\s]+V|\d+P([\d\s\+P]+)?/, "").replaceAll("|", "-").trim(),
        hide: ".td-a-ad",
        //downloadVideo: true,
        category: "nsfw1"
    }, {
        name: "呦糖社",
        host: ["www.nicesss.com"],
        reg: /^https?:\/\/www\.nicesss\.com\/archives\/[\w-]+\/([\w-]+\/)?\d+\.html$/i,
        init: () => fn.createImgBox(".entry-content>img[data-srcset],.entry-content>p>img[data-srcset]", 1),
        imgs: () => fn.gae(".entry-content>img[data-srcset],.entry-content>p>img[data-srcset]").map(e => e.dataset.srcset),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".entry-content>img[data-srcset],.entry-content>p:has(>img[data-srcset])"], 2
        ],
        customTitle: ".entry-title>a",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "呦糖社C+",
        host: ["www.nicezzz.com", "www.nicekkk.com"],
        reg: [
            /^https?:\/\/www\.nicezzz\.com\/archives\/[\w-]+\/([\w-]+\/)?\d+\.html$/i,
            /^https?:\/\/www\.nicekkk\.com\/archives\/[\w-]+\/[\w-]+\.html$/i
        ],
        init: () => fn.createImgBox(".wp-posts-content>img,.wp-posts-content>p>img", 1),
        imgs: ".wp-posts-content>img,.wp-posts-content>p>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".wp-posts-content>img,.wp-posts-content>p:has(>img)"], 2
        ],
        customTitle: ".article-title>a",
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "nsfw1"
    }, {
        name: "Fliporn",
        host: ["fliporn.biz"],
        reg: /^https?:\/\/fliporn\.biz\/videos\//,
        include: "//span[@class='entry-category']/a[text()='亚洲贴图' or text()='写真' or text()='动漫贴图' or text()='性感贴图' or text()='欧美贴图' or text()='网友自拍']",
        init: () => fn.createImgBox("//center[img] | //center[p[img]] | //div[@id='conttpc' and img] | //div[@id='conttpc' and p[img]] | //div[@class='entry-content']//p[img] | //div[figure[div[img]]]", 1),
        imgs: () => fn.gae(".entry-content img").map(e => e.dataset.src ? e.dataset.src.replace(/\?w=858(&ssl=1)?/, "") : e.src.replace("%3C/center%3E%3C/p%3E%3Cdiv%20class=", "").replace(/\?w=858(&ssl=1)?/, "")),
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//center[img] | //center[p[img]] | //div[@id='conttpc' and img] | //div[@id='conttpc' and p[img]] | //div[@class='entry-content']//p[img] | //div[figure[div[img]]]"], 2
        ],
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /\n|[\s\d]+$/g
        }),
        category: "nsfw2"
    }, {
        name: "91图录",
        host: ["www.91tulu.com"],
        reg: /^https?:\/\/www\.91tulu\.com\/\d+\.html$/,
        imgs: ".wp-posts-content img",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: ".article-title",
        css: ".wp-posts-content{max-height:unset!important}",
        category: "nsfw1"
    }, {
        name: "91HD视频",
        host: ["91hd.com"],
        reg: /^https?:\/\/www\.91hd\w+\.\w+\/[^\/]+\/$/,
        link: "https://www.91hdzq.cc/category/%E6%88%90%E4%BA%BA%E8%89%B2%E5%9B%BE/",
        include: ".image-container",
        imgs: () => fn.getImgA(".image-container img", ".post-nav-links>a"),
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: ".post-title",
        css: "body{padding:unset!important}.sidebar-secondary{top:70px!important}",
        hide: ".tuadx,body>*[id][style]:has(>img)",
        category: "nsfw2"
    }, {
        name: "91HD视频 AD",
        reg: /^https?:\/\/www\.91hd\w+\.\w+\//,
        css: "body{padding:unset!important}.sidebar-secondary{top:70px!important}",
        hide: ".tuadx,body>*[id][style]:has(>img)",
        category: "ad"
    }, {
        name: "淫淫小说写真馆",
        host: ["books.xxgirls.vip"],
        url: {
            h: "xxgirls",
            p: "artdetail"
        },
        imgs: "#read_tpc img,.hl-article-content img",
        button: [4],
        insertImg: ["#read_tpc,.hl-article-content", 2],
        autoDownload: [0],
        next: ".hl-next",
        prev: ".hl-prev",
        customTitle: () => fn.dt({
            s: ".hl-article-title",
            d: /-[\d\s]+P?$|\(\d+P\)?.*$|【\d+P】$/i
        }),
        category: "nsfw2"
    }, {
        name: "成人图片 Qinimg",
        host: ["www.qinimg.com"],
        reg: /^https?:\/\/www\.qinimg\.com\/image\/\d+\.html$/,
        imgs: () => {
            thumbnailSrcArray = fn.gae("#image a>img").map(e => e.getAttribute("img") != "" ? e.getAttribute("img") : e.src);
            return fn.gae("#image a");
        },
        button: [4],
        insertImg: [
            ["#image", 2], 2
        ],
        go: 1,
        customTitle: ".box>h1",
        category: "nsfw2"
    }, {
        name: "Elite Babes格式",
        host: ["www.elitebabes.com", "pmatehunter.com", "www.jperotica.com", "www.metarthunter.com", "www.femjoyhunter.com"],
        reg: /^https?:\/\/(www\.)?(elitebabes|pmatehunter|jperotica|metarthunter|femjoyhunter)\.com\/.+\//,
        exclude: "#content video",
        imgs: ".list-gallery a[data-fancybox]",
        thums: ".list-gallery a[data-fancybox]>img",
        button: [4, "23%"],
        insertImg: [
            [".list-gallery", 2], 2
        ],
        go: 1,
        customTitle: "#content>p",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw2"
    }, {
        name: "Naked Women Pics/VIEW GALS/Hot Pussy Pics/Busty Women Pics",
        host: ["nakedwomenpics.com", "viewgals.com", "hotpussypics.com", "bustypassion.com"],
        reg: [
            /^https?:\/\/nakedwomenpics\.com\/pics\/[^\/]+\/$/,
            /^https?:\/\/viewgals\.com\/pics\/[^\/]+\/$/,
            /^https?:\/\/hotpussypics\.com\/pics\/[^\/]+\/$/,
            /^https?:\/\/bustypassion\.com\/pics\/[^\/]+\/$/,
        ],
        imgs: "a.ss-image",
        button: [4],
        insertImg: [".m-content-con", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "TeenPussyPics.com",
        host: ["teenpussypics.com"],
        reg: /^https?:\/\/teenpussypics\.com\/images\/\d+\/$/,
        imgs: "//div[@id='lucrezia']//a[img[@data-src]]",
        button: [4],
        insertImg: ["#lucrezia", 2],
        customTitle: "h1",
        css: "#lucrezia{height:auto!important}",
        category: "nsfw2"
    }, {
        name: "Wb-express porno",
        url: {
            h: "wb-express.ru"
        },
        imgs: ".pw-description img",
        button: [4],
        insertImg: [".pw-description", 2],
        customTitle: ".page-wrap h1",
        category: "nsfw2"
    }, {
        name: "NSFWalbum",
        host: ["nsfwalbum.com"],
        reg: /^https?:\/\/nsfwalbum\.com\/album\/\d+$/,
        init: () => fn.createImgBox(".album", 2),
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".albumPhoto");
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            return fn.gae(".album .item>a").map(async (a, i, arr) => {
                let img = fn.ge("img", a);
                let src = img.dataset.src ?? img.src;
                if (/imx\.to/.test(src)) {
                    return src.replace("/t/", "/i/");
                } else {
                    await delay(100 * i);
                    return fetch(a.href).then(res => res.text()).then(async text => {
                        await delay(200 * i);
                        let id = a.href.split("/").at(-1);
                        let spirit = fn.run(text.match(/var\sspirit\s?=\s?([^;]+);/)[1]);
                        let api = `/backend.php?&spirit=${spirit}&photo=${id}`;
                        return fetch(api).then(res => res.json()).then(json => {
                            fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${arr.length}`, 0);
                            return json[0];
                        });
                    });
                }
            });
        },
        button: [4, "24%", 3],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".album"], 2
        ],
        customTitle: () => fn.dt({
            s: ".gallery_name",
            d: /\sx\d{1,4}.*|-\sx\d{1,4}.*|-\s\d{1,4}x.*|-[\d\s]+pic.+| - \d{2}.\d{2}.\d{4}.*|\(x\d+\).*|[\d\s]+pics.*|\([\w\s\.\+,]+\)|\|[\s\dx]+\|.*/i
        }),
        category: "nsfw2"
    }, {
        name: "Adult photo sets",
        host: ["adultphotosets.best"],
        reg: /^https?:\/\/adultphotosets\.best\/index\.php\?newsid=\d+$/i,
        include: "//a[img[@data-src][@data-maxwidth]]",
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("//img[@data-src][@data-maxwidth]");
            let URLs = fn.gau("//a[img[@data-src][@data-maxwidth]]");
            return fn.getImageHost(URLs);
        },
        button: [4],
        insertImg: [
            ["//a[img[@data-src][@data-maxwidth]]", 2, "//a[img[@data-src][@data-maxwidth]]"], 2
        ],
        customTitle: ".title",
        category: "nsfw2"
    }, {
        name: "Pics-X",
        host: ["pics-x.com"],
        reg: /^https?:\/\/pics-x\.com\/gallery\/\d+\//i,
        init: () => fn.waitEle("#images-container img"),
        imgs: "#images-container img",
        button: [4],
        insertImg: ["#images-container", 2],
        customTitle: () => fn.title(" | Pics-X"),
        category: "nsfw2"
    }, {
        name: "Redpics",
        host: ["www.redpics.top"],
        reg: /^https?:\/\/www\.redpics\.top\/(japanese|korean|chinese|hardcore|softcore|lesbian)\/[\w-]+$/,
        imgs: () => {
            let aEles = fn.gae("#extra-content>a,.post-content a");
            thumbnailSrcArray = aEles.map(a => fn.ge("img", a).src);
            let URLs = aEles.map(a => a.href);
            return fn.getImageHost(URLs);
        },
        button: [4],
        insertImg: ["#post-content", 3],
        autoDownload: [0],
        next: () => fn.gu("//div[text()='Next Post']/following-sibling::div[1]/a"),
        prev: 1,
        customTitle: "#photoset-title",
        category: "nsfw2"
    }, {
        name: "SXYPIX",
        host: ["sxypix.com"],
        reg: /^https?:\/\/sxypix\.com\/w\/\w+$/i,
        init: () => fn.createImgBox(".gallgrid", 2),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let pid = fn.ge("div.grid-item").dataset.photoid;
            let aid = fn.gu(".gall_info_panel a.tdn").split("/").at(-1);
            let ghash = fn.ge(".gall_cp[data-ghash]").dataset.ghash;
            let total = Number(fn.gt(".ip_count"));
            let pages = Math.ceil(total / 36);
            let headers = {
                "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                "x-requested-with": "XMLHttpRequest"
            };
            let resArr = fn.arr(pages, (v, i) => fetch("/php/apg.php", {
                "headers": headers,
                "body": `mode=w&param={"page":${(i + 1)},"ghash":"${ghash}"}`,
                "method": "POST"
            }).then(res => res.json()).then(json => json.r));
            thumbnailSrcArray = await Promise.all(resArr).then(data => data.flat()).then(arr => {
                let html = arr.join("");
                let dom = fn.doc(html);
                return fn.gae(".gall_cover", dom).map(e => e.dataset.src ?? e.src);
            });
            return fetch("/php/gall.php", {
                "headers": headers,
                "body": `x=x&pid=${pid}&aid=${aid}&ghash=${ghash}&width=1920`,
                "method": "POST"
            }).then(res => res.json()).then(json => {
                let arr = json.r;
                let html = arr.join("");
                let dom = fn.doc(html);
                return fn.gae("div.gall_pix_el", dom);
            });
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".grid"], 2
        ],
        endColor: "white",
        customTitle: ".gall_title",
        category: "nsfw2"
    }, {
        name: "ЯУстал",
        url: () => fn.checkUrl({
            h: "yaustal.com"
        }) && fn.lp !== "/",
        exclude: "#bottom-nav",
        imgs: "a.highslide",
        customTitle: ".blog_tit",
        category: "nsfw2"
    }, {
        name: "МЕДИА ТРЕНД",
        link: "https://jb5.ru/shoubiz/onlyfans-sliv/",
        url: {
            h: "jb5.ru",
            e: ".entry-content img[srcset]"
        },
        imgs: () => fn.getImgSrcset(".gallery-item a,span[itemprop=image]>img,.entry-content img[srcset]"),
        capture: () => _this.imgs(),
        customTitle: ".entry-title>h1",
        category: "nsfw2"
    }, {
        name: "alt Goddess",
        url: {
            h: "altgoddess.com"
        },
        init: () => {
            if ("adde_modal_detector" in _unsafeWindow) {
                _unsafeWindow.adde_modal_detector(false);
            }
        },
        imgs: "a[data-fancybox],.mpc-grid-images img",
        autoDownload: [0],
        next: ".mk-post-next",
        prev: ".mk-post-prev",
        customTitle: ".page-title",
        observerClick: ".adde_modal_detector-action-btn-close",
        category: "nsfw2"
    }, {
        name: "alt Goddess",
        url: {
            h: "altgoddess.com"
        },
        init: () => {
            if ("adde_modal_detector" in _unsafeWindow) {
                _unsafeWindow.adde_modal_detector(false);
            }
        },
        observerClick: ".adde_modal_detector-action-btn-close",
        category: "ad"
    }, {
        name: "Фото идеи и картинки",
        url: {
            h: "fotoslava.ru",
            e: ".entry-title"
        },
        imgs: ".gallery-item img",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /\([\d\s]+фото\)|\(\d+[\sфотfots]+\)|\d+[\sфотfots]+/
        }),
        category: "nsfw1"
    }, {
        name: "Картинки и фото",
        url: {
            h: "cojo.ru",
            e: ".entry-title"
        },
        imgs: ".wp-block-image img",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /\([\d\s]+фото\)|\(\d+[\sфотfots]+\)|\d+[\sфотfots]+/
        }),
        setFancybox: true,
        category: "nsfw1"
    }, {
        name: "geekfan.site",
        url: {
            h: "geekfan.site",
            e: [".sgb-data,.entry-content img", ".entry-title"]
        },
        imgs: () => {
            let data = fn.ge(".sgb-data");
            if (data) {
                return fn.gae(".sgb-data").flatMap(data => {
                    let text = data.textContent;
                    let json = JSON.parse(text);
                    return json.images.map(e => e.url.replace("-scaled", ""));
                });
            } else {
                return fn.gae(".entry-content img");
            }
        },
        capture: () => _this.imgs(),
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: [
                /\(\d+[\sфотfots]+\)|[\d\sфотfots]+/,
                "слив",
                "фото",
                /[\d\s]+$/
            ]
        }),
        category: "nsfw1"
    }, {
        name: "TIỆM TẠP HÓA KỲ DIỆU",
        url: {
            h: "clannadhouse.com",
            p: /^\/[^\/]+\/$/
        },
        imgs: "a.fox-lightbox-gallery-item",
        customTitle: ".post-title",
        category: "nsfw1"
    }, {
        name: "Sex Pics Space",
        url: {
            h: "www.sex-pics.xyz",
            p: "/view/"
        },
        init: () => fn.remove("div:has(>.sticky-top)"),
        imgs: "#photos img",
        button: [4],
        insertImg: ["#photos", 2],
        customTitle: "h1",
        css: ".col-12{flex:0 0 100%!important;max-width:100%!important}",
        category: "nsfw1"
    }, {
        name: "Nevsepic",
        host: ["nevsepic.com.ua"],
        url: {
            h: "nevsepic",
            e: ["//div[@class='full-comms']/a[text()='18+']", ".full-text img,a.highslide", ".share_widget"]
        },
        init: () => fn.createImgBox(".share_widget", 1),
        imgs: async () => {
            let srcs;
            let pages = fn.ge(".bottom-nav");
            if (pages) {
                let last = fn.ge(".navigation>a:last-child");
                let max = last.innerText;
                let url = last.pathname;
                let links = fn.arr(max, (v, i) => i == 0 ? fn.url : url.replace(/(\/page\,)(\d+\,)/, `$1${(i + 1) + ","}`));
                srcs = await fn.getImgA("a.highslide,.full-text img", links);
            } else {
                srcs = fn.getImgSrcArr("a.highslide,.full-text img");
            }
            return srcs.filter(src => !src.includes("/thumbs/") && !src.includes("attach.png"));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".full-text img:not(.FullPictureLoadImage,[src$='attach.png']),.full-text img:not(.FullPictureLoadImage,[src$='attach.png'])~br,a.highslide,a.highslide~br,.bottom-nav"], 2
        ],
        customTitle: ".f-page-title",
        category: "nsfw2"
    }, {
        name: "Nevsepic",
        host: ["nevsepic.com.ua"],
        url: {
            h: "nevsepic",
            e: [".full-text img,a.highslide", ".share_widget"]
        },
        imgs: async () => {
            let srcs;
            let pages = fn.ge(".bottom-nav");
            if (pages) {
                let last = fn.ge(".navigation>a:last-child");
                let max = last.innerText;
                let url = last.pathname;
                let links = fn.arr(max, (v, i) => i == 0 ? fn.url : url.replace(/(\/page\,)(\d+\,)/, `$1${(i + 1) + ","}`));
                srcs = await fn.getImgA("a.highslide,.full-text img", links);
            } else {
                srcs = fn.getImgSrcArr("a.highslide,.full-text img");
            }
            return srcs.filter(src => !src.includes("/thumbs/") && !src.includes("attach.png"));
        },
        capture: () => _this.imgs(),
        button: [4],
        customTitle: ".f-page-title",
        category: "nsfw2"
    }, {
        name: "DTF",
        url: {
            h: "dtf.ru"
        },
        observerURL: true,
        SPA: () => !!fn.ge(".comments"),
        imgs: () => {
            let [post] = fn.gae(".content__blocks");
            if (post) {
                fn.createImgBox(".content", 1);
                //let medias = Object.values(JSON.parse(_unsafeWindow.__INITIAL_STATE__)).find(obj => !!obj.blocks)?.blocks.filter(item => item.type === "media");
                //return medias?.map(e => "https://leonardo.osnova.io/" + e.data.items[0].image.data.uuid);
                let imgs = fn.gae(".block-wrapper.block-wrapper--media img", post);
                return imgs.map(e => {
                    let id = e.src.split("/")[3];
                    return "https://leonardo.osnova.io/" + id;
                });
            } else {
                return [];
            }
        },
        capture: () => _this.imgs(),
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: async () => {
            await delay(1000);
            return fn.dt({
                d: " — О, порно на DTF"
            });
        },
        category: "nsfw2"
    }, {
        name: "uCrazy",
        url: {
            h: "ucrazy.org"
        },
        SPA: () => !!fn.ge("#addcomment"),
        observerURL: true,
        init: () => fn.addMutationObserver(() => fn.remove(".banner:has(>#advideo_adv_container)")),
        imgs: ".news__content_wrapper img:not(.news__tags-more-icon)",
        capture: () => fn.gae(".news__content_wrapper img:not(.news__tags-more-icon)"),
        button: [4],
        customTitle: async () => {
            await delay(1000);
            return fn.dt({
                d: [
                    " | uCrazy.org",
                    " | girls.uCrazy.org"
                ]
            });
        },
        category: "nsfw2"
    }, {
        name: "JoyReactor",
        url: {
            h: "joyreactor.cc",
            p: "/post/"
        },
        SPA: true,
        init: async () => {
            addNewTabViewButton();
            const get = async () => {
                let imgs = fn.gae(".image>img:not(.get)");
                if (imgs.length > 0) {
                    imgs.forEach(img => img.classList.add("get"));
                    fn.getImgSrcArr(imgs).forEach(src => setArray.add(src));
                }
                let videos = fn.gae("video[poster]:not(.get)");
                if (videos.length > 0) {
                    videos.forEach(video => {
                        let src = fn.ge("source[type='video/mp4']", video)?.src;
                        if (src) {
                            video.classList.add("get");
                            setVideoArray.add(src);
                            setArray.add(video.poster);
                        }
                    });
                    videoSrcArray = [...setVideoArray];
                }
                if (captureTotal != setArray.size) {
                    captureTotal = setArray.size;
                    await captureSrcB();
                }
            };
            await get();
            fn.addMutationObserver(async () => {
                if (captureExclude()) return;
                await get();
            });
        },
        imgs: () => setArray,
        capture: () => _this.imgs(),
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "bdsmlr",
        link: "https://chasti-wabbit.bdsmlr.com/post/265859932",
        url: {
            h: ".bdsmlr.com",
            e: ".image_container img",
            d: "pc"
        },
        SPA: true,
        init: async () => {
            addNewTabViewButton();
            const get = async () => {
                let imgs = fn.gae(".image_container img:not(.get)");
                if (imgs.length > 0) {
                    imgs.forEach(img => img.classList.add("get"));
                    fn.getImgSrcArr(imgs).forEach(src => setArray.add(src));
                }
                let videos = fn.gae("video.vjs-tech[value][poster]:not(.get)");
                if (videos.length > 0) {
                    videos.forEach(video => {
                        video.classList.add("get");
                        let src = video.getAttribute("value");
                        setVideoArray.add(src);
                        setArray.add(video.poster);
                    });
                    videoSrcArray = [...setVideoArray];
                }
                if (captureTotal != setArray.size) {
                    captureTotal = setArray.size;
                    await captureSrcB();
                }
                customTitle = document.title;
            };
            await get();
            fn.addMutationObserver(async () => {
                if (captureExclude()) return;
                await get();
            });
        },
        imgs: () => setArray,
        capture: () => _this.imgs(),
        hide: ".reblogcontainerouter",
        downloadVideo: true,
        focus: "last:.image_container",
        closeAF: () => {
            let ask = fn.ge(".askholder");
            if (ask) {
                EClick(".cancelbutton");
            }
        },
        aeg: 0,
        category: "nsfw2"
    }, {
        name: "Дзен",
        url: {
            h: "dzen.ru"
        },
        SPA: () => {
            let url = new URL(document.URL);
            return url.pathname.startsWith("/a/") && url.search === "";
        },
        observerURL: true,
        imgs: () => {
            //帖子的數據
            //JSON.parse([...document.scripts].find(s => s.textContent.includes("__APP_STATE__")).textContent.match(/\{"data":\{"__APP_STATE__":.+\)\)/)[0].slice(0, -2));
            //環境變數_data
            //每張圖片讀取完成後會將圖片網址存到sessionStorage屬性hermioneStatPixels裡
            //sessionStorage.getItem("hermioneStatPixels");
            if (_this.SPA()) {
                return fn.wait(() => {
                    fn.showMsg(displayLanguage.str_04, 0);
                    let imgs = fn.gae("figure img");
                    let loadeds = fn.gae("figure img[srcset*='w, ']");
                    if (imgs.length > 0) {
                        fn.showMsg("Waiting for loading " + loadeds.length + "/" + imgs.length, 0);
                        return imgs.at(-1)?.getAttribute("srcset")?.includes("w, ");
                    } else {
                        return false;
                    }
                }, 3000).then(() => {
                    fn.hideMsg();
                    //return fn.getImgSrcArr("figure img[srcset]");
                    let srcs = JSON.parse(sessionStorage.getItem("hermioneStatPixels"));
                    thumbnailSrcArray = [...new Set(srcs.map(src => src.replace(/\d+$/, "360")))];
                    return [...new Set(srcs.map(src => src.replace(/\w+$/, "orig")))];
                });
            } else {
                return [];
            }
        },
        capture: () => _this.imgs(),
        customTitle: async () => {
            await delay(1000);
            return fn.dt({
                d: /\|.+$/
            });
        },
        category: "nsfw2"
    }, {
        name: "NUDE_ART_EROTIC",
        url: {
            h: "nude-art-erotic.livejournal.com",
            p: /^\/\d+\.html$/
        },
        imgs: ".entry-content img:not([src$='19736856'])",
        customTitle: ".entry-title",
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "Развлекательно-эротический блог",
        url: {
            h: "tettie.net",
            s: "p="
        },
        imgs: ".postContent img",
        customTitle: ".postTitle",
        setFancybox: true,
        category: "nsfw2"
    }, {
        name: "URLGalleries",
        host: ["urlgalleries.net"],
        reg: /^https?:\/\/[^\.]+\.urlgalleries\.net\/porn-gallery-\d+\//,
        imgs: () => {
            fn.showMsg(displayLanguage.str_16, 0);
            let fetchNum = 0;
            let pages = [fn.url];
            if (fn.ge(".gallerybody a[href*='?p=']")) {
                pages = [fn.url, ...fn.gau(".gallerybody a[href*='?p=']")];
            }
            let resEleArr = pages.map(url => fetch(url).then(res => res.text()).then(text => {
                fn.showMsg(`${displayLanguage.str_17}${fetchNum+=1}/${pages.length}`, 0);
                let dom = fn.doc(text);
                return fn.gae("#wtf>a", dom);
            }));
            return Promise.all(resEleArr).then(arr => arr.flat()).then(aArr => {
                thumbnailSrcArray = aArr.map(a => fn.ge("img", a)?.src);
                let links = aArr.map(a => a.href);
                fn.showMsg(displayLanguage.str_05, 0);
                fetchNum = 0;
                let imageHostLinks = links.map(url => fetch(url).then(res => res.text()).then(text => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${links.length}`, 0);
                    let dom = fn.doc(text);
                    let code = fn.gst("window.location.href", dom);
                    let [, link] = code.match(/window\.location\.href[\s\='"]+([^'";]+)/);
                    return link;
                }));
                return Promise.all(imageHostLinks).then(urls => fn.getImageHost(urls));
            });
        },
        button: [4],
        insertImg: [
            ["#wtf", 2, "#wtf"], 3
        ],
        customTitle: ".galleryhead>h3>a",
        category: "nsfw2"
    }, {
        name: "wikiFeetX / wikiFeet",
        host: ["www.wikifeet.com", "www.wikifeetx.com"],
        reg: /^https?:\/\/www\.wikifeetx?\.com\/[^\/]+$/,
        imgs: async () => {
            await fn.waitEle(".pic>a");
            const {
                messanger
            } = _unsafeWindow;
            let [imgDir] = fn.gu(".pic>a").match(/[^\d]+/);
            thumbnailSrcArray = messanger.gdata.map(e => "https://thumbs.wikifeet.com/" + e.pid + ".jpg");
            return messanger.gdata.map(e => imgDir + e.pid + ".jpg");
        },
        button: [4],
        insertImg: ["#thepics", 2],
        customTitle: "#content h1",
        category: "nsfw2"
    }, {
        name: "VK",
        host: ["vk.com", "m.vk.com"],
        url: {
            h: "vk.com",
            p: "/album"
        },
        getVK: (list, picNum) => {
            fn.showMsg(displayLanguage.str_05, 0);
            let max = Math.ceil(Number(picNum) / 10);
            let fetchNum = 0;
            let resArr = [];
            for (let i = 0; i < Number(picNum); i += 10) {
                let data = new URLSearchParams({
                    act: "show",
                    al: 1,
                    direction: 1,
                    list,
                    offset: i
                }).toString();
                let res = fn.xhr("https://vk.com/al_photos.php?act=show", {
                    headers: {
                        "content-type": "application/x-www-form-urlencoded",
                        "x-requested-with": "XMLHttpRequest"
                    },
                    data,
                    responseType: "json",
                    method: "POST"
                }).then(json => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                    return json.payload[1][3].map(e => e.w_src ?? e.z_src ?? e.y_src ?? e.x_src);
                });
                resArr.push(res);
            };
            return Promise.all(resArr).then(data => data.flat());
        },
        imgs: () => {
            let list = fn.lp.split("/").at(-1);
            let picNum;
            if (fn.lh.startsWith("m.")) {
                [picNum] = document.title.split("–").at(-1).match(/\d+/);
            } else {
                picNum = fn.gt(".ui_crumb_count");
            }
            return _this.getVK(list, picNum);
        },
        capture: () => _this.imgs(),
        customTitle: ".photos_album_intro>h1,.AlbumPage__title",
        category: "nsfw2"
    }, {
        name: "CyberDrop",
        url: {
            h: "cyberdrop.me",
            p: "/a/"
        },
        init: () => fn.createImgBox("#table", 2),
        imgs: async () => {
            let srcs = [];
            let fileIds = fn.gau("a.image").map(u => u.split("/").at(-1));
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            let resArr = [];
            for (let id of fileIds) {
                let api = `https://api.cyberdrop.me/api/file/info/${id}`
                let res = fetch(api, {
                    "headers": {
                        "accept": "application/json, text/plain, */*",
                    },
                }).then(res => res.json()).then(json => {
                    let isV = /^video/.test(json.type);
                    let isI = /^image/.test(json.type);
                    let isO = json.type === "application/octet-stream";
                    if (isV || isI || isO) {
                        return fetch(json.auth_url, {
                            "headers": {
                                "accept": "application/json, text/plain, */*",
                            }
                        }).then(res => res.json()).then(obj => {
                            fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${fileIds.length}`, 0);
                            if (isV) {
                                return {
                                    v: obj.url
                                }
                            } else {
                                return {
                                    i: obj.url
                                }
                            }
                        });
                    } else {
                        fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${fileIds.length}`, 0);
                        return {
                            n: null
                        }
                    }

                });
                resArr.push(res);
            }
            await Promise.all(resArr).then(data => {
                videoSrcArray = data.filter(obj => "v" in obj)?.map(e => e.v);
                srcs = data.filter(obj => "i" in obj)?.map(e => e.i);
            });
            return srcs;
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "#title",
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "FitNakedGirls",
        host: ["fitnakedgirls.com"],
        reg: /^https?:\/\/fitnakedgirls\.com\/photos\/gallery\/[^\/]+\/$/,
        imgs: () => {
            let srcs;
            let [a, b] = [".wp-block-image img[data-src]", ".entry-content img"];
            if (!!fn.ge(a)) {
                srcs = fn.gae(a).map(e => e.dataset.src.replace(/-\d+x\d+(\.\w+)$/, "$1"));
            } else {
                srcs = fn.gae(b).map(e => e.dataset.src ?? e.src);
            }
            return srcs.filter(src => !src.includes("18xmob.png"));
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        css: ".g1-column-2of3{width:100%!important}",
        hide: "#secondary",
        category: "nsfw2"
    }, {
        name: "R18hub",
        host: ["r18hub.com"],
        link: "https://r18hub.com/photos",
        reg: /^https?:\/\/r18hub\.com\/photo\/[\w-]+/,
        imgs: () => {
            let eles = fn.gae("#photos>li");
            thumbnailSrcArray = eles.map(e => e.dataset.thumb);
            return eles.map(e => e.dataset.src);
        },
        button: [4],
        insertImg: ["#photos", 2],
        customTitle: () => fn.title(" - R18hub"),
        category: "nsfw2"
    }, {
        name: "ZzUp.Com",
        host: ["www.zzup.com", "zzup.com"],
        link: "https://zzup.com/user-album/3338/petmer/index.html",
        reg: /^https?:\/\/(www\.)?zzup\.com\/content\/.+index\.html/i,
        init: () => {
            fn.remove("//iframe|//div[div[center[script[contains(text(),'juicy')]]]][@class='container']|//font[b[contains(text(),'ads')]]");
            fn.createImgBox("//div[div[div[@class='picbox']]]", 2);
        },
        imgs: async () => {
            let max;
            let links;
            try {
                [, max] = fn.gu(".imgpagebar>a:last-child").match(/page-(\d+)/);
            } catch {
                max = 1;
            }
            if (max > 1) {
                let pages = fn.arr(max, (v, i) => i == 0 ? siteUrl : siteUrl.replace("index.html", "") + "page-" + (i + 1) + ".html");
                return fn.getEle(pages, "//div[div[@class='picbox']]").then(picboxs => {
                    let te = fn.ge("//div[@class='row'][div[div[@class='picbox']]]");
                    te.innerHTML = "";
                    te.append(...picboxs);
                    thumbnailSrcArray = picboxs.map(b => fn.ge("img", b).src);
                    links = picboxs.map(b => fn.ge("a", b).href);
                    return fn.getImgA("//main//a[img]", links, 100);
                });
            }
            thumbnailSrcArray = fn.getImgSrcArr(".picbox img");
            links = fn.gau(".picbox>a");
            return fn.getImgA("//main//a[img]", links, 100);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//div[div[div[@class='picbox']]]"], 2
        ],
        customTitle: () => fn.dt({
            d: " - ZzUp.Com"
        }),
        category: "nsfw2"
    }, {
        name: "ZzUp.Com 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/(www\.)?zzup\.com\//,
        init: () => fn.remove("iframe[src*='ad']"),
        autoPager: {
            ele: "//div[div[@class='picbox'][not(script)]]",
            observer: "//div[div[@class='picbox']]",
            next: "//a[h3[span[@class='glyphicon glyphicon-arrow-right']]]",
            re: "//div[div[@class='imgpagebar']]",
            pageNum: () => nextLink.match(/page-(\d+)/)[1]
        },
        category: "autoPager"
    }, {
        name: "FreeXcafe",
        host: ["www.freexcafe.com"],
        reg: /^https?:\/\/www\.freexcafe\.com\/erotica\/[\w-]+\/[\w-]+\/index\.php/,
        init: () => fn.createImgBox("#content>*:last-child", 2),
        imgs: () => fn.getImgA("#imagelink>img,#bigphoto>img", ".thumbs>a", 500),
        thums: ".thumbs>a>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 2, ".thumbs"], 2
        ],
        category: "nsfw2"
    }, {
        name: "TUPIC.TOP",
        host: ["www.tupic.top"],
        reg: /^https?:\/\/www\.tupic\.top\/\w+\/\w+\/\d+\.html$/,
        init: () => fn.createImgBox("#metadata_qrcode", 2),
        imgs: ".gallery_img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".spotlight-group,#touch_to_see"], 2
        ],
        customTitle: () => fn.ge("#post_content h1").textContent.replaceAll("\n", "").trim(),
        category: "nsfw2"
    }, {
        name: "EPORNER Photo",
        host: ["www.eporner.com"],
        link: "https://www.eporner.com/profile/namaiki/,https://www.eporner.com/profile/janekhansen/",
        reg: /^https?:\/\/\w{2,3}\.eporner\.com\/gallery\/.+\//,
        init: () => fn.createImgBox(".photosgrid", 2),
        imgs: () => {
            thumbnailSrcArray = fn.gae("#container img").map(e => e.src);
            return thumbnailSrcArray.map(e => e.replace("_296x1000", ""));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 2, ".photosgrid"], 2
        ],
        endColor: "white",
        customTitle: "#galleryheader>h1",
        category: "nsfw2"
    }, {
        name: "Asian Porn",
        host: ["asianporn.li"],
        link: "https://asianporn.li/photos/",
        reg: /^https?:\/\/asianporn\.li\/photo\/\d+\/[^\/]+\/$/i,
        init: () => fn.createImgBox(".photos", 2),
        imgs: async () => {
            await fn.getNP(".cell.photo", "li.active+li>a", null, ".pagination", 0, "img[data-src]");
            thumbnailSrcArray = fn.gae(".photos img.thumb").map(e => e.dataset.src ?? e.src);
            return fn.getImgA("#image .img-reponsive", ".photos a");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 2, ".photos"], 2
        ],
        customTitle: ".content-title",
        category: "nsfw2"
    }, {
        name: "Xasiat",
        host: ["www.xasiat.com", "areegator.net", "snapmoms.com"],
        link: "https://www.xasiat.com/albums/",
        url: {
            h: [
                /^www\.xasiat\.com$/,
                /^(www\.)?areegator\.net$/,
                /^(www\.)?snapmoms\.com$/
            ],
            p: /^\/([\w]{2}\/)?albums\/\d+\/[\w-]+\/$/
        },
        init: () => {
            fn.gae("img.thumb[data-original]").forEach(img => (img.src = img.dataset.original));
            fn.remove(".sponsor,.footer-margin");
            fn.createImgBox(".images", 2);
        },
        imgs: ".images>a",
        thums: ".images>a>img[data-original]",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".images"], 2
        ],
        endColor: "white",
        customTitle: ".headline>h1",
        css: ".block-album{display:block !important}.block-album>.table,.top,.footer~*:not([id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],#comicRead,#fab,*[class^=fancybox]){display:none !important}",
        category: "nsfw2"
    }, {
        name: "Xasiat 自動翻頁",
        url: {
            h: [
                /^www\.xasiat\.com$/,
                /^(www\.)?areegator\.net$/,
                /^(www\.)?snapmoms\.com$/
            ],
            p: /^\/([\w]{2}\/)?albums\/(\d+\/)?/
        },
        init: () => {
            setInterval(() => {
                fn.remove("//div[iframe] | //iframe");
                if (document.body.getAttribute("class").length > 13) document.body.setAttribute("class", "big-container");
            }, 500);
            fn.remove(".footer~*", 2000);
        },
        autoPager: {
            ele: "#list_albums_common_albums_list_items",
            observer: "#list_albums_common_albums_list_items>.item",
            next: () => {
                let [num] = fn.attr(".load-more>a", "data-parameters")?.match(/\d+$/);
                let [p] = fn.lp.match(/^\/([\w]{2}\/)?albums\//);
                return num ? `${p}${num}/` : null;
            },
            re: ".load-more>a",
            pageNum: () => nextLink.match(/\d+/)[0],
            lazySrc: "img[data-original]"
        },
        openInNewTab: "#list_albums_common_albums_list_items a:not([target=_blank])",
        hide: ".footer~*",
        category: "autoPager"
    }, {
        name: "Erotic Pics",
        host: ["erotic.pics"],
        reg: /^https?:\/\/erotic\.pics\/[^\/]+\/$/,
        include: ".entry-content img",
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /\s–\s\d+\spics/
        }),
        category: "nsfw2"
    }, {
        name: "Erotic Pics 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/erotic\.pics\//,
        autoPager: {
            ele: "#masonry",
            observer: "#masonry>article",
            next: "span.current+a",
            re: ".wp-pagenavi",
            pageNum: "span.current"
        },
        openInNewTab: "a.entry-thumbnail:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "xHamster gallery",
        host: ["xhamster.com"],
        link: "https://zh.xhamster.com/users/eros721_official/photos",
        url: {
            h: "xhamster.com",
            p: /^\/photos\/gallery\/[^/]+$/,
            e: ".gallery-section"
        },
        imgs: async () => {
            await fn.getNP("#initials-script", "//div[@class='gallery-section']//li[a[contains(@class,'active')]]/following-sibling::li[1]/a", null, ".gallery-section .pager-section");
            let photos = fn.gae("#initials-script").map(script => {
                let json = JSON.parse(script.innerText.replace(/window.initials=|;/g, ""));
                return json.photosGalleryModel.photos;
            }).flat();
            thumbnailSrcArray = photos.map(e => e.thumbURL);
            return photos.map(e => e.imageURL);
        },
        init: "fn.remove('.mixed-list>.flex-element')",
        button: [4],
        insertImg: [
            ["main>article", 2, "main>article,.gallery-controls"], 2
        ],
        customTitle: ".page-title h1",
        hide: "div[data-role=promo-messages-wrapper]",
        category: "nsfw2"
    }, {
        name: "xHamsterM gallery M",
        url: {
            h: "xhamster.com",
            p: /^\/photos\/gallery\/[^/]+$/,
            d: "m"
        },
        imgs: async () => {
            await fn.getNP(".items[data-role='gallery-photos']>.item-container", "//ol[@class='page-list']/li[@class='page-button' and a[@class='page-button-link page-button-link--active']]/following-sibling::li[1]/a", null, "//ol[@class='page-list']");
            return fn.getImgA("#photoCurr", "a.item.slided", 1, null, 0);
        },
        button: [4],
        insertImg: [".items[data-role=gallery-photos]", 1],
        customTitle: "h1.page-title",
        css: ".items[data-role=gallery-photos]>.item-container{width:100%!important}",
        hide: ".page-title-controls,aside[data-role=yld-mdtop],.yld-md--bottom,.yld-pc--bottom,aside[data-role=yld-pctop],div[data-role=promo-messages-wrapper]",
        category: "nsfw2"
    }, {
        name: "PornHub photo", //很容易會被短暫封IP
        host: ["pornhub.com"],
        link: "https://pornhub.com/albums",
        enable: 1,
        url: {
            h: "pornhub.com",
            p: /^\/album\/\d+$/
        },
        imgs: () => fn.getImgA("#photoImageSection img", ".js_lazy_bkg a", 200),
        button: [4],
        insertImg: [
            [".photoBlockBox .clear", 1], 1
        ],
        go: 1,
        customTitle: ".photoAlbumTitleV2",
        category: "nsfw2"
    }, {
        name: "BITCHES GIRLS",
        host: ["bitchesgirls.com"],
        reg: /^https?:\/\/bitchesgirls\.com\/[^\/]+\/[^\/]+\/[^\/]+\/$/,
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            const getUrls = (dom = document, pageUrl = siteUrl) => {
                let text = fn.gst("@context", dom);
                let json = JSON.parse(text.replace(/\n/g, "").replace(/\s+/g, " "));
                //debug("\n此頁JSON資料\n", {
                //    url: pageUrl,
                //    json: json
                //});
                let images = [];
                let thums = [];
                let videos = [];
                let {
                    image,
                    video
                } = json;
                image = image?.filter(e => e["@type"] === "ImageObject");
                video = video?.filter(e => e["@type"] === "VideoObject");
                if (video.length > 0) {
                    videos = video.map(e => e.url);
                }
                if (image.length > 0) {
                    thums = image.map(e => e.thumbnailUrl);
                    images = image.map(e => e.url);
                    thums = thums.filter(e => !e.includes("/logos/"));
                    images = images.filter(e => !e.includes("/logos/"));
                }
                return {
                    images,
                    thums,
                    videos
                }
            }
            const max = _unsafeWindow.adConstants.pagesAmount;
            if (max > 1) {
                fn.showMsg(displayLanguage.str_05, 0);
                let fetchNum = 0;
                let resArr = fn.arr(max, (v, i) => {
                    let url = i == 0 ? siteUrl : siteUrl + `${i + 1}/`;
                    return fn.fetchDoc(url).then(dom => {
                        fn.showMsg(`${displayLanguage.str_06}${fetchNum += 1}/${max}`, 0);
                        return getUrls(dom, url);
                    });
                });
                return Promise.all(resArr).then(data => {
                    thumbnailSrcArray = data.map(e => e.thums).flat();
                    videoSrcArray = data.map(e => e.videos).flat();
                    return data.map(e => e.images).flat();
                });
            } else {
                let obj = getUrls();
                thumbnailSrcArray = obj.thums;
                videoSrcArray = obj.videos;
                return obj.images;
            }
        },
        button: [4],
        insertImg: [
            [".button-container", 2, ".albumgrid,.popup-container"], 2
        ],
        go: 1,
        hide: "a#loadMore,.my-girls-popup-element",
        category: "nsfw2"
    }, {
        name: "X-video",
        host: ["x-video.tube"],
        reg: /^https?:\/\/x-video\.tube\/albums\/\d+\//i,
        init: () => fn.createImgBox(".album-view", 2),
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let total = Number(fn.gt(".media-data__list-value"));
            let max;
            if (total > 12) {
                max = Math.ceil(total / 100) + 1;
            } else {
                max = 1;
            }
            let fetchNum = 0;
            let resArr = fn.arr(max, (v, i) => {
                let url = i == 0 ? "?mode=async&function=get_block&block_id=album_view_album_view" : "?mode=async&function=get_block&block_id=album_view_album_view&load=more&from=" + i;
                return fn.fetchDoc(url, {
                    "headers": {
                        "accept": "text/html, */*; q=0.01",
                        "x-requested-with": "XMLHttpRequest"
                    }
                }).then(dom => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                    return {
                        thumbs: fn.getImgSrcArr("a.grid-item img", dom),
                        originals: fn.gae("a.grid-item", dom)
                    }
                });
            });
            return Promise.all(resArr).then(data => {
                thumbnailSrcArray = data.map(e => e.thumbs).flat();
                return data.map(e => e.originals).flat();
            });
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".album-view"], 2
        ],
        customTitle: ".title",
        category: "nsfw2"
    }, {
        name: "jimpicotphotography.com",
        url: {
            h: "jimpicotphotography.com"
        },
        imgs: ".con>img,#post-navigation img",
        customTitle: () => fn.dt({
            d: " - jimpicotphotography.com"
        }),
        category: "nsfw2"
    }, {
        name: "EroMe",
        host: ["www.erome.com"],
        url: {
            h: "erome.com",
            p: "/a/",
            e: "div[id^='album'].page-content"
        },
        imgs: () => {
            videoSrcArray = fn.gae(".video source[type='video/mp4']").map(e => e.src);
            return hasTouchEvent ? fn.gae(".img>img[data-src]") : fn.gae("div.img[data-src]");
        },
        button: [4],
        insertImg: ["div[id^='album'].page-content", 2],
        customTitle: ".page-content h1",
        category: "nsfw2"
    }, {
        name: "EroMe",
        url: {
            h: "erome.fan",
            p: "/a/",
            e: ".entry-content"
        },
        imgs: () => {
            videoSrcArray = fn.gae(".video source[type='video/mp4']").map(e => e.src);
            return hasTouchEvent ? fn.gae(".img>img[data-src]").map(e => e.currentSrc) : fn.gae("div.img[data-src]");
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "luxurybeachresorts.net",
        host: ["www.luxurybeachresorts.net"],
        url: {
            h: "luxurybeachresorts.net",
            e: "#gallery .media-group",
            d: "pc"
        },
        init: () => fn.createImgBox(".media-group", 1),
        imgs: () => {
            videoSrcArray = fn.gae(".video source[type='video/mp4']").map(e => e.src);
            thumbnailSrcArray = fn.getImgSrcArr(".media-group div.img[data-src]");
            return thumbnailSrcArray.map(src => src.replace(/(\?)([^&]+&)/, "$1"));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".media-group"], 2
        ],
        customTitle: "#page #page h1",
        category: "nsfw2"
    }, {
        name: "Amateur Likes",
        host: ["amateurlikes.com"],
        reg: /^https?:\/\/amateurlikes\.com\/\w\/[^\/]+\/\d+$/i,
        imgs: "#gallery img",
        button: [4],
        insertImg: ["#gallery .masonry", 2],
        customTitle: () => fn.dt({
            s: ".full_h1",
            d: /\([\d\s]+Photos\)/i
        }),
        css: "#gallery .masonry{display:block!important}",
        category: "nsfw2"
    }, {
        name: "Nakedsex",
        host: ["nakedsex.pics"],
        reg: /^https?:\/\/nakedsex\.pics\/.+\.php$/i,
        imgs: ".gallerycontent a",
        button: [4],
        insertImg: [
            [".tags", 2], 2
        ],
        endColor: "white",
        go: 1,
        customTitle: () => fn.title(" - Best adult videos and photos"),
        category: "nsfw2"
    }, {
        name: "ThotHub Leaks",
        host: ["thothub.vip"],
        reg: /^https?:\/\/thothub\.vip\/album\/\d+\//,
        imgs: ".images a",
        thums: ".images a img",
        button: [4],
        insertImg: [".images", 2],
        customTitle: ".title",
        category: "nsfw2"
    }, {
        name: "ThotHub Leaks",
        url: {
            h: "thothub.vip",
            e: ".entry-title"
        },
        imgs: ".entry-content img",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /\([\d\s]+Photos\)/i
        }),
        category: "nsfw2"
    }, {
        name: "MrDeepFakes",
        host: ["mrdeepfakes.com"],
        reg: /^https?:\/\/mrdeepfakes\.com\/photo\/\d+\//,
        init: () => {
            fn.remove(".player-adv");
            fn.ge(".page-columns").classList.remove("page-columns");
        },
        imgs: () => {
            if (fn.ge("#album_view_album_view_pagination")) {
                fn.showMsg(displayLanguage.str_05, 0);
                let max = Number(fn.gt("//li[@class='next action-item']/preceding-sibling::li[@class='page action-item'][1]//span[@class='text']"));
                let fetchNum = 0;
                let resArr = fn.arr(max, (v, i) => {
                    let url = siteUrl + "?mode=async&function=get_block&block_id=album_view_album_view&sort_by=&from=" + (i + 1);
                    return fn.fetchDoc(url).then(dom => {
                        fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                        return fn.gae("a[data-fancybox-type=image]", dom).map(a => {
                            let img = fn.ge("img", a);
                            return {
                                original: a.href,
                                thumbnail: img.dataset.original ?? img.src
                            }
                        });
                    });
                });
                return Promise.all(resArr).then(arr => {
                    thumbnailSrcArray = arr.flat().map(e => e.thumbnail);
                    return arr.flat().map(e => e.original);
                });
            } else {
                thumbnailSrcArray = fn.gae(".content img.thumb").map(e => e.dataset.original ?? e.src);
                return fn.gae("a[data-fancybox-type=image]");
            }
        },
        button: [4],
        insertImg: ["#album_view_album_view", 2],
        customTitle: ".player-title",
        category: "nsfw2"
    }, {
        name: "PicHunter",
        host: ["www.pichunter.com"],
        reg: /^https?:\/\/www\.pichunter\.com\/gallery\/\d+\//,
        imgs: () => {
            if (fn.ge(".flex-images figure>a>img")) {
                thumbnailSrcArray = fn.gae(".flex-images figure>a>img").map(e => e.getAttribute("xs"));
            } else {
                thumbnailSrcArray = fn.gae("#main-grid a img").map(e => e.src);
            }
            return fn.gae(".flex-images figure>a,#main-grid a");
        },
        button: [4],
        insertImg: [
            [".flex-images,#main-grid", 2], 1
        ],
        go: 1,
        customTitle: "h1",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw2"
    }, {
        name: "Pictoa",
        host: ["www.pictoa.com"],
        reg: /^https?:\/\/www\.pictoa\.com\/(thumbs|albums)\/.+\.html$/i,
        imgs: () => fn.getImgA("#player img", ".thumb-nav-img a"),
        thums: ".thumb-nav-img img",
        button: [4],
        insertImg: ["#player", 2],
        customTitle: ".title>h1",
        css: "#gallery #player{cursor:unset!important}",
        hide: ".ad-placement",
        category: "nsfw2"
    }, {
        name: "PimpAndHost",
        host: ["pimpandhost.com"],
        link: "https://pimpandhost.com/site/trending",
        reg: /^https?:\/\/pimpandhost\.com\/(image|album)\/\d+/,
        init: () => {
            if (/image/.test(location.href)) location.href = fn.ge("a[title=Album]").href;
            fn.remove(".flex-block-1,.flex-block-2,#comments,.ano_po");
        },
        imgs: async () => {
            await fn.getNP("#album-images>.image-block", "li.active+li:not(.next)>a", null, ".pagination");
            return fn.gae("#album-images .image-block a[data-src]");
        },
        button: [4],
        insertImg: [
            [".summary", 2], 2
        ],
        go: 1,
        customTitle: ".author-header__album-name",
        category: "nsfw2"
    }, {
        name: "PimpAndHost 隱藏廣告",
        reg: /^https?:\/\/pimpandhost\.com\//,
        init: "fn.remove('.flex-block-1,.flex-block-2,#comments,.ano_po')",
        hide: ".list-view:not(#main-list-view) .item:not(.image-block)",
        category: "ad"
    }, {
        name: "Pornpaw 圖片清單頁",
        host: ["www.pornpaw.com"],
        reg: /^https?:\/\/www\.pornpaw\.com\/gallery\/[\w-]+\.html$/i,
        delay: 500,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr("img[data-src]");
            return thumbnailSrcArray.map(e => e.replace("x160.", "."));
        },
        button: [4],
        insertImg: [
            [".container>.row", 2], 2
        ],
        go: 1,
        customTitle: "h1",
        hide: "div:has(>ins)",
        category: "nsfw2"
    }, {
        name: "ImageFap 圖片清單頁",
        url: {
            h: "www.imagefap.com",
            p: ["/gallery/", "/pictures/"],
            e: "#gallery table a"
        },
        init: () => fn.createImgBox("#gallery", 2),
        imgs: async () => {
            let temps = [];
            let originals = [];
            let thumbs = [];
            let gid = new URL(fn.gu("a[href*='&gid']")).searchParams.get("gid");
            let loop = true;
            let pn = 0;
            fn.showMsg(displayLanguage.str_05, 0);
            const get = () => {
                return fn.fetchDoc(`/ajax/actions.php?gid=${gid}&page=${pn}&action=getGallery`).then(dom => {
                    fn.showMsg(`${displayLanguage.str_05} (Page${pn + 1})`, 0);
                    if (!fn.ge("#hgallery", dom)) {
                        loop = false;
                        return;
                    }
                    for (let img of [...dom.images]) {
                        let noParams = new URL(img.dataset.full).pathname;
                        if (temps.includes(noParams)) {
                            loop = false;
                            return;
                        } else {
                            temps.push(noParams);
                            originals.push(img.dataset.full);
                            thumbs.push(img.dataset.original);
                        }
                    }
                });
            };
            while (loop) {
                await get();
                pn++;
            }
            thumbnailSrcArray = thumbs;
            return originals;
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: "#menubar font,h1 b",
        category: "nsfw2"
    }, {
        name: "ImageFap",
        url: {
            h: "www.imagefap.com",
            p: "/photo/",
            d: "pc"
        },
        init: () => {
            fn.remove("//td[div[@id='main']]/following-sibling::td[1] | //div[iframe]");
            fn.ge("#main").removeAttribute("style");
            fn.ge("//table[@width='750']").width = "1000";
        },
        imgs: async () => {
            let max = Number(fn.attr("div[data-total]", "data-total"));
            let pages = Math.ceil(max / 24);
            let pid = fn.ge("#imageid_input").value;
            let gid = fn.ge("#galleryid_input").value;
            let resArr = [];
            let fetchNum = 0;
            fn.showMsg(displayLanguage.str_05, 0);
            for (let i = 0; i < max; i += 24) {
                let url = `/photo/${pid}/?gid=${gid}&idx=${i}&partial=true`;
                let res = await fn.fetchDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${pages}`, 0);
                    if (!fn.ge(".thumbs a", dom)) {
                        alert("Encountered human-machine verification");
                        window.location.href = siteUrl;
                    }
                    return fn.gae(".thumbs a", dom).map(a => {
                        let original = a.href;
                        let thumb = fn.attr("img", "src", a);
                        return {
                            original,
                            thumb
                        }
                    });
                });
                resArr.push(res);
                await delay(1000);
            }
            return Promise.all(resArr).then(data => data.flat()).then(arr => {
                let thumbs = arr.map(e => e.thumb);
                thumbnailSrcArray = thumbs;
                let originals = arr.map(e => e.original);
                return originals;
            });
        },
        button: [4],
        insertImg: ["//td[div[@id='slideshow']]", 2],
        customTitle: "#main h1",
        category: "nsfw2"
    }, {
        name: "ImageFapM",
        url: {
            h: "beta.imagefap.com",
            p: ["/gallery/", "/pictures/"],
            d: "m"
        },
        imgs: async () => {
            let gid = fn.ge("#gid").value;
            let max;
            if (fn.ge(".newNav")) {
                max = Number(fn.gt(".newNav b").match(/\d+/g).at(-1));
            } else {
                max = 1;
            }
            let pages = [`/ajax/actions.php?gid=${gid}&page=0&action=getGallery`];
            if (max > 1) {
                pages = fn.arr(max, (v, i) => `/ajax/actions.php?gid=${gid}&page=${i}&action=getGallery`);
            }
            let resArr = [];
            let fetchNum = 0;
            fn.showMsg(displayLanguage.str_05, 0);
            for (let url of pages) {
                let res = await fn.fetchDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                    return [...dom.images].map(img => {
                        let original = img.dataset.full;
                        let thumb = img.dataset.original;
                        return {
                            original,
                            thumb
                        }
                    });
                });
                resArr.push(res);
                //await delay(1000);
            }
            return Promise.all(resArr).then(data => data.flat()).then(arr => {
                let thumbs = arr.map(e => e.thumb);
                thumbnailSrcArray = thumbs;
                let originals = arr.map(e => e.original);
                return originals;
            });
        },
        button: [4],
        insertImg: ["#gallery", 2],
        customTitle: ".nMobHeader>h1,.userPageInfoGal strong",
        hide: ".ad_placeholder",
        category: "nsfw2"
    }, {
        name: "Fuskator 圖片清單頁",
        host: ["fuskator.com"],
        reg: /^https?:\/\/fuskator\.com\/thumbs\/[\w-~]+\/[\w-~]+\.html$/i,
        init: async () => {
            fn.showMsg(displayLanguage.str_04, 0);
            await fn.waitEle(".pic_pad");
        },
        imgs: "#thumbimages a,.swipebox a",
        thums: "#thumbimages a>img,.swipebox a>img",
        button: [4],
        insertImg: [
            ["//a[text()='View full images']", 2], 2
        ],
        go: 1,
        category: "nsfw2"
    }, {
        name: "Fuskator 大圖頁",
        host: ["fuskator.com"],
        reg: /^https?:\/\/fuskator\.com\//i,
        include: "//a[text()='View gallery thumbnails']",
        imgs: "img.full",
        button: [4],
        insertImg: ["#fullimages", 2, 1000],
        category: "nsfw2"
    }, {
        name: "TOKYO Motion",
        host: ["www.tokyomotion.net"],
        link: "https://www.tokyomotion.net/albums",
        reg: /^https?:\/\/www\.tokyomotion\.net\/album\/\d+\/.+/,
        imgs: async () => {
            await fn.getNP("div[id^=album_photo]", ".pagination li.active+li>a", null, ".pagination");
            thumbnailSrcArray = fn.gae(".thumb-overlay img").map(e => e.src);
            return thumbnailSrcArray.map(e => e.replace("tmb/", ""));
        },
        button: [4],
        insertImg: [
            ["//div[div[div[contains(@id,'album_photo')]]]", 0], 2
        ],
        go: 1,
        customTitle: () => fn.gae(".pull-left")[2].innerText.trim(),
        category: "nsfw2"
    }, {
        name: "JavBangers",
        url: {
            h: "javbangers.com",
            p: "/albums/",
            e: ".album-info"
        },
        imgs: ".images a",
        thums: ".images img",
        button: [4],
        insertImg: [
            [".album-info", 2, ".images"], 2
        ],
        go: 1,
        customTitle: ".headline>h1",
        category: "nsfw2"
    }, {
        name: "multi.xnxx.com",
        host: ["multi.xnxx.com"],
        reg: /^https?:\/\/multi\.xnxx\.com\/gallery\//,
        imgs: ".galleryPage .boxImg",
        button: [4],
        insertImg: [
            [".originalLink", 2], 1
        ],
        go: 1,
        category: "nsfw2"
    }, {
        name: "色情圖片網",
        url: {
            h: "www.photos18.com",
            p: "/v/"
        },
        imgs: ".imgHolder a[data-fancybox]",
        button: [4],
        insertImg: ["#content", 2],
        customTitle: "h1.title",
        fancybox: {
            v: 3,
            css: false
        },
        hide: ".no-gutters",
        category: "nsfw2"
    }, {
        name: "趣事館",
        host: ["17sex.vip"],
        link: "https://17sex.vip/list/4858",
        reg: /^https?:\/\/17sex\.vip\/pic\/\d+$/i,
        imgs: () => {
            let max = fn.gt(".count-pageindex") || 1;
            return fn.getImg(".page>img", max, "4");
        },
        button: [4],
        insertImg: [
            [".page", 0], 2
        ],
        go: 1,
        customTitle: "h3",
        hide: ".topzanpage",
        category: "nsfw2"
    }, {
        name: "久久热/GavPorn",
        url: {
            h: ["www.99re.com", "cav103.com"],
            p: "/albums/"
        },
        imgs: "a[data-fancybox-type]",
        button: [4],
        insertImg: [".sponsor,.images", 2],
        customTitle: ".headline>h1",
        hide: ".top",
        category: "nsfw2"
    }, {
        name: "X1HUB",
        url: {
            h: "x1hub.com",
            p: "/albums/",
            e: ".album-info"
        },
        imgs: ".images a",
        thums: ".images img",
        button: [4],
        insertImg: [".images", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "Hentai Image 單張",
        host: ["hentai-img.com", "hentai-img-xxx.com", "hentai-cosplays.com", "hentai-cosplay-xxx.com", "porn-image.com", "porn-images-xxx.com"],
        reg: /(hentai-img|hentai-img-xxx|hentai-cosplays|hentai-cosplay-xxx|porn-image|porn-images-xxx)\.com\/image\/[^/]+\//,
        include: "//a[text()='DETAIL PAGE' or text()='DETAIL HALAMAN' or text()='詳細へ' or text()='详细信息页面' or text()='Страница сведений' or text()='상세 페이지' or text()='página de detalles' or text()='หน้ารายละเอียด' or text()='TRANG CHI TIẾT']",
        imgs: async () => {
            let [max] = document.title.split("/").at(-1).match(/\d+/);
            let url = siteUrl.replace(/\/\d+\/$/, "");
            let links = fn.arr(max, (v, i) => url + `/${(i + 1)}/`);
            let imgSrcArray = await fn.getImgA("#display_image_detail a,#detail_list a", links, 100);
            thumbnailSrcArray = imgSrcArray.map(e => {
                let arr = e.split("/");
                arr[arr.length - 1] = "p=305/" + arr[arr.length - 1];
                return arr.join("/");
            });
            return imgSrcArray;
        },
        button: [4],
        insertImg: ["#display_image_detail,#detail_list", 2],
        customTitle: () => fn.dt({
            s: "#title>h2,#page h3",
            d: /\s?Photo\s?\d+P|\s?-\s?\d+\/\d+\s?|\([0-9\s]+ảnh\)/i
        }),
        css: "#display_image_detail img{max-width:100% !important}",
        category: "nsfw2"
    }, {
        name: "Hentai Image",
        host: ["hentai-img.com", "hentai-img-xxx.com", "hentai-cosplays.com", "hentai-cosplay-xxx.com", "porn-image.com", "porn-images-xxx.com"],
        reg: /(hentai-img|hentai-img-xxx|hentai-cosplays|hentai-cosplay-xxx|porn-image|porn-images-xxx)\.com\/image\/[^/]+\/(page\/\d+\/)?$/,
        init: () => {
            let ele = fn.ge("//div[span[a]]");
            if (ele) {
                let tE = fn.ge("#display_image_detail,#detail_list");
                insertBefore(tE, ele);
            }
        },
        imgs: async () => {
            let max = fn.gt("#paginator>*:last-child", 3) || fn.gt(".paginator_page[rel=next]", 2) || 1;
            let url = siteUrl.replace(/page\/\d+\/$/, "");
            let links = fn.arr(max, (v, i) => url + `page/${(i + 1)}/`);
            thumbnailSrcArray = await fn.getImgA(".icon-overlay img,#display_image_detail img", links, 100);
            thumbnailSrcArray = thumbnailSrcArray.map(e => {
                let arr = e.split("/");
                arr[arr.length - 2] = "p=305";
                return arr.join("/");
            });
            return thumbnailSrcArray.map(e => e.replace(/\/p=(700|305)/, ""));
        },
        button: [4],
        insertImg: ["#display_image_detail,#detail_list", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//a[text()='Prev Article' or text()='前の記事' or text()='前一篇']");
            return next ? next.href : null;
        },
        prev: "//a[text()='Next Article' or text()='次の記事' or text()='下一篇文章']",
        customTitle: () => fn.dt({
            s: "#title>h2,#page h3",
            d: /\s?Photo\s?\d+P|\s?-\s?\d+\/\d+\s?|\([0-9\s]+ảnh\)/i
        }),
        css: "#display_image_detail img{max-width:100% !important}",
        category: "nsfw2"
    }, {
        name: "Fapator 圖片清單頁",
        host: ["www.fapator.com"],
        reg: /^https?:\/\/www\.fapator\.com\/\?content_id=/i,
        init: () => fn.remove("//div[@class='img' and a[@target and img]]"),
        imgs: "a[data-lightbox]",
        thums: "a[data-lightbox]>img",
        button: [4],
        insertImg: [".fcon+.fapad", 1],
        next: "//a[contains(text(),'next photos')]",
        prev: 1,
        go: 1,
        css: ".fapad{width:auto !important;height:auto !important}",
        category: "nsfw2"
    }, {
        name: "SMUTPOND",
        host: ["www.smutpond.com"],
        reg: /^https?:\/\/www\.smutpond\.com\/gallery-pics\/\?uid=/i,
        init: () => delay(2000),
        imgs: () => {
            thumbnailSrcArray = fn.gae(".viewerPreview img").slice(5).map(e => e.dataset.lazy ?? e.src);
            thumbnailSrcArray = [...new Set(thumbnailSrcArray)];
            return fn.gae("img[alt=Pic]");
        },
        button: [4],
        insertImg: [".viewerBox", 2],
        customTitle: "h2.sectionTitleLeft",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw2"
    }, {
        name: "DirtyShip.com",
        host: ["dirtyship.com"],
        reg: /^https?:\/\/dirtyship\.com\/gallery\/[^\/]+\/$/,
        imgs: () => fn.getImgSrcset(".gallery_grid img,.gallery_grid~img"),
        thums: ".gallery_grid img,.gallery_grid~img",
        button: [4],
        insertImg: [
            [".gallery_grid", 0, ".gallery_grid img:not(.FullPictureLoadImage),.gallery_grid~img"], 2
        ],
        customTitle: () => fn.title(" - DirtyShip.com"),
        category: "nsfw2"
    }, {
        name: "ᑕ❶ᑐ Onlyfans +18",
        host: ["www.tiktaks.de"],
        reg: /^https?:\/\/www\.tiktaks\.de\/onlyfans\/[^\/]+\/$/,
        imgs: "figure.wp-block-image>img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".title",
        category: "nsfw2"
    }, {
        name: "SexyThots.com",
        host: ["sexythots.com"],
        reg: /^https?:\/\/sexythots\.com\/gallery\/[^\/]+\/$/,
        imgs: () => fn.getImgSrcset(".gallery_grid img"),
        thums: ".gallery_grid img",
        button: [4],
        insertImg: [".gallery_grid", 2],
        customTitle: () => fn.title(" - SexyThots.com"),
        category: "nsfw2"
    }, {
        name: "SexyGirlsPics",
        host: ["sexygirlspics.com"],
        reg: /^https?:\/\/sexygirlspics\.com\/pics\/[\w-]+\//i,
        imgs: "a.ss-image",
        thums: "a.ss-image>img",
        button: [4],
        insertImg: [
            [".sponsor-button", 2], 1
        ],
        go: 1,
        category: "nsfw2"
    }, {
        name: "PornPic",
        host: ["www.pornpic.com", "pornpic.com"],
        reg: /^https?:\/\/(www\.)?pornpic\.com\/gallery\/[\w-]+/i,
        imgs: ".gallery-grid a.item-link[data-fancybox]",
        thums: ".gallery-grid a.item-link[data-fancybox] img",
        button: [4],
        insertImg: [
            [".gallery-info", 2], 1
        ],
        go: 1,
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw2"
    }, {
        name: "Girlsreleased",
        url: {
            h: "girlsreleased.com",
            p: "/set/"
        },
        init: async () => {
            await fn.waitEle(".images .imageContainer .image img");
            fn.createImgBox(".images", 2);
        },
        imgs: async () => {
            let selector = ".images .imageContainer .image img";
            await fn.waitEle(selector);
            thumbnailSrcArray = fn.gae(selector).map(e => e.src);
            let src = fn.attr(selector, "src");
            let images = fn.gae(selector);
            if (/imx\.to/.test(src)) {
                let tempSrc = src.replace("https://imx.to/u/t/", "https://i.imx.to/i/");
                return new Promise(async resolve => {
                    let obj = await fn.checkImgStatus(tempSrc);
                    if (obj.ok && obj.width > 200) {
                        resolve(images.map(e => e.src.replace("https://imx.to/u/t/", "https://i.imx.to/i/")));
                    } else {
                        resolve(images.map(e => e.src.replace("/t/", "/i/")));
                    }
                });
            } else if (/imgadult\.com/.test(src)) {
                return images.map(e => e.src.replace("small-medium/", "big/"));
            } else if (/pixhost\.to/.test(src)) {
                return images.map(e => e.src.replace("https://t", "https://img").replace("/thumbs/", "/images/"));
            } else if (/imagevenue/.test(src)) {
                return fn.getImgCorsA("#main-image", "a[target=imageView]");
            } else {
                return [];
            }
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        go: 1,
        referer: "src",
        css: "@media only screen and (max-width:1920px){#FullPictureLoadMainImgBox{width:100%;max-width:1400px;margin:0 auto}}",
        category: "nsfw2"
    }, {
        name: "Girlsreleased 載入更多",
        url: {
            h: "girlsreleased.com"
        },
        observerClick: "//button[text()='more']",
        openInNewTab: ".content .main a",
        category: "autoPager"
    }, {
        name: "Eropics", // vipr.im,Imagetwist.com圖床無法外連但可以下載
        host: ["eropics.to"],
        reg: /^https?:\/\/eropics\.\w+\/\d+\/\d+\/\d+\//i,
        init: () => {
            document.addEventListener("keydown", event => {
                if (event.ctrlKey && event.altKey && (event.code === "KeyC" || event.key === "c" || event.key === "C")) {
                    event.preventDefault();
                    let arr = fn.gau(".entry-content a");
                    let str = arr.join("\n");
                    console.log(str);
                    copyToClipboard(str);
                    fn.showMsg(displayLanguage.str_11);
                }
            });
        },
        imgs: async () => {
            let aEles = fn.gae(`
            .entry-content a[href^='//imgspice.com/'],
            .entry-content a[href^='//imagetwist.com/'],
            .entry-content a[href*='postimg.cc'],
            .entry-content a[href*='fastpic.org'],
            .entry-content a[href*='vipr.im'],
            .entry-content a[href*='pixhost.to']:not([href*='/gallery/']),
            .entry-content a[href*='turboimagehost'],
            .entry-content a[href*='imgbox.com'],
            .entry-content a[href*='imagevenue'],
            .entry-content a[href*='imx.to'],
            .entry-content a[href*='imagebam']
            `);
            thumbnailSrcArray = aEles.map(a => fn.ge("img", a).src);
            let URLs = aEles.map(a => a.href);
            return fn.getImageHost(URLs);
        },
        button: [4],
        insertImg: [
            [".entry-footer", 2], 3
        ],
        go: 1,
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "ViperGirls/PornCoven/ErotiCity",
        link: "https://viper.to/threads/10623260-Coser-UmekoJ-NieR-2B",
        host: ["vipergirls.to", "viper.to", "viperohilia.art", "vipervault.link", "viperbb.rocks", "viperkats.eu", "planetviper.club", "porncoven.com", "eroticity.net"],
        reg: () => !hasTouchEvent && /^https?:\/\/(vipergirls\.to|viper\.to|viper\w+\.\w+|planetviper\.club|porncoven\.com|eroticity\.net)\/threads\//i.test(fn.url),
        include: ".postdetails",
        init: () => {
            document.addEventListener("click", event => {
                if (event.target.className === "postdetails") {
                    let links = [];
                    if (event.target.querySelector("a[href$='.jpg']:not([href^='http://imagetwist.com/'])")) {
                        links = [...event.target.querySelectorAll("a[href$='.jpg']")].map(a => a.href);
                    } else {
                        links = [...event.target.querySelectorAll(`
                            a[href^='https://imgspice.com/'],
                            a[href*='imx.to']:not([href*='/u/i/']),
                            a[href*='pixhost.to'],
                            a[href^='http://imagetwist.com/'],
                            a[href*='postimg.cc'],
                            a[href*='fastpic.org'],
                            a[href*='vipr.im'],
                            a[href*='turboimagehost'],
                            a[href*='imgbox.com'],
                            a[href*='imagevenue'],
                            a[href*='imagebam']
                            `)].map(a => a.href);
                    }
                    captureLinksArray = links;
                    fn.showMsg(`Capture ${links.length} Links`);
                    debug("captureLinksArray", captureLinksArray);
                }
            });
        },
        imgs: () => fn.getImageHost(),
        repeat: 1,
        category: "nsfw2"
    }, {
        name: "Kitty Kats Forum",
        host: ["kitty-kats.net"],
        reg: () => !hasTouchEvent && /^https?:\/\/kitty-kats\.net\/threads\//i.test(fn.url),
        init: () => {
            document.addEventListener("click", event => {
                if (event.target.className === "message-cell message-cell--user") {
                    let links = [];
                    if (event.target.parentNode.querySelector("a[href$='.jpg']:not([href^='http://imagetwist.com/'])")) {
                        links = [...event.target.parentNode.querySelectorAll("a[href$='.jpg']")].map(a => a.href);
                    } else {
                        links = [...event.target.parentNode.querySelectorAll(`
                        a[href^='https://imgspice.com/'],
                        a[href*='imx.to']:not([href*='/u/i/']),
                        a[href*='pixhost.to'],
                        a[href^='http://imagetwist.com/'],
                        a[href*='postimg.cc'],
                        a[href*='fastpic.org'],
                        a[href*='vipr.im'],
                        a[href*='turboimagehost'],
                        a[href*='imgbox.com'],
                        a[href*='imagevenue'],
                        a[href*='imagebam']
                        `)].map(a => a.href);
                    }
                    captureLinksArray = links;
                    fn.showMsg(`Capture ${links.length} Links`);
                    debug("captureLinksArray", captureLinksArray);
                }
            });
        },
        imgs: () => fn.getImageHost(),
        repeat: 1,
        category: "nsfw2"
    }, {
        name: "Teen Photos",
        host: ["teenphotos.forumes.ru"],
        link: "https://teenphotos.forumes.ru/viewtopic.php?id=324",
        reg: () => !hasTouchEvent && /^https?:\/\/teenphotos\.forumes\.ru\/viewtopic\.php\?id=\d+/.test(fn.url),
        init: () => {
            document.addEventListener("click", event => {
                if (event.target.className === "container") {
                    let links = [...event.target.querySelectorAll(`
                    a[href^='https://imgspice.com/'],
                    a[href*='imx.to']:not([href*='/u/i/']),
                    a[href*='pixhost.to'],
                    a[href^='http://imagetwist.com/'],
                    a[href*='postimg.cc'],
                    a[href*='fastpic.org'],
                    a[href*='vipr.im'],
                    a[href*='turboimagehost'],
                    a[href*='imgbox.com'],
                    a[href*='imagevenue'],
                    a[href*='imagebam']
                    `)].map(a => a.href);
                    captureLinksArray = links;
                    fn.showMsg(`Capture ${links.length} Links`);
                    debug("captureLinksArray", captureLinksArray);
                }
            });
        },
        imgs: () => fn.getImageHost(),
        repeat: 1,
        category: "nsfw2"
    }, {
        name: "XONLY",
        host: ["xonly8.com"],
        link: "https://xonly8.com/index.php?topic=229069.0",
        reg: () => !hasTouchEvent && /^https?:\/\/xonly\d?\.com\/index\.php\?topic=/.test(fn.url),
        init: () => {
            document.addEventListener("click", event => {
                if (event.target.className === "post_wrapper") {
                    let links = [...event.target.querySelectorAll(`
                    a[href^='https://imgspice.com/'],
                    a[href*='imx.to']:not([href*='/u/i/']),
                    a[href*='pixhost.to'],
                    a[href^='http://imagetwist.com/'],
                    a[href*='postimg.cc'],
                    a[href*='fastpic.org'],
                    a[href*='vipr.im'],
                    a[href*='turboimagehost'],
                    a[href*='imgbox.com'],
                    a[href*='imagevenue'],
                    a[href*='imagebam']
                    `)].map(a => a.href);
                    captureLinksArray = links;
                    fn.showMsg(`Capture ${links.length} Links`);
                    debug("captureLinksArray", captureLinksArray);
                }
            });
        },
        imgs: () => fn.getImageHost(),
        repeat: 1,
        category: "nsfw2"
    }, {
        name: "imx.to gallery",
        host: ["imx.to"],
        reg: /^https?:\/\/imx\.to\/g\/\w+$/i,
        imgs: () => fn.gae("img.imgtooltip").map(e => e.src.replace("/u/t/", "/u/i/")),
        button: [4],
        insertImg: [
            ["#content", 2], 2
        ],
        go: 1,
        category: "nsfw2"
    }, {
        name: "imx.to",
        host: ["imx.to"],
        reg: /^https?:\/\/imx\.to\/i\/\w+$/i,
        autoClick: ".button.blue.large,#continuebutton,a[title='Show gallery']",
        category: "none"
    }, {
        name: "亚洲色吧",
        host: ["yazhouseba.com"],
        reg: /^https?:\/\/yazhouseba\.com\/meinv\/img-\d+\.html/,
        include: "#next-url",
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let pid = fn.ge("#next-url").rel;
            return fetch("/meinv/ajax.php", {
                "headers": {
                    "accept": "application/json, text/javascript, */*; q=0.01",
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `action=src&pid=${pid}`,
                "method": "POST"
            }).then(res => res.json()).then(json => json.urls.map(e => _unsafeWindow.img_dir + e));
        },
        button: [4],
        insertImg: [".content>.image", 2],
        customTitle: ".content>h1",
        category: "nsfw2"
    }, {
        name: "1000艺术摄影/169图片大全",
        host: ["www.1000yishu.com", "www.169tp.com", "wap.169tp.com"],
        reg: /^https?:\/\/(www\.1000yishu\.com|www\.169tp\.com|wap\.169tp\.com)\/\w+\/\d+\/\d+\/\d+\.html/,
        imgs: () => {
            let max;
            try {
                [max] = fn.gt(".pagelist a").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg(".big-pic img,.inside_box img", max, 9);
        },
        button: [4],
        insertImg: [".big-pic,.inside_box", 2],
        autoDownload: [0],
        next: ".fenxianga a,.pre_arct a",
        prev: ".fenxianga a:last-child,.next_arct a",
        hide: ".ad,union",
        category: "nsfw1"
    }, {
        name: "1T图库格式",
        reg: () => {
            let hosts1 = [
                "www.0b23.com",
                "www.1taz.com",
                "www.2cra.com",
                "www.3ktu.com",
                "www.714g.com",
                "www.aizibang.com",
                "www.cdnecs.com",
                "www.diu5.com",
                "www.edu-zytc.com",
                "www.gkiev.com",
                "www.hsudhf.com",
                "www.iduobi.com",
                "www.jnnmm.com",
                "www.jsjfgkgs.com",
                "www.mash120.com",
                "www.mmokok.com",
                "www.nanitu.com",
                "www.opks.cc",
                "www.php-art.com",
                "www.qo6q.com",
                "www.qyjafk.com",
                "www.rodwy.com",
                "www.rzjyz.com",
                "www.sqhyyz.com",
                "www.sy-sme.com",
                "www.wjjlf.com",
                "www.woxiutu.com",
                "www.wt768.com",
                "www.y521.com"
            ];
            let hosts2 = [
                "www.7tul.com"
            ];
            return hosts1.some(h => h === fn.lh) && /\/\w+\/\d+\.html$/.test(fn.lp) || hosts2.some(h => h === fn.lh) && /\/tu\d+\.html$/.test(fn.lp);
        },
        include: "#showimg img,.img-box img",
        imgs: () => {
            let max;
            try {
                [, max] = fn.gu(".endpage").match(/-(\d+)\.html/);
            } catch {
                max = 1;
            }
            return fn.getImgO("#showimg img,.img-box img", max, 5, null, 0, "#pageNum");
        },
        button: [4],
        insertImg: ["#showimg,.img-box", 2],
        autoDownload: [0],
        next: "a[title='上一篇']",
        prev: "a[title='下一篇']",
        category: "nsfw1"
    }, {
        name: "仿紳士漫畫UI寫真圖庫 簡介頁",
        url: {
            e: [
                "//ul[@id='album_tabs']/li/a[@title='寫真圖庫'][text()='寫真圖庫']",
                ".png.bread a[title='寫真圖庫']",
                "//a[@class='btn'][text()='開始閱讀']"
            ]
        },
        init: () => {
            fn.clearAllTimer();
            fn.createImgBox("#bodywrap", 2);
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.ge("//a[@class='btn'][text()='開始閱讀']").href;
            return fn.fetchDoc(url).then(dom => fn.gae("#photo_body img", dom));
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: "#bodywrap>h2",
        css: "#FullPictureLoadMainImgBox{max-width:1170px;margin-left:auto;margin-right:auto}",
        category: "nsfw1"
    }, {
        name: "仿紳士漫畫UI寫真圖庫 閱讀頁",
        url: {
            p: "/read/id/",
            e: [
                "//ul[@id='album_tabs']/li/a[@title='寫真圖庫'][text()='寫真圖庫']",
                ".png.bread a[title='寫真圖庫']"
            ]
        },
        imgs: "#photo_body img",
        button: [4],
        insertImg: ["#photo_body", 2],
        customTitle: () => fn.title(/閱讀內頁.+/),
        css: "#photo_body{max-width:1170px;margin-left:auto;margin-right:auto}",
        category: "nsfw1"
    }, {
        name: "坏哥哥旧站",
        url: () => fn.checkUrl({
            e: ["#content_news img", "#page"]
        }) && !fn.lp.includes("/index"),
        init: () => fn.setStyleSheet(),
        imgs: () => {
            let [max] = fn.gt("#page>*:last-child").match(/\d+/);
            let links = fn.arr(max, (v, i) => i === 0 ? fn.url : fn.url + "index" + (i + 1) + ".html");
            return fn.getImgA("#content_news img", links);
        },
        button: [4],
        insertImg: ["#content_news", 2],
        customTitle: ".title h1",
        hide: "div:has(>img[src^='/template/']),div:has(>img[src*='/HtmlS/'])",
        category: "nsfw2"
    }, {
        name: "坏哥哥旧站M",
        url: {
            p: /\.html$/,
            e: [".fed-arti-content img", "//a[text()='尾页']"]
        },
        init: () => fn.setStyleSheet(),
        imgs: () => {
            let [, max] = fn.gu("//a[text()='尾页']").match(/-(\d+)\.html$/);
            let url = fn.url.replace(/(-\d+)?\.html$/, "");
            let links = fn.arr(max, (v, i) => url + "-" + (i + 1) + ".html");
            return fn.getImgA(".fed-arti-content img", links);
        },
        button: [4],
        insertImg: [".fed-arti-content", 2],
        customTitle: ".fed-arti-head h2",
        hide: "div:has(>img[src^='/template/']),div:has(>img[src*='/HtmlS/'])",
        category: "nsfw2"
    }, {
        name: "坏哥哥旧站M",
        url: () => fn.checkUrl({
            e: [".fed-arti-content img", ".fed-page-info"]
        }) && !fn.lp.includes("/index"),
        init: () => fn.setStyleSheet(),
        imgs: () => {
            let [max] = fn.gt(".fed-page-info>*:last-child").match(/\d+/);
            let links = fn.arr(max, (v, i) => i === 0 ? fn.url : fn.url + "index" + (i + 1) + ".html");
            return fn.getImgA(".fed-arti-content img", links);
        },
        button: [4],
        insertImg: [".fed-arti-content", 2],
        customTitle: ".fed-arti-head h2",
        hide: "div:has(>img[src^='/template/']),div:has(>img[src*='/HtmlS/'])",
        category: "nsfw2"
    }, {
        name: "坏哥哥新站",
        url: {
            e: [".single-video-info-content img", ".pagination"]
        },
        imgs: async () => {
            await fn.getNP(".single-video-info-content>*", ".pagination li.active+li>a:not([title='下一页'])", null, ".pagination");
            return fn.gae(".single-video-info-content img");
        },
        button: [4],
        insertImg: [".single-video-info-content", 2],
        customTitle: ".single-video-title h2",
        hide: "div:has(>img[src^='/template/']),div:has(>img[src*='/HtmlS/'])",
        category: "nsfw2"
    }, {
        name: "坏哥哥M_AD",
        url: {
            e: [
                ".fed-nav-logo,.navbar-brand",
                "//div[@class='fed-nav-left']/a[text()='美女美图' or text()='美图区'] | //div[@class='m-footer']"
            ],
            d: "m"
        },
        hide: "div:has(>img[src^='/template/']),div:has(>img[src*='/HtmlS/'])",
        category: "ad"
    }, {
        name: "万德美图屋/蚂蚁图库",
        url: {
            h: ["www.wind5.com", "www.mayihz.com"],
            p: /^\/tu\d+\.html$/,
            e: "#portfolio img"
        },
        imgs: () => {
            let max;
            try {
                [, max] = fn.gu("a[title=尾页]").match(/-(\d+)\.html/);
            } catch {
                max = 1;
            }
            return fn.getImgO("#portfolio img", max, 5);
        },
        button: [4],
        insertImg: ["#portfolio", 2],
        autoDownload: [0],
        next: "a[title='上一篇']",
        prev: "a[title='下一篇']",
        customTitle: "h1.fed-swip-head",
        category: "nsfw1"
    }, {
        name: "每天乐图片网",
        host: ["www.mtianle.com"],
        reg: /^https?:\/\/www\.mtianle\.com\/\w+\/\d+\.html$/,
        imgs: () => {
            let [, max] = fn.gu("//a[text()='尾页']").match(/_(\d+)\.html/);
            return fn.getImgO(".pic-main img", max, 9);
        },
        button: [4],
        insertImg: [".pic-main", 2],
        autoDownload: [0],
        next: "a#pre-page",
        prev: "a#next-page",
        customTitle: "h1",
        category: "nsfw1"
    }, {
        name: "每天乐图片网M",
        host: ["m.mtianle.com"],
        reg: /^https?:\/\/m\.mtianle\.com\/\w+\/\d+\.html$/,
        imgs: () => {
            let [max] = fn.gt(".num-page").match(/\d+$/);
            return fn.getImgO(".pic-m img", max, 9);
        },
        button: [4],
        insertImg: [".pic-m", 2],
        autoDownload: [0],
        next: "//a[text()='上一组图'][@href]",
        prev: "//a[text()='下一组图'][@href]",
        customTitle: ".tit-m h1",
        hide: "div[style]:has(>ul)",
        category: "nsfw1"
    }, {
        name: "亿秀美女",
        host: ["www.itu11.com", "m.itu11.com"],
        reg: /^https?:\/\/(www|m)\.i?tu11\.com\/\w+\/(\d+\/)?\d+\/\d+\.html$/i,
        include: "#showimg img,.img-box img",
        imgs: async () => {
            await fn.getNP("#showimg img,.img-box img", "a.curpage+a:not(.prepage)", null, "#paginationEle", 0, null, 0, 0);
            return fn.gae("#showimg img,.img-box img");
        },
        button: [4],
        insertImg: ["#showimg,.img-box", 2],
        autoDownload: [0],
        next: "//div[contains(text(),'上一篇')]/a | //a[text()='上一篇']",
        prev: "//div[contains(text(),'下一篇')]/a | //a[text()='下一篇']",
        category: "nsfw1"
    }, {
        name: "爱美女网",
        host: ["www.aimeinv6.com"],
        reg: /^https?:\/\/www\.aimeinv6\.com\/\w+\/\d+\.html$/,
        init: () => {
            let a = fn.ge("a[href*=dPlayNext]");
            a.outerHTML = `<div class="imgBox">${a.innerHTML}</div>`;
        },
        imgs: () => {
            let max;
            try {
                [max] = fn.gt("//a[contains(text(),'共')]").match(/\d+/);
            } catch {
                max = 1;
            }
            return fn.getImg("#bigimg", max, 9);
        },
        button: [4],
        insertImg: [".imgBox", 2],
        autoDownload: [0],
        next: "//span[contains(text(),'上一篇')]/a",
        prev: "//span[contains(text(),'下一篇')]/a",
        category: "nsfw1"
    }, {
        name: "xHer",
        url: {
            h: "xher.net",
            s: "/category/"
        },
        init: () => fn.createImgBox("#thumbnails", 1),
        imgs: () => {
            let url = fn.gu("a[rel=last]");
            let [max] = /\d+$/.exec(url);
            url = url.replace(/\d+$/, "");
            max = Number(max);
            let pages = [fn.url];
            for (let i = 15; i <= max; i += 15) {
                pages.push(url + i);
            }
            return fn.getEle(pages, "#thumbnails>li").then(eles => {
                thumbnailSrcArray = eles.map(li => fn.ge("img", li)?.src);
                let links = eles.map(li => fn.ge("a", li)?.href);
                return fn.getImgA("#downloadSwitchLink", links);
            });
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#thumbnails"], 2
        ],
        customTitle: ".titrePage>h2>a+a",
        fetch: 1,
        category: "nsfw2"
    }, {
        name: "JavCup",
        url: {
            h: "javcup.com",
            p: "/movie/",
            e: ["#video[poster]", ".movies-images li"]
        },
        init: () => fn.createImgBox("#play-card", 2),
        imgs: () => {
            let videoSrc = fn.ge("#video>source")?.src;
            videoSrcArray[0] = videoSrc;
            let poster = fn.attr("#video[poster]", "poster");
            let srcs = fn.getImgSrcArr(".movies-images li");
            srcs.unshift(poster);
            return srcs;
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: "h1.title",
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "JavCup",
        url: {
            h: "javcup.com",
            p: "/video/",
            e: "#video[poster]"
        },
        imgs: () => {
            let videoSrc = fn.ge("#video>source")?.src;
            videoSrcArray[0] = videoSrc;
            let poster = fn.attr("#video[poster]", "poster");
            return [poster];
        },
        customTitle: "h1.title",
        downloadVideo: true,
        category: "nsfw2"
    }, {
        name: "JavCup",
        url: {
            h: "javcup.com",
            p: "/photo/"
        },
        init: () => fn.createImgBox(".content>.body", 2),
        imgs: "#photos>li",
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: "h1.title",
        category: "nsfw2"
    }, {
        name: "JavCup",
        url: {
            h: "javcup.com",
            p: "/model/"
        },
        init: () => {
            fn.createImgBox(".content>.body", 2);
            fn.gae("section img[data-src]").forEach(e => (e.src = e.dataset.src));
        },
        imgs: () => {
            let links = fn.gau("a[href*='type=photos']");
            if (links.length > 1) {
                let url = links.at(0);
                let [max] = links.at(-1).match(/\d+$/);
                links = fn.arr(max, (v, i) => url + "&page=" + (i + 1));
                return fn.getEle(links, "#photos>ul").then(uls => {
                    links = uls.map(ul => fn.gau(".photo-grid-item a", ul));
                    links = links.flat();
                    return fn.getImgA("#photos>li", links, 1);
                });
            } else {
                links = fn.gau("#photos .photo-grid-item a");
                return fn.getImgA("#photos>li", links, 1);
            }
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "h1 span",
        category: "nsfw2"
    }, {
        name: "JJGirls",
        url: {
            h: "jjgirls.com",
            e: ".L664 a:has(>img:not([src^='/thumbs/']))",
            d: "pc"
        },
        init: () => fn.createImgBox(".L664"),
        imgs: () => {
            let pagesE = fn.ge(".matchlinks");
            let pages = /\/\d+\/$/.test(fn.lp);
            if (pagesE && pages) {
                let url = fn.lp.replace(/\/\d+\/$/, "");
                let max;
                let link = fn.gu(".matchlinks>a:has(+img)");
                if (/more$/.test(link)) {
                    max = fn.gt(".matchlinks>a+b");
                } else {
                    [, max] = link.match(/\/(\d+)\/$/);
                }
                let links = fn.arr(max, (v, i) => `${url}/${(i + 1)}/`);
                return fn.getImgA(".L664 a:has(>img:not([src^='/thumbs/']))", links, 1);
            } else {
                return fn.getImgA(".L664 a:has(>img:not([src^='/thumbs/']))", [fn.url]);
            }
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        category: "nsfw2"
    }, {
        name: "エロ画像 オナップル",
        url: {
            h: "onapple.jp",
            p: "/archives/"
        },
        imgs: ".permanent_text img",
        customTitle: ".permanent_title",
        category: "nsfw2"
    }, {
        name: "JavTube/PureJapanese/ThumbNow/69DV/JapaneseThumbs/AsiaUncensored",
        url: {
            h: [
                "javtube.com",
                "purejapanese.com",
                "thumbnow.com",
                "69dv.com",
                "japanesethumbs.com",
                "asiauncensored.com"
            ],
            e: ".L664 a:has(>img:not([src^='/thumbs/']))",
            d: "pc"
        },
        init: () => fn.createImgBox(".L664,.L996"),
        imgs: () => {
            let pagesE = fn.ge(".matchlinks");
            let pages = /\/\d+\/$/.test(fn.lp);
            if (pagesE && pages) {
                let url = fn.lp.replace(/\/\d+\/$/, "");
                let max;
                let last = fn.ge("//div[@class='matchlinks']/a[text()='Last']");
                if (last) {
                    let link = fn.gu("//div[@class='matchlinks']/a[text()='Last']");
                    [, max] = link.match(/\/(\d+)\/$/);
                } else {
                    max = fn.gt(".matchlinks>a:last-child", 2);
                }
                let links = fn.arr(max, (v, i) => `${url}/${(i + 1)}/`);
                return fn.getImgA(".L664 a:has(>img:not([src^='/thumbs/']))", links, 1);
            } else {
                return fn.getImgA(".L664 a:has(>img:not([src^='/thumbs/']))", [fn.url]);
            }
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        category: "nsfw2"
    }, {
        name: "一千美女",
        url: {
            h: [
                /yqmn\.live$/
            ],
            s: "action-imagelist-uid-"
        },
        imgs: async () => {
            await fn.getNP(".imglist>*,.m_aana>ul,.main_column_pic,.pic-list>ul", "strong+a:not(.next)", null, ".pages");
            return fn.getImgA(".bigimg img,#articlebody img,.content_pic img,#big-pic img", ".imglist a,.m_aana a,.main_column_pic a,.pic-list a");
        },
        button: [4],
        insertImg: [".imglist,.m_aana,.main_column,.pic-list", 2],
        customTitle: () => {
            let selector = ".title>div[style],.imgWrap a,.name>a";
            let r = /\(\d+p\)|\s?\(.+\)\s?/i;
            if (fn.ge(selector)) {
                return fn.dt({
                    s: selector,
                    d: r
                });
            } else {
                return fn.dt({
                    t: fn.ge(".main_column_pic img").alt,
                    d: r
                });
            }
        },
        category: "nsfw2"
    }, {
        name: "人体艺术",
        link: "https://dsqs8.com/",
        url: {
            e: ".umBody",
            p: /^\/post\/\d+/
        },
        init: () => {
            fn.clearAllTimer();
            fn.createImgBox(".viewall_plugin", 2);
        },
        imgs: ".LightGallery_Item",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".viewall_plugin"], 2
        ],
        autoDownload: [0],
        next: ".prev>a",
        prev: ".next>a",
        customTitle: "h1.tit",
        category: "nsfw2"
    }, {
        name: "上流时尚人体艺术/美女坊",
        url: {
            h: [
                /6643\.live$/,
                /mnrt\.xyz$/
            ],
            p: /^\/html\/\d+\/n-\d+\.html$/
        },
        imgs: () => {
            let [max] = fn.gt("a.next", 2).match(/\d+$/);
            let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url.replace(".html", "") + `-${i + 1}.html`);
            return fn.getImgA("#d_BigPic img,.arcbody img", links);
        },
        button: [4],
        insertImg: ["#efpBigPic,.arcbody", 2],
        autoDownload: [0],
        next: "#efpNextTxt>a,.arcLocal a:last-child",
        prev: "#efpPreTxt>a,.arcLocal a",
        customTitle: "#d_picTit,.arctitle>h1>a",
        category: "nsfw2"
    }, {
        name: "Girl Girl Go",
        reg: /^https?:\/\/(\w{2}\.)?(girlgirlgo|girlygirlpic)\.(org|net|xyz|icu|com|biz|top)\/a\/\w+/,
        imgs: ".figure-link",
        button: [4],
        insertImg: [".post-media-body", 2],
        next: async () => {
            await fn.waitEle("a[rel=next]", 30);
            let next = fn.ge("a[rel=next]");
            return next ? next.href : null;
        },
        prev: "a[rel=prev]",
        customTitle: () => fn.waitEle(".figure-link").then(() => fn.gt(".entry-title a").split(" No.")[0].trim()),
        category: "nsfw1"
    }, {
        name: "QGirlz/CuteLadyPic",
        url: {
            e: [
                ".main-image",
                "//a[@data-title and picture/source]",
                ".next",
                ".main-title"
            ]
        },
        imgs: () => fn.getImg("//a[@data-title and picture/source]", (fn.gt(".next", 2) || 1), 16),
        button: [4],
        insertImg: [".main-image", 2],
        customTitle: () => fn.gt(".main-title").split(" No.")[0].trim(),
        category: "nsfw1"
    }, {
        name: "QGirlz/CuteLadyPic M",
        url: {
            p: "/m/",
            e: [
                ".place-padding+.place-padding",
                "//a[@data-title and picture/source]",
                ".prev-next-page",
                ".blog-title",
                "#post-tag"
            ]
        },
        init: () => fn.createImgBox("#post-tag", 1),
        imgs: () => {
            let [, max] = fn.gt(".prev-next-page").match(/\d+/g);
            return fn.getImg("//a[@data-title and picture/source]", max, "4");
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#content>div:first-child[style],#content>article,#content>.place-padding:not([id])"], 2
        ],
        customTitle: () => fn.gt(".blog-title").split(" No.")[0].trim(),
        category: "nsfw1"
    }, {
        name: "cn.angirlz.com", //SPA
        reg: /^https?:\/\/\w{2}\.angirlz\.com\/album\/\w+/,
        imgs: async () => await fn.waitEle(".loading[style$=hidden]") ? fn.gae("#divGallery a") : [],
        button: [4],
        insertImg: ["div[key=album_main]", 2],
        customTitle: "h1",
        category: "nsfw2"
    }, {
        name: "KawaiiX系列 一 分頁",
        url: {
            p: /^\/[^/]+\/\w+/,
            e: [
                ".separator>a[href]",
                ".album-post-body .clear,.album-post-share-wrap",
                ".nav-links"
            ]
        },
        imgs: () => fn.getImg(".separator>a[href]", (fn.gt(".nav-links>*:last-child", 2) || 1), 16),
        button: [4],
        insertImg: [
            [".album-post-body .clear,.album-post-share-wrap", 1, "div[itemprop='description articleBody'],.album-post-body>*:not(.album-post-inner):not(.album-post-share-wrap):not(#FullPictureLoadOptionsButtonParentDiv,.FullPictureLoadImage,a[data-fancybox]):not(#FullPictureLoadEnd)"], 2
        ],
        customTitle: ".breadcrumbs>span:last-child",
        hide: "#openRss",
        category: "nsfw2"
    }, {
        name: "KawaiiX系列 一",
        url: {
            e: ".album-post-inner,.album-postmeta-primarypix"
        },
        imgs: ".separator>a[href]",
        button: [4],
        insertImg: [
            [".album-post-inner,.album-postmeta-primarypix", 2, ".separator"], 2
        ],
        customTitle: ".breadcrumbs>span:last-child",
        hide: "#openRss",
        category: "nsfw2"
    }, {
        name: "KawaiiX系列 二 分頁",
        url: {
            e: [
                "//a[@data-title and picture/source]",
                ".hero+.hero,.entry-content,.d-flex>.col-24,.album-post",
                ".entry-title,.album-title,.album-post-title,.col-12>h1,.album-h1",
                ".nav-links"
            ]
        },
        imgs: () => {
            let max;
            fn.ge(".current-page") ? max = fn.gt(".current-page").match(/\d+$/)[0] : max = fn.gt(".nav-links>*:last-child", 2) || 1;
            return fn.getImg("//a[@data-title and picture/source]", max, 16);
        },
        button: [4],
        insertImg: [".hero+.hero,.entry-content,.d-flex>.col-24,.album-post", 2],
        customTitle: () => fn.gt(".entry-title,.album-title,.album-post-title,.col-12>h1,.album-h1").split(" No.")[0].trim(),
        css: ".flex-grid:not(.masonry){display:block!important;}",
        hide: "#openRss,div.loading[style]",
        category: "nsfw2"
    }, {
        name: "KawaiiX系列 二",
        url: {
            e: [
                ".hero+.hero,.entry-content,.d-flex>.col-24,.album-post",
                ".entry-title,.album-title,.album-post-title,.col-12>h1,.album-h1",
                "//a[@data-title and picture/source]"
            ]
        },
        imgs: "//a[@data-title and picture/source]",
        button: [4],
        insertImg: [".hero+.hero,.entry-content,.d-flex>.col-24,.album-post,.album-h1", 2],
        customTitle: () => fn.title(/\s-\s[\w\.]+$/i).replace(/\s?\(\d+\s?photos\)/, "").trim(),
        hide: "#openRss,div.loading[style]",
        category: "nsfw2"
    }, {
        name: "壹纳网",
        host: ["yinaw.com"],
        reg: /^https?:\/\/yinaw\.com\/\d+\.html$/,
        include: ".article-content img:not([src*='yinaw.png'])",
        init: async () => {
            let baiduApi = "https://image.baidu.com/search/down?thumburl=https://baidu.com&url=";
            let links = fn.gau(".fenye>a");
            if (links.length > 0) {
                await fn.getEle(links, ".article-content>*:not(.open-message,.fenye,.article-social)", [".open-message", 1], ".fenye");
            }
            let imgs = fn.gae(".article-content img:not([src*='yinaw.png'])");
            imgs.forEach(img => {
                if (/^https?:\/\/\w+\.sinaimg\.cn\//.test(img.src)) {
                    img.dataset.src = img.src.replace(/^(https?:\/\/\w+\.sinaimg\.cn\/)/, `${baiduApi}$1`).replace("/mw690/", "/large/");
                } else if (/^https?:\/\/i\d\.wp\.com\//.test(img.src)) {
                    img.dataset.src = img.src.replace("/mw690/", "/large/").replace(/\?w=.+$/, "").replace(/^https?:\/\/i\d\.wp\.com\//, `${baiduApi}https://`);
                } else {
                    img.dataset.src = img.src.replace("/mw690/", "/large/");
                }
            });
            if (setYinawSinaOriginalURL == 1) {
                imgs.forEach(img => (img.dataset.src = img.dataset.src.replace(baiduApi, "")));
            }
            imgs.forEach(img => {
                img.src = loading_bak;
                fn.imagesObserver.observe(img);
            });
        },
        imgs: ".article-content img:not([src*='yinaw.png'])",
        autoDownload: [0],
        next: ".article-nav-prev>a",
        prev: ".article-nav-next>a",
        customTitle: ".article-title",
        referer: "https://weibo.com/",
        category: "nsfw1"
    }, {
        name: "D哥新聞",
        host: ["dbro.news"],
        link: "https://dbro.news/category/p0-%e5%a5%97%e5%9c%96%e7%b3%bb%e5%88%97",
        url: {
            h: "dbro.news"
        },
        imgs: ".pic_center>img,.content_left img,.container img.mt-1,.wp-block-gallery img,a.jig-link,.pages img,.post-content img",
        customTitle: ".post-title",
        category: "nsfw2"
    }, {
        name: "流量密碼",
        host: ["jo106.com"],
        link: "https://jo106.com/beauty-photo/",
        reg: /^https?:\/\/jo106\.com\/\d+\/$/i,
        include: "//div[@class='cat-links']/a[text()='美女圖片'][@rel='category tag']",
        imgs: ".entry-content .col-md-12>img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "R18成人站-流量密碼",
        host: ["r18.jo106.com"],
        reg: /^https?:\/\/r18\.jo106\.com\/\d+\/$/i,
        include: "//div[@class='cat-links']/a[text()='成人漫畫' or text()='清涼寫真' or  text()='歐美寫真' or  text()='性感激情' or  text()='絲襪美腿'][@rel='category tag']",
        imgs: ".entry-content .col-md-12>img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /– 貼圖 –.+/
        }),
        category: "nsfw2"
    }, {
        name: "正妹六区",
        url: {
            h: "prettysix.com",
            p: "/thread"
        },
        imgs: "img[id^=aimg][zoomfile]",
        customTitle: "#thread_subject",
        category: "nsfw2"
    }, {
        name: "18成人貼圖",
        host: ["www.sexphotos.cc"],
        reg: /^https?:\/\/www\.sexphotos\.cc\/\w+\/\d+\.html$/,
        init: () => fn.waitEle(".article-body>img").then(e => fn.createImgBox(e, 1)),
        imgs: ".article-body>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".article-body>img"], 2
        ],
        autoDownload: [0],
        next: "a.entry-page-prev[href$=html]",
        prev: "a.entry-page-next[href$=html]",
        customTitle: ".detail-title",
        category: "nsfw2"
    }, {
        name: "尼克成人網 人體寫真",
        host: ["nick20.com"],
        link: "https://nick20.com/pic/index.html",
        reg: /^https?:\/\/nick20\.com\/pic\/pic\d+\.html$/i,
        imgs: () => {
            thumbnailSrcArray = _unsafeWindow.Large_cgurl.filter(item => item);
            return thumbnailSrcArray.map(e => e.replace("https://thumbs", "https://images").replace("_t.", "_o."));
        },
        button: [4],
        insertImg: ["//center[img]", 2],
        customTitle: ".bbs_entry_wrapper>h2",
        category: "nsfw2"
    }, {
        name: "尼克成人網 成人漫畫",
        reg: /^https?:\/\/nick20\.com\/bbs2\/index\.cgi\?read=\d+/i,
        imgs: "a[id][onclick]",
        button: [4],
        insertImg: ["p.img", 2],
        customTitle: ".bbs_entry_wrapper>h2",
        category: "nsfw2"
    }, {
        name: "尼克成人網 成人貼圖 本土自拍 走光偷拍",
        reg: /^https?:\/\/nick20\.com\/bbs(3|5)?\/\d+\.html/i,
        imgs: "p#img>img",
        button: [4],
        insertImg: ["p#img", 2],
        customTitle: ".bbs_entry_wrapper>h2",
        category: "nsfw2"
    }, {
        name: "尼克成人網M",
        host: ["m.nick20.com"],
        link: "https://nick20.com/pic/index.html",
        reg: [
            /^https?:\/\/m\.nick20\.com\/pic\/index\.(html|cgi)\?read=\d+$/i,
            /^https?:\/\/m\.nick20\.com\/bbs(2|3|5)?\/\d+\.html$/i
        ],
        imgs: () => {
            let [bp] = fn.gae(".bbs_pictures");
            let imgs = fn.gae("img", bp);
            return fn.getImgSrcArr(imgs).filter(src => !/\/images\/share|\/add\/|aav999/.test(src));
        },
        button: [4],
        insertImg: [".bbs_pictures", 2],
        customTitle: ".entryBlock>strong",
        category: "nsfw2"
    }, {
        name: "小濕妹圖庫",
        host: ["xsmpic.com"],
        reg: /^https?:\/\/xsmpic\.com\/\d+\/$/,
        imgs: ".entry-content img:not([data-src])",
        customTitle: "h1.entry-title",
        category: "nsfw2"
    }, {
        name: "五歌的开心网",
        host: ["happy.5ge.net"],
        reg: /^https?:\/\/happy\.5ge\.net\/archives\/\d+\.html$/,
        include: "//ul[@class='joe_bread__bread']//a[contains(text(),'图册')]",
        imgs: ".joe_detail__article img",
        button: [4],
        insertImg: [".joe_detail__article", 2],
        customTitle: ".joe_detail__title",
        fancybox: {
            v: 3,
            css: false
        },
        hide: "div:has(>center>a>img)",
        category: "nsfw2"
    }, {
        name: "漫画精品",
        host: ["xxxxn.click"],
        reg: /^https?:\/\/xxxxn\.click\/index\.php\/art\/detail\/id\/\d+\.html$/,
        imgs: ".photoList img",
        button: [4],
        insertImg: [".photoList", 2],
        customTitle: ".title",
        hide: "div:has(>div[title=Close]),div:has(>span[onclick])",
        category: "nsfw2"
    }, {
        name: "漫画精品 AD",
        reg: /^https?:\/\/xxxxn\.click\//,
        hide: ".colPhotoList:has(>div>a>img[style]),div:has(>div[title=Close]),div:has(>span[onclick])",
        category: "ad"
    }, {
        name: "我們的性愛日誌",
        host: ["www.sexdiary1769.com"],
        reg: /^https?:\/\/www\.sexdiary1769\.com\/article\/\d+$/,
        include: "//div[@class='category']/a[contains(text(),'寫真館')]",
        imgs: "#article-content img",
        button: [4],
        insertImg: ["#article-content", 2],
        customTitle: ".top-info h1",
        category: "nsfw2"
    }, {
        name: "湿女吧",
        host: ["shinv.pics"],
        reg: /^https?:\/\/shinv\.\w+\/posts\/\w+\/$/i,
        imgs: "//div[@class='p-1 col-span-12 md:col-span-9']//img[@class='block my-2 mx-auto']",
        button: [4],
        insertImg: ["//div[@class='p-1 col-span-12 md:col-span-9']", 2],
        customTitle: "h1.text-xl",
        category: "nsfw2"
    }, {
        name: "好视角",
        host: ["shijiao.meinvnews.com"],
        url: {
            e: ".logo img[alt=好视角]",
            p: /^\/\w+\.html$/
        },
        imgs: ".tit+.text img:not([onerror]),.tit+.pic img:not([onerror])",
        button: [4],
        insertImg: [".tit+.text,.tit+.pic", 2],
        autoDownload: [0],
        next: "//p[contains(text(),'上一篇')]/a",
        prev: "//p[contains(text(),'下一篇')]/a",
        customTitle: ".tit>h1,.grjs h1",
        css: ".tit+.text img{width:100%!important}",
        hide: ".tit+.pic img{margin:auto!important}.mbx_nav~div:not([class]),body>em",
        gallery: 1,
        category: "nsfw2"
    }, {
        name: "秘秘秘/美鲍儿",
        host: ["ktacf.click", "lingleis.info"],
        url: {
            e: "#menu_top_gg+.table,#content_top_gg"
        },
        imgs: "#content_top_gg+.titletablerow img",
        button: [4],
        insertImg: ["#content_top_gg+.titletablerow", 2],
        autoDownload: [0],
        next: "//div[text()='下篇']/preceding-sibling::div[1]/a",
        prev: "//div[text()='上篇']/following-sibling::div[1]/a",
        customTitle: ".cell3.clmtop3",
        hide: "#header,#sidebar_left,#sidebar_right,.logo_top_gg,#menu_top_gg,#menu_bottom_gg,#content_top_gg,#content_bottom_gg,#page_bottom_top_gg,#page_bottom_bottom_gg,div:has(>#page_bottom_link_gg)",
        category: "nsfw2"
    }, {
        name: "秘秘秘/美鲍儿 AD",
        url: {
            e: ".topbody .logo+.table,#menu_top_gg+.table"
        },
        hide: "#tnoticegg,.topnotice,#header,#sidebar_left,#sidebar_right,.logo_top_gg,#menu_top_gg,#menu_bottom_gg,#page_bottom_top_gg,#page_bottom_bottom_gg,div:has(>#page_bottom_link_gg),.titletablerow:has(>.titletablecell>a:not([href$=html]))",
        category: "ad"
    }, {
        name: "啪啪凸凸",
        host: ["papatutu.com"],
        url: {
            e: "#content.card-body",
            p: "/a/show/"
        },
        imgs: "div.lightbox",
        button: [4],
        insertImg: ["#content", 2],
        autoDownload: [0],
        next: "a:has(.fa-arrow-right)",
        prev: "a:has(.fa-arrow-left)",
        customTitle: ".container>h4",
        hide: "#span_h4",
        category: "nsfw2"
    }, {
        name: "播播阁",
        link: "https://www.boboge.lat/index",
        url: {
            h: "boboge",
            p: /^\/img\d+\//
        },
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        hide: "div[id^=ads]",
        category: "nsfw2"
    }, {
        name: "播播阁AD",
        url: {
            h: "boboge",
            e: "div[id^=ads]"
        },
        hide: "div[id^=ads]",
        category: "ad"
    }, {
        name: "超级资源分享",
        host: ["www.xiu07.com", "m.xiu07.com"],
        url: {
            t: "超级资源分享",
            p: "/detailimg/"
        },
        imgs: ".images img",
        button: [4],
        insertImg: [".images", 2],
        customTitle: ".srt h5",
        category: "nsfw2"
    }, {
        name: "哔咔庇护所v2",
        host: ["ios.zzgo810.top"],
        url: {
            t: "哔咔庇护所",
            s: "&catid="
        },
        exclude: "#dplayer.dplayer",
        init: async () => {
            fn.remove("//div[@class='row'][div/a/img]");
            await fn.waitEle("#lightbox~img");
        },
        imgs: () => fn.ge("#lightbox a") ? fn.gae("#lightbox a") : fn.gae("#lightbox~img"),
        button: [4],
        insertImg: ["//div[div[@id='lightbox']]", 2],
        customTitle: "#comic-view-main .text-center",
        category: "nsfw2"
    }, {
        name: "G-AVSTAR",
        url: {
            h: "g-avstar.com",
            p: /^\/\d+\/\d+\/\d+\/[^\/]+\/$/,
            e: "//p[contains(text(),'更多美图')]"
        },
        init: () => fn.createImgBox(".ngg-galleryoverview", 1),
        imgs: async () => {
            await fn.getNP(".ngg-gallery-thumbnail-box", ".ngg-navigation>span.current+a:not(.prev)", null, ".ngg-navigation");
            return fn.gae(".ngg-gallery-thumbnail a")
        },
        thums: ".ngg-gallery-thumbnail img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".ngg-galleryoverview,.ngg-navigation"], 2
        ],
        customTitle: ".entry-title",
        category: "nsfw2"
    }, {
        name: "瓜老師の鉴赏课",
        url: {
            h: "photo.lovegua.com",
            p: /^\/\d+\.html$/
        },
        init: () => fn.createImgBox("p:has(>img)", 1),
        imgs: "p:has(>img)>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "p:has(>img)"], 2
        ],
        autoDownload: [0],
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".title.single",
        category: "nsfw2"
    }, {
        name: "XO福利圖",
        links: [
            "https://kb1.a7xofulitu.com/%E5%84%BF%E6%AD%8C%E4%B8%89%E7%99%BE%E9%A6%96/",
            "https://www.xofulitu521.xyz/xoxo",
            "https://www.xofulitu9ok999.xyz/xoxo",
            "https://diedk1123-ake33i.xofulitu2za222.sbs/xoxo",
            "https://ponds-attract-ducks.xofulitu1qqq111.xyz/xoxo"
        ],
        url: {
            t: "XO福利圖",
            h: "xofulitu",
            e: ".picture-wrap img",
            p: /\/art\/pic\/id\/\d+\/$/i
        },
        imgs: () => fn.getImgSrcArr(".picture-wrap img").filter(src => !src.includes("loading")),
        button: [4],
        insertImg: [".container.clearfix", 2],
        go: 1,
        customTitle: () => fn.dt({
            d: [
                / - XO福利圖.+$/,
                /[\/\s]?[\(\[(【“]\d+[\w\s\\\/\.+-/]+[\)\])】”]|\s?\d+p[\+\s]+\d+v|\s?\d+p\d+v|\s?\d+P|\(\d\)/gi,
                /[\s-]+$/
            ]
        }),
        hide: ".custom_link-wrapper,div:has(>#floating-ad)",
        category: "nsfw2"
    }, {
        name: "XO福利圖 分類自動翻頁",
        enable: 1,
        url: {
            h: "xofulitu",
            t: "XO福利圖",
            p: /^\/arttype\//i
        },
        autoPager: {
            ele: ".container.clearfix",
            observer: ".container.clearfix .album",
            next: ".paging-item--current+a",
            re: ".pagging-div",
            lazySrc: "img[data-src]",
            pageNum: ".paging-item--current"
        },
        openInNewTab: ".picture-list a:not([target=_blank])",
        hide: ".custom_link-wrapper,div:has(>#floating-ad)",
        category: "autoPager"
    }, {
        name: "XO福利圖AD",
        url: {
            h: "xofulitu",
            t: "XO福利圖"
        },
        hide: ".custom_link-wrapper,div:has(>#floating-ad)",
        category: "ad"
    }, {
        name: "ONS漂亮MM图库",
        host: ["ons.ooo"],
        link: "https://www.rb1.es/momotk/",
        reg: /^https?:\/\/ons\.ooo\/article\/\d+\/$/,
        imgs: ".article-content img",
        button: [4],
        insertImg: [".article-content", 2],
        customTitle: ".focusbox-title",
        category: "nsfw1"
    }, {
        name: "XXAV",
        host: ["www.xxav.one", "www.xxav2235.com"],
        reg: /^https?:\/\/(www\.xxav\.one|www\.xxav\d+\.com)\/view\/\d+\/\d+\/\d+\.html$/,
        init: () => fn.createImgBox("article:has(>img)", 1),
        imgs: "article>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "article:has(>img)"], 2
        ],
        autoDownload: [0],
        next: "//em[text()='上一篇:']/a",
        prev: "//em[text()='下一篇:']/a",
        customTitle: () => fn.title("-XXAV"),
        hide: ".suspend",
        category: "nsfw1"
    }, {
        name: "性福里",
        host: ["sexfull.av9238.com"],
        url: {
            h: "sexfull",
            p: /^\/img\/detail_\d+\.html$|^\/manhua\/chapter_[\d_]+\.html$/
        },
        imgs: ".left .image img",
        button: [4],
        insertImg: [".image", 2],
        autoDownload: [0],
        next: "//a[h2[contains(text(),'下一话')]]",
        prev: "//a[h2[contains(text(),'上一话')]]",
        customTitle: ".left h2",
        hide: ".container:has(>#advlist)",
        category: "nsfw2"
    }, {
        name: "性福里 AD",
        url: {
            h: "sexfull",
            e: "#advlist"
        },
        hide: ".container:has(>#advlist)",
        category: "ad"
    }, {
        name: "色色图库",
        host: ["www.sstuku13.xyz", "sstuku6.xyz", "sstuku7.xyz", "sstuku8.xyz", "sstuku9.xyz", "sstuku10.xyz", "sstuku11.xyz", "sstuku12.xyz", "sstuku13.xyz", "sstuku14.xyz", "sstuku15.xyz"],
        reg: /^https?:\/\/(www\.)?sstuku\d+\.xyz\/artshow-\d+\.html$/i,
        imgs: ".entry-media img",
        button: [4],
        insertImg: [".entry-content", 2],
        go: 1,
        customTitle: () => fn.dt({
            s: ".single-post-detail",
            d: "😋 "
        }),
        category: "nsfw1"
    }, {
        name: "wholsp",
        host: ["www.wholsp.com", "wholsp.comc"],
        url: {
            h: "wholsp.com",
            p: "/resource/"
        },
        imgs: "p[data-fancybox]",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        customTitle: ".article-title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw2"
    }, {
        name: "美女写真图集",
        host: ["www.112ze.com", "112ze.com"],
        reg: /^https?:\/\/(www\.)?112ze\.com\/index\.php\/\w+\/\d+\.html$/i,
        imgs: ".post-content img",
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: ".mdui-text-black",
        fancybox: {
            v: 3,
            css: false
        },
        category: "nsfw1"
    }, {
        name: "聚姬集",
        host: ["18jjj.cyou", "18jjj.xyz"],
        reg: /^https?:\/\/18jjj\.\w+\/chapter\/\d+$/i,
        include: "#enc_img img",
        init: () => {
            fn.clearAllTimer();
            fn.remove("//div[@class='comicpage']/a[img[@alt]] | //div[@class='comicpage']/div[script] | //div[@id='cp_img']/a[img[@alt]] | //div[@id='cp_img']/div[script]");
        },
        imgs: async () => {
            await fn.getNP("#enc_img>div,#enc_img>img", "//a[text()='下一页'][@href]", null, ".fanye,.view-bottom-bar");
            return fn.gae("#enc_img img");
        },
        button: [4],
        insertImg: ["#enc_img", 2],
        customTitle: () => {
            if (fn.ge(".comic-name")) {
                return fn.gt(".comic-name");
            } else {
                let [, text] = fn.gst("bookInfo").match(/bookInfo[\s=]+([^;]+)/);
                let bookInfo = fn.run(text);
                return bookInfo.book_name;
            }
        },
        css: "img{opacity:1!important;}",
        hide: "#pubcdnModal",
        category: "nsfw1"
    }, {
        name: "adultspic色情成人圖片",
        host: ["adultspic.com"],
        reg: /^https?:\/\/adultspic\.com\/\d+\.html$/i,
        imgs: async () => {
            await fn.getNP(".wp-block-image", "//a[text()='下一頁']");
            return fn.gae(".wp-block-image img").map(e => e.src);
        },
        button: [4],
        insertImg: [".article-content", 2],
        autoDownload: [0],
        next: ".article-nav-prev>a",
        prev: ".article-nav-next>a",
        customTitle: ".article-title",
        hide: ".ssr-content",
        category: "nsfw2"
    }, {
        name: "中国街拍",
        host: ["jiepai.sifang.app"],
        url: {
            e: "meta[content=中国街拍]",
            p: /^\/\d+\/[\w-]+\.html$/
        },
        imgs: "a[data-fancybox]",
        button: [4],
        insertImg: [
            ["//p[a[img]]", 2, "//p[a[img]]"], 2
        ],
        customTitle: "article>h1",
        fancybox: {
            v: 3,
            css: false
        },
        css: "@media only screen and (max-width:480px){article{width:100%!important}}",
        category: "nsfw1"
    }, {
        name: "美图收藏夹",
        host: ["sifang.app"],
        reg: /^https?:\/\/sifang\.app\/node\/\d+$/i,
        imgs: "a[data-fancybox]",
        button: [4],
        insertImg: [
            ["//p[a[img]]", 2, "//p[a[img]]"], 2
        ],
        customTitle: ".page-title",
        fancybox: {
            v: 3,
            css: false
        },
        css: "@media only screen and (max-width:480px){article{width:100%!important}}",
        category: "nsfw1"
    }, {
        name: "名腿网",
        host: ["www.mingtuiw.com", "mingtui.net"],
        reg: /^https?:\/\/(www\.mingtuiw\.com|mingtui\.net)\/archives\/\d+$/,
        exclude: ".swpm-more-tag-not-logged-in,.swpm-more-tag-restricted-msg",
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".entry-content img");
            return thumbnailSrcArray.map(e => e.replace(/-\d+x\d+(\.\w+)$/, "$1"))
        },
        button: [4],
        insertImg: [".entry-content>p", 2],
        autoDownload: [0],
        next: ".nav-previous>a[rel=prev]",
        prev: ".nav-next>a[rel=next]",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /(\d+图)/
        }),
        category: "nsfw1"
    }, {
        name: "名腿网",
        host: ["www.mingtuiw.com"],
        reg: () => {
            if (/^https?:\/\/www\.mingtuiw\.com\/archives\/\d+$/.test(siteUrl)) {
                let [, num] = fn.gt(".entry-title").match(/((\d+)图)/);
                let tImgsNum = fn.gae(".entry-content img").length;
                if (num == tImgsNum) return true;
            }
            return false;
        },
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".entry-content img");
            return thumbnailSrcArray.map(e => e.replace(/-\d+x\d+(\.\w+)$/, "$1"))
        },
        button: [4],
        insertImg: [".entry-content>p", 2],
        autoDownload: [0],
        next: ".nav-previous>a[rel=prev]",
        prev: ".nav-next>a[rel=next]",
        customTitle: () => fn.dt({
            s: ".entry-title",
            d: /(\d+图)/
        }),
        category: "nsfw1"
    }, {
        name: "名腿网",
        host: ["www.mingtuiw.com"],
        reg: /^https?:\/\/www\.mingtuiw\.com\/archives\/\d+\/.+$/,
        exclude: "#div_img_vip",
        imgs: async () => {
            let links = fn.gau("#thumb_imglist>a");
            let imgSrcs = await fn.getImgA(".entry-content img.attachment-large", links);
            return imgSrcs.map(e => e.replace(/-\d+x\d+(\.\w+)$/, "$1"))
        },
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.dt({
            d: /(\d+\/\d+).+/
        }),
        category: "nsfw1"
    }, {
        name: "Ai19 Art/Ai art nude/Hentaimama",
        host: ["ai19.art", "ainudesporn.art", "hentaimama.xyz"],
        reg: /^https?:\/\/(ai19\.art|ainudesporn\.art|hentaimama\.xyz)\/news\//,
        imgs: ".entry-content img",
        button: [4],
        insertImg: [
            ["//p[img]", 2, "//p[img]"], 2
        ],
        endColor: "white",
        customTitle: () => fn.gt(".entry-header").replaceAll("|", "-"),
        category: "nsfw1"
    }, {
        name: "Kungfutv/Series Donghua",
        host: ["kungfutv.net", "seriesdonghua.net"],
        reg: [
            /^https?:\/\/kungfutv\.net\/cosplay\/[^\/]+\//,
            /^https?:\/\/seriesdonghua\.net\/cosplay\/[^\/]+\//
        ],
        imgs: "#readerarea img",
        button: [4],
        insertImg: [
            ["#readerarea img", 1, ".ts-main-image"], 2
        ],
        endColor: "white",
        customTitle: ".entry-title",
        category: "nsfw1"
    }, {
        name: "18Kami.com",
        host: ["18kami.com", "www.18kami.com"],
        reg: /^https?:\/\/(www\.)?18kami\.com\/photo\/\d+/,
        imgs: ".thumb-overlay-albums img",
        button: [4],
        insertImg: [".thumb-overlay-albums", 2],
        endColor: "white",
        customTitle: ".panel-heading>.pull-left",
        fetch: 1,
        observerClick: "#chk_cover",
        category: "hcomic"
    }, {
        reg: /^https?:\/\/(www\.)?18kami\.com\//,
        observerClick: "#chk_cover",
        category: "ad"
    }, {
        name: "逆次元逆ACG",
        host: ["www.nicohentai.com", "www.freeacg.org", "www.freeacg2.org", "acg.taipei", "nico.yt"],
        url: {
            e: "#Comic_Top_Nav img[alt=logo][src$='_nico.png']",
            p: /^\/(moeupup-\d-\d+\.html|showinfo-\d+-\d+-\d\.html)$/
        },
        init: () => fn.getNP(".row.thumb-overlay-albums img", ".pagination li.active+li>a:not(.prevnext)"),
        imgs: ".row.thumb-overlay-albums img",
        button: [4],
        insertImg: [".row.thumb-overlay-albums", 2],
        next: "//a[span[text()='下一页']][@href]",
        prev: 1,
        customTitle: () => fn.fetchDoc(fn.gu("//a[span[text()='漫畫簡介']]")).then(albumDoc => {
            let comicName = fn.gt(".panel-heading h1", 1, albumDoc);
            let episode = fn.ge(".episode", albumDoc);
            return episode ? comicName + " - " + fn.gt(".panel-heading>.pull-left") : comicName;
        }).then(text => fn.dt({
            t: text,
            d: [
                /\(\d+[\w\s\.\+-]+\)/i,
                /[\d+[\w\s\.\+-]+]/i
            ]
        })),
        category: "hcomic"
    }, {
        name: "Comic18H",
        host: ["www.comic18h.com"],
        reg: /^https:\/\/www\.comic18h\.com\/chapter\/\d+\.html$/,
        imgs: async () => {
            if (hasTouchEvent) {
                await fn.getNP("#readerarea>div", "//ul[@class='pagination']//a[text()='Next»']");
            } else {
                await fn.getNP("#readerarea>div", ".pagination li.active+li>a:not(.prevnext)");
            }
            return fn.gae("#readerarea img");
        },
        button: [4],
        insertImg: ["#readerarea", 2],
        next: "//a[text()='Next Article»'][contains(@href,'.html')]",
        prev: "//a[text()='«Previous Chapter'][contains(@href,'.html')]",
        customTitle: ".entry-title",
        hide: ".code-block:has(>.ads),.hidden-xs:has(>.pagination)",
        observerClick: "#chk_cover",
        category: "hcomic"
    }, {
        reg: /^https?:\/\/www\.comic18h\.com\//,
        observerClick: "#chk_cover",
        hide: ".code-block:has(>.ads)",
        category: "ad"
    }, {
        name: "Doujindesu.XXX",
        url: {
            h: "doujindesu.tv",
            e: "#reader>.main"
        },
        init: async () => {
            await fn.waitEle("#reader>.main img");
            for (const sheet of document.styleSheets) {
                if (sheet.href?.includes("doujindesu.css")) {
                    for (const rule of sheet.rules) {
                        if (rule.selectorText === ".darkmode input, .darkmode button") {
                            rule.style.setProperty("color", "#fff");
                            return;
                        }
                    }
                }
            }
        },
        imgs: () => fn.gae("#reader>.main img"),
        button: [4],
        insertImg: ["#reader>.main", 2],
        next: "a:has(>.fa-chevron-right):not([href='#'])",
        prev: "a:has(>.fa-chevron-left):not([href='#'])",
        customTitle: "#reader h1",
        category: "hcomic"
    }, {
        name: "Doujindesu",
        url: {
            h: "doujindesu.click"
        },
        imgs: "#readerarea img",
        button: [4],
        insertImg: ["#readerarea", 2],
        next: ".ch-next-btn:not(.disabled)",
        prev: ".ch-prev-btn:not(.disabled)",
        customTitle: ".entry-title",
        hide: ".blox.mlb.kln",
        category: "hcomic"
    }, {
        name: "熱辣漫畫",
        url: {
            h: [
                /^(www\.)?relamanhua\.org$/,
                "www.2024manga.com"
            ],
            e: [
                ".disData[contentKey]",
                ".comicContent-list"
            ],
            i: 0
        },
        init: async () => {
            await fn.waitVar("webpackJsonp");
            fn.copymangaUI();
            fn.createImgBox(".comicContent-list", 1);
            let readHistoryData = localStorage.getItem("readHistory");
            let [, , word, , id] = fn.lp.split("/");
            let json;
            readHistoryData ? json = JSON.parse(readHistoryData) : json = {};
            json[word] = id;
            localStorage.setItem("readHistory", JSON.stringify(json));
        },
        imgs: (dom = document) => {
            let contentKey = fn.attr(".disData", "contentKey", dom);
            return fn.cm_decrypt(contentKey).map(e => e.url.replace("800x.", "1500x."));
        },
        button: [4, "24%", 2],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".comicContent-list"], 2
        ],
        endColor: "white",
        next: "//a[text()='下一話'][starts-with(@href,'/')]",
        prev: "//a[text()='上一話'][starts-with(@href,'/')]",
        customTitle: (dom = document) => fn.dt({
            t: dom.title,
            d: / - 熱辣漫畫.+$/
        }),
        preloadNext: true,
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "熱辣漫畫 自動翻頁",
        url: {
            h: [
                /^(www\.)?relamanhua\.org$/,
                "www.2024manga.com"
            ],
            e: [
                ".disData[contentKey]",
                ".comicContent-list"
            ],
            i: 1
        },
        setReadHistory: () => {
            let readHistoryData = localStorage.getItem("readHistory");
            let [, , word, , id] = new URL(document.URL).pathname.split("/");
            let json;
            readHistoryData ? json = JSON.parse(readHistoryData) : json = {};
            json[word] = id;
            localStorage.setItem("readHistory", JSON.stringify(json));
        },
        getSrcs: (dom) => {
            let contentKey = fn.attr(".disData", "contentKey", dom);
            let srcs = fn.cm_decrypt(contentKey).map(e => e.url.replace("800x.", "1500x."));
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            await fn.waitVar("webpackJsonp");
            fn.copymangaUI();
            let tE = fn.createImgBox(".comicContent-list", 1);
            let imgs = _this.getImgs();
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            fn.remove(".comicContent-list");
            await fn.lazyload();
            _this.setReadHistory();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: "//a[text()='下一話'][starts-with(@href,'/')]",
            title: (dom) => dom.title.replace(/ - 熱辣漫畫.+$/, ""),
            re: ".header,.footer",
            preloadNextPage: 1,
            aF: () => _this.setReadHistory()
        },
        category: "comic autoPager"
    }, {
        name: "熱辣漫畫 目錄頁",
        url: {
            h: [
                /^(www\.)?relamanhua\.org$/,
                "www.2024manga.com"
            ],
            p: /^\/comic\/\w+$/
        },
        init: async () => {
            await fn.waitEle(".tab-pane.show.active a");
            const updateLastChapter = () => {
                let [, , comic] = fn.lp.split("/");
                let readHistoryData = localStorage.getItem("readHistory");
                if (!!readHistoryData) {
                    let json = JSON.parse(readHistoryData);
                    if (comic in json) {
                        let selector = `.tab-content a[href$="${json[comic]}"]`;
                        fn.gae(".lastchapter").forEach(a => a.classList.remove("lastchapter"));
                        fn.gae(selector).forEach(a => a.classList.add("lastchapter"));
                        setTimeout(() => {
                            let lastReadUrl = fn.lp + "/chapter/" + json[comic];
                            let lastText = fn.ge(".lastchapter").title;
                            let lastE = fn.ge("#lastRead");
                            if (!lastE && !fn.ge("//span[contains(text(),'最後閱讀')]")) {
                                let a = document.createElement("a");
                                a.id = "lastRead";
                                a.target = "_blank";
                                let tableRight = fn.ge(".table-default-right");
                                tableRight.insertAdjacentElement("afterbegin", a);
                                const span = document.createElement("span");
                                span.innerText = "最後閱讀:";
                                tableRight.insertAdjacentElement("afterbegin", span);
                                a.href = lastReadUrl;
                                a.innerText = lastText;
                            } else if (!!lastE) {
                                let a = lastE;
                                a.href = lastReadUrl;
                                a.innerText = lastText;
                            }
                        }, 200);
                    }
                }
            };
            updateLastChapter();
            document.addEventListener("visibilitychange", updateLastChapter);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            setTimeout(() => fn.clearAllTimer(3), 1000);
        },
        css: ".lastchapter{color:#fff !important;background:#ff0000}",
        hide: ".comicDetailAds",
        category: "none"
    }, {
        name: "熱辣漫畫M",
        url: {
            h: ["m.relamanhua.org", "m.2024manga.com"],
            p: "/v2h5/comicContent/",
            i: 0
        },
        xhrJson: (url = siteUrl) => {
            let split = url.split("/");
            let word = split.at(-2);
            let id = split.at(-1);
            let api = `https://mapi.fgjfghkk.club/api/v3/comic/${word}/chapter/${id}?platform=1&_update=true`;
            return fetch(api).then(res => res.json());
        },
        init: async () => {
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            siteJson = await _this.xhrJson();
            debug("\n此頁JSON資料\n", siteJson);
            let word = siteUrl.split("/").at(-2);
            let url = `/v2h5/details/comic/${word}`;
            let hUrl = "/v2h5/index";
            const addHtml = (url, text) => {
                let str = `<div style="padding: 10px 0; text-align: center;"><a href="${url}"style="width: 100%;font-size: 26px;line-height: 50px;height: 50px;text-align: center;">${text}</a></div>`;
                fn.ge("#comicContentMain").insertAdjacentHTML("afterend", str);
            };
            addHtml(hUrl, "首頁");
            addHtml(url, "目錄");
            let nUrl = _this.next();
            if (nUrl) addHtml(nUrl, "點選進入下一話");
        },
        imgs: (json = siteJson) => json.results.chapter.contents.map(e => e.url),
        button: [4],
        insertImg: ["#comicContentMain", 2],
        next: () => {
            let next = siteJson.results.chapter.next;
            return next ? siteUrl.replace(/[\w-]+$/, "") + next : null;
        },
        customTitle: () => siteJson.results.comic.name + " - " + siteJson.results.chapter.name,
        preloadNext: (nextDoc, obj) => {
            obj.xhrJson(nextLink).then(json => {
                let srcs = obj.imgs(json);
                let title = json.results.comic.name + " - " + json.results.chapter.name;
                fn.picPreload(srcs, title, "next");
            });
        },
        fancybox: {
            blacklist: 1
        },
        infiniteScroll: true,
        css: ".comicContentPopup #comicContentMain{position:unset!important}",
        hide: ".comicFixed",
        category: "comic"
    }, {
        name: "熱辣漫畫M 自動翻頁",
        url: {
            h: ["m.relamanhua.org", "m.2024manga.com"],
            p: "/v2h5/comicContent/",
            i: 1
        },
        getData: () => {
            let split = document.URL.split("/");
            let word = split.at(-2);
            let id = split.at(-1);
            let api = `https://mapi.fgjfghkk.club/api/v3/comic/${word}/chapter/${id}?platform=1&_update=true`;
            return fetch(api).then(res => res.json()).then(json => {
                globalImgArray = json.results.chapter.contents.map(e => e.url);
                customTitle = json.results.chapter.name;
                let next = json.results.chapter?.next;
                console.log("\n熱辣漫畫M_JSON\n", json, globalImgArray, customTitle, next);
                if (!!next) {
                    tempNextLink = document.URL.replace(/[^\/]+$/, "") + next;
                } else {
                    tempNextLink = null;
                }
            });
        },
        init: async () => {
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getData();
            let imgs = fn.createImgArray(globalImgArray);
            let tE = fn.ge("#comicContentMain");
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            fn.hideMsg();
            let word = siteUrl.split("/").at(-2);
            let url = `/v2h5/details/comic/${word}`;
            let hUrl = "/v2h5/index";
            const addHtml = (url, text) => {
                let str = `<div style="padding: 10px 0; text-align: center;"><a href="${url}"style="width: 100%;font-size: 26px;line-height: 50px;height: 50px;text-align: center;">${text}</a></div>`;
                fn.ge("#comicContentMain").insertAdjacentHTML("afterend", str);
            };
            addHtml(hUrl, "首頁");
            addHtml(url, "目錄");
        },
        autoPager: {
            ele: () => fn.createImgArray(globalImgArray),
            pos: ["#comicContentMain", 0],
            observer: "#comicContentMain>img",
            next: () => tempNextLink,
            wait: async () => await _this.getData(),
            title: () => customTitle
        },
        css: ".comicContentPopup #comicContentMain{position:unset!important}",
        hide: ".comicFixed",
        category: "comic autoPager"
    }, {
        name: "熱辣漫畫 清除不給開啟開發人員工具",
        url: {
            h: [
                /^(www\.|m.)?relamanhua\.org$/,
                /^(www\.|m.)?2024manga.com$/
            ],
        },
        init: () => {
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            setTimeout(() => fn.clearAllTimer(3), 1000);
        },
        category: "ad"
    }, {
        name: "禁漫天堂",
        url: {
            e: "meta[property='og:site_name'][content=禁漫天堂]",
            p: /^\/photo\/\d+/
        },
        imgs: async () => {
            await fn.getNP(".scramble-page", ".pagination li.active+li>a:not(.prevnext)");
            fn.showMsg(displayLanguage.str_01, 0);
            const {
                aid,
                scramble_id,
                get_num
            } = _unsafeWindow;
            let arr = [];
            let fetchNum = 0;
            let imgs = fn.gae(".scramble-page img[id],.owl-item .center img[id]");
            for (let i = 0; i < imgs.length; i++) {
                let getRedraw = new Promise(async resolve => {
                    const url = imgs[i].dataset.original ?? imgs[i].dataset.src;
                    let error = false;
                    if (url.includes(".gif") || aid < scramble_id) {
                        resolve(url);
                    } else {
                        const blob = await fetch(url).then(res => res.blob());
                        const fileName = new URL(url).pathname.split("/").at(-1);
                        const [id, ex] = fileName.split(".");
                        const img = new Image();
                        await new Promise(load => {
                            img.onload = load;
                            img.onerror = () => {
                                error = true;
                                resolve(null);
                            }
                            img.src = URL.createObjectURL(blob);
                        });
                        if (error) return;
                        const imgWidth = img.naturalWidth;
                        const imgHeight = img.naturalHeight;
                        const canvas = new OffscreenCanvas(imgWidth, imgHeight);
                        const canvas_2d = canvas.getContext("2d");
                        const num = get_num(btoa(aid), btoa(id));
                        const cropHeight = Number(imgHeight % num);
                        const sHeight = Math.floor(imgHeight / num);
                        let sy = imgHeight - cropHeight - sHeight;
                        let dy = cropHeight;
                        canvas_2d.drawImage(img, 0, sy, imgWidth, cropHeight + sHeight, 0, 0, imgWidth, cropHeight + sHeight);
                        for (let i = 1; i < num; ++i) {
                            canvas_2d.drawImage(img, 0, sy -= sHeight, imgWidth, sHeight, 0, dy += sHeight, imgWidth, sHeight);
                        }
                        URL.revokeObjectURL(img.src);
                        canvas.convertToBlob({
                            type: blob.type,
                            quality: 0.9
                        }).then(blob => {
                            fn.showMsg(`DrawImage ${fetchNum+=1}/${imgs.length}`, 0);
                            resolve(URL.createObjectURL(blob));
                        });
                    }
                });
                arr.push(getRedraw);
                await delay(100);
            }
            return arr;
        },
        button: [4, "24%", 1],
        insertImg: ["//div[@class='panel-body'][div[@class='row thumb-overlay-albums']]", 0],
        next: "//a[span[text()='下一話']][@href]",
        prev: 1,
        customTitle: () => {
            return fn.fetchDoc(fn.gu("//a[span[text()='漫畫簡介']]")).then(albumDoc => {
                let comicName = fn.gt(".panel-heading h1", 1, albumDoc).replaceAll("/", "").replace(/\s?\[禁漫漢化組\]/, "");
                let episode = fn.ge(".episode", albumDoc);
                if (episode) {
                    let [id] = fn.lp.match(/\d+/);
                    let selector = `.episode a[data-album="${id}"]`;
                    let text = fn.gt(selector, 1, albumDoc);
                    let [chapterName] = text.split("\n").filter(item => item);
                    return comicName + " - " + chapterName.replace(/\[\d+[\w\s\.\+-]+\]/i, "").trim();
                } else {
                    return comicName.replace(/\[\d+[\w\s\.\+-]+\]/i, "").trim();
                }
            });
        },
        fetch: 1,
        hide: ".hidden-lg:not(.panel)[style*='z-index'],div:has(>.photo_center_div)",
        observerClick: ["#chk_cover", "#chk_guide", "div[class^='btn_hide']"],
        category: "hcomic"
    }, {
        name: "禁漫天堂",
        url: {
            e: "meta[property='og:site_name'][content=禁漫天堂]",
        },
        observerClick: ["#chk_cover", "#chk_guide", "div[class^='btn_hide']"],
        category: "ad"
    }, {
        name: "E-Hentai圖片清單頁",
        url: {
            h: ["e-hentai.org", "exhentai.org"],
            p: /^\/g\/\d+\/\w+\/$/
        },
        exclude: "//h1[text()='Content Warning']",
        init: () => fn.createImgBox("#gdt", 2),
        imgs: async () => {
            await fn.getNP("#gdt>*", ".ptds+td>a", null, "//tr[td[@class='ptds']]");
            if (options.fancybox == 1 && !isDownloading) {
                //預覽縮圖網址需要裁剪難弄...
                if (fn.ge(".gdtm img[style],.gdtl img[style],#gdt>a>div[style*='url(']")) {
                    let num_a;
                    let num_b;
                    let thumbnailsHeightData = [...document.querySelectorAll(".gdtm img,.gdtl img,#gdt>a>div[style*='url(']")].map(e => Number(e.style.height.match(/\d+/)[0]));
                    let thumbnailUrls = [...document.querySelectorAll(".gdtm>div,.gdtl>div,#gdt>a>div[style*='url(']")].map(div => getComputedStyle(div).getPropertyValue("background-image").slice(5, -2));
                    num_a = thumbnailUrls.length;
                    thumbnailUrls = [...new Set(thumbnailUrls)];
                    num_b = thumbnailUrls.length;
                    if (num_a === num_b) {
                        thumbnailSrcArray = thumbnailUrls;
                    } else {
                        let getThumbnai = 0;
                        fn.showMsg("Get Thumbnailsing...", 0);
                        let blobs = thumbnailUrls.map((url, i, arr) => fn.xhr(url, {
                            responseType: "blob"
                        }).then(blob => {
                            fn.showMsg(`Get Thumbnails ${getThumbnai += 1}/${arr.length}`, 0);
                            return blob;
                        }));
                        let heightIndex = 0;
                        let crop = 0;
                        await Promise.all(blobs).then(async blobArr => {
                            fn.hideMsg();
                            for (let blob of blobArr) {
                                fn.showMsg(`Thumbnails Crop ${crop += 1}/${blobArr.length}`, 0);
                                //console.log(`預覽縮圖裁切第${crop}張`);
                                let img = new Image();
                                await new Promise((resolve, reject) => {
                                    img.onload = resolve;
                                    img.onerror = reject;
                                    img.src = URL.createObjectURL(blob);
                                });
                                for (let w = 0; w < img.width; w += 100) {
                                    let canvas = document.createElement("canvas");
                                    canvas.height = thumbnailsHeightData[heightIndex];
                                    canvas.width = 100;
                                    canvas.getContext("2d").drawImage(img, -Math.abs(w), 0);
                                    let dataURL = canvas.toDataURL("image/webp", 0.5);
                                    if (dataURL.startsWith("data:image/webp;")) {
                                        let thumbnailBlobURL = fn.dataURLtoBlobURL(dataURL);
                                        thumbnailSrcArray.push(thumbnailBlobURL);
                                        //console.log(thumbnailBlobURL);
                                        heightIndex++;
                                    }
                                }
                            }
                        });
                    }
                } else {
                    thumbnailSrcArray = [...document.querySelectorAll(".gdtm img,.gdtl img")].map(e => e.src);
                }
            }
            if (E_HENTAI_LoadOriginalImage == 1) {
                fn.showMsg(displayLanguage.str_01, 0);
                let fetchNum = 0;
                return fn.gau(".gdtm a,.gdtl a,#gdt a").map(async (url, i, arr) => {
                    await delay(100 * i);
                    return fn.fetchDoc(url).then(async (dom) => {
                        fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${arr.length}`, 0);
                        let fullimg = fn.ge("a[href*=fullimg]", dom);
                        let img = fn.ge("#img", dom);
                        if (fullimg) {
                            url = fullimg.href;
                            let res = await fn.xhrHEAD(url);
                            let finalUrl = res.finalUrl;
                            return /login\.php/.test(finalUrl) ? img.src : url;
                        } else {
                            return img.src;
                        }
                    });
                });
            } else {
                let links = fn.gau(".gdtm a,.gdtl a,#gdt a");
                return fn.getImgA("#img", links, 100);
            }
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: () => {
            let t = fn.gt("#gj").replace(/\/|\[\d+[\w\.\+\s-]+\]/i, "");
            return t.length > 0 ? t : fn.gt("#gn").replace(/\|.+|\[\d+[\w\.\+\s-]+\]/i, "").trim();
        },
        topButton: true,
        category: "hcomic"
    }, {
        name: "E-Hentai圖片清單頁",
        host: ["e-hentai.org"],
        link: "https://e-hentai.org/lofi/",
        reg: /^https?:\/\/e-hentai\.org\/lofi\/g\/\w+\/\w+\//,
        imgs: async () => {
            await fn.getNP(".gi,#gh>a", "//a[text()='Next Page >' or text()='下一页 >']", null, "#ia");
            let links = fn.gau(".gi>a,#gh>a");
            return fn.getImgA("#sm", links, 100);
        },
        button: [4],
        insertImg: [
            ["#ia", 2], 3
        ],
        customTitle: () => fn.title(" - E-Hentai", 1).replace(/\|.+/, "").replace(/\//, "").trim(),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "nhentai圖片清單頁",
        url: {
            h: [
                "nhentai.net",
                "nyahentai.red",
                "www.hentai.name",
                "nhentai.xxx",
                "nhentai.to",
                "nhentai.website",
                "simplyhentai.org"
            ],
            p: /^\/g\/\d+\/?$/
        },
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr("a.gallerythumb>img");
            if (fn.lh === "nhentai.net") {
                const hostArray = ["i", "i3", "i5", "i7"];
                const randomHost = arr => {
                    let choose = Math.floor(Math.random() * Math.floor(arr.length));
                    let rValue = arr[choose];
                    return rValue;
                };
                return _unsafeWindow._gallery.images.pages.map((e, i) => `https://${randomHost(hostArray)}.nhentai.net/galleries/${_unsafeWindow.gallery.media_id}/${i + 1}.${fn.ex(e.t)}`);
            } else if (fn.lh === "nyahentai.red") {
                fn.showMsg(displayLanguage.str_05, 0);
                let [imgDir] = fn.ge(".gallerythumb>img").src.match(/.+\//);
                let url = fn.gu("a.gallerythumb");
                return fn.iframeVar(url, "images_ext").then(w => w.images_ext.map((e, i) => `${imgDir}${(i + 1)}.${fn.ex(e)}`));
            } else if (fn.lh === "nhentai.xxx") {
                fn.showMsg(displayLanguage.str_05, 0);
                let [max] = fn.gt(".pages").match(/\d+/);
                let img = fn.ge(".gallery_thumbs img");
                let src = img.dataset.src ?? img.src;
                let [imgDir] = src.match(/.+\//);
                let url = fn.gu(".gallery_thumbs a");
                let iframe = await fn.iframeVar(url, "g_th");
                return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(iframe.g_th.fl[(i + 1)][0])}`);
            } else if (fn.lh === "nhentai.to" || fn.lh === "nhentai.website") {
                fn.showMsg(displayLanguage.str_05, 0);
                let url = fn.gu("a.gallerythumb");
                return fn.iframeVar(url, "reader").then(frame => {
                    const {
                        gallery,
                        image_cache
                    } = frame.reader;
                    const k = "1";
                    const [path] = image_cache[k].image.src.match(/^.+\//);
                    return gallery.images.pages.map((e, i) => `${path}${(i + 1)}.${fn.ex(e.t)}`);
                });
            } else if (fn.lh === "simplyhentai.org") {
                return fn.gae(".thumbs img,.thumb-container img").map(e => e.dataset.src ? e.dataset.src.replace(/t(\.\w+)$/, "$1") : e.src.replace(/t(\.\w+)$/, "$1"));
            } else if (fn.lh === "www.hentai.name") {
                return fn.gae(".thumb-container img").map(e => e.src.replace(/_thumb(\.\w+)$/, "$1"));
            }
        },
        button: [4],
        insertImg: [
            [".thumbs,#thumbnail-container,.outer_thumbs", 0], 2
        ],
        customTitle: () => {
            if (fn.lh === "nhentai.net") {
                const {
                    gallery
                } = _unsafeWindow;
                return gallery.title.japanese ?? gallery.title.english;
            } else {
                let h2 = fn.gt("h2.title,h2");
                return h2.length > 4 ? h2 : fn.gt("h1.title,h1");
            }
        },
        go: 1,
        topButton: true,
        hide: ".advt",
        category: "hcomic"
    }, {
        name: "nhentai閱讀頁",
        host: ["nhentai.net"],
        reg: /^https?:\/\/nhentai\.net\/g\/\d+\/\d+\/$/,
        imgs: () => {
            const {
                _gallery
            } = _unsafeWindow;
            const hostArray = ["i", "i3", "i5", "i7"];
            const randomHost = arr => {
                let choose = Math.floor(Math.random() * Math.floor(arr.length));
                let rValue = arr[choose];
                return rValue;
            };
            return _gallery.images.pages.map((e, i) => `https://${randomHost(hostArray)}.nhentai.net/galleries/${_gallery.media_id}/${i + 1}.${fn.ex(e.t)}`);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => {
            const {
                _gallery
            } = _unsafeWindow;
            return _gallery.title.japanese ?? _gallery.title.english;
        },
        category: "hcomic"
    }, {
        name: "nyahentai.red閱讀頁",
        reg: /^https?:\/\/nyahentai\.red\/g\/\d+\/\d+\/$/,
        imgs: () => {
            let [imgDir] = fn.ge("#image-container img").src.match(/.+\//);
            return _unsafeWindow.images_ext.map((e, i) => `${imgDir}${(i + 1)}.${fn.ex(e)}`);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => fn.title(" » ", 1),
        category: "hcomic"
    }, {
        name: "www.hentai.name閱讀頁",
        reg: /^https?:\/\/www\.hentai\.name\/g\/\d+\/\d+\/$/,
        imgs: () => {
            let max = fn.gt(".num-pages");
            let [, imgDir, ex] = fn.ge("#image-container img").src.match(/(.+\/)\d+(\.\w+)$/);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}${ex}`);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => fn.title(" - Hentai.name"),
        category: "hcomic"
    }, {
        name: "simplyhentai.org閱讀頁",
        reg: /^https?:\/\/simplyhentai\.org\/g\/\d+\/\d+\/$/,
        imgs: () => {
            let max = fn.gt(".num-pages");
            let [, imgDir, ex] = fn.ge("#image-container img").src.match(/(.+\/)\d+(\.\w+)$/);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}${ex}`);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => fn.title(" » ", 1),
        category: "hcomic"
    }, {
        name: "Yabai!",
        host: ["yabai.si"],
        reg: /^https?:\/\/yabai\.si\/g\/\w+$/i,
        init: async () => {
            await fn.waitEle(".grid img");
            fn.showMsg(displayLanguage.str_05, 0);
            let pageData = JSON.parse(document.querySelector("#app").dataset.page);
            let {
                version
            } = pageData;
            let token = decodeURIComponent(document.cookie.replace("XSRF-TOKEN=", ""));
            let readApi = fn.url + "/read";
            let fetchJson = await fetch(readApi, {
                "headers": {
                    "accept": "text/html, application/xhtml+xml",
                    "x-inertia": "true",
                    "x-inertia-version": version,
                    "x-requested-with": "XMLHttpRequest",
                    "x-xsrf-token": token
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", fetchJson);
            siteJson = fetchJson;
            fn.createImgBox(".article>:last-child", 2);
        },
        imgs: () => {
            let {
                code,
                hash,
                head,
                rand,
                root,
                type
            } = siteJson.props.pages.data.list;
            let srcs = [];
            head.forEach((e, i) => (srcs[Number(e) - 1] = `${root}/${code}/${e.padStart(4, "0")}-${hash[i]}-${rand[i]}.${type[i]}`));
            return srcs;
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        go: 1,
        customTitle: () => siteJson.props.post.data.name,
        category: "hcomic"
    }, {
        name: "Sukidesu.moe",
        host: ["sukidesu.moe"],
        reg: /^https?:\/\/sukidesu\.moe\/g\/\d+$/i,
        init: async () => {
            await fn.waitEle(".preview-imgs img");
            fn.showMsg(displayLanguage.str_05, 0);
            let [id] = fn.lp.match(/\d+/);
            let readApi = `https://sukidesu.moe/spa/manga/${id}/read`;
            let fetchJson = await fetch(readApi, {
                "headers": {
                    "accept": "application/json, text/plain, */*"
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", fetchJson);
            siteJson = fetchJson;
            fn.createImgBox(".preview-imgs", 2);
        },
        imgs: () => {
            const {
                server,
                chapter_content
            } = siteJson.chapter_detail;
            let dom = fn.doc(chapter_content);
            return fn.gae("[data-srcset]", dom).map(e => server + e.dataset.srcset);
        },
        thums: ".preview-imgs img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        go: 1,
        customTitle: () => siteJson.chapter_detail.manga_name,
        category: "hcomic"
    }, {
        name: "akuma.moe",
        reg: /^https?:\/\/akuma\.moe\/g\/\w+$/i,
        init: () => fn.waitEle("#pages"),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            const {
                pag,
                ajx
            } = _unsafeWindow;
            if (options.fancybox == 1 && !isDownloading) {
                let pages = pag.cnt;
                if (pages > 40) {
                    let max = Math.ceil(pages / 20);
                    let resArr = fn.arr(max, (v, i) => fetch(pag.act, {
                        "headers": {
                            "accept": "*/*",
                            "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                            "x-csrf-token": ajx.hdr["X-CSRF-TOKEN"],
                            "x-requested-with": "XMLHttpRequest"
                        },
                        "body": `index=${i}`,
                        "method": "POST",
                    }).then(res => res.text()).then(text => fn.doc(text)).then(dom => [...dom.images]));
                    thumbnailSrcArray = await Promise.all(resArr).then(data => fn.getImgSrcArr(data.flat()));
                } else {
                    thumbnailSrcArray = fn.getImgSrcArr("#pages img");
                }
            }
            let url = fn.gu("#pages a");
            let imgDir = await fn.iframeVar(url, "img_prt").then(w => w.img_prt + "/");
            return fetch(siteUrl, {
                "headers": {
                    "accept": "*/*",
                    "x-csrf-token": ajx.hdr["X-CSRF-TOKEN"],
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": null,
                "method": "POST"
            }).then(res => res.json()).then(arr => arr.map(e => imgDir + e));
        },
        button: [4],
        insertImg: [
            ["#pages", 0], 2
        ],
        go: 1,
        customTitle: () => fn.ge(".entry-header>span") ? fn.gt(".entry-header>span") : fn.gt(".entry-title"),
        category: "hcomic"
    }, {
        name: "SchaleNetwork",
        url: {
            h: ["shupogaki.moe", "hoshino.one", "niyaniya.moe"]
        },
        SPA: () => document.URL.includes("/g/"),
        observerURL: true,
        imgs: () => {
            const [, , g_id, g_key] = location.pathname.split("/");
            const detailApi = `https://api.schale.network/books/detail/${g_id}/${g_key}`;
            fn.showMsg(displayLanguage.str_05, 0);
            return fetch(detailApi).then(res => res.json()).then(detailJson => {
                debug("\ndetailJson\n", detailJson);
                const {
                    created_at,
                    updated_at,
                    data,
                    thumbnails
                } = detailJson;
                const {
                    base,
                    entries
                } = thumbnails;
                const thumbs = entries.map(e => base + e.path);
                thumbnailSrcArray = thumbs;
                const [maxKey] = Object.keys(data).sort((a, b) => b - a);
                const {
                    id,
                    public_key
                } = data[maxKey];
                const dataApi = `https://api.schale.network/books/data/${g_id}/${g_key}/${id}/${public_key}?v=${updated_at ?? created_at}&w=${maxKey}`;
                return fetch(dataApi).then(res => res.json()).then(dataJson => {
                    const {
                        base,
                        entries
                    } = dataJson;
                    debug("\ndataJson\n", dataJson);
                    let xhrNum = 0;
                    const srcs = entries.map(async (e, i, arr) => {
                        await delay(i * 500);
                        return new Promise(resolve => {
                            const xhr = new XMLHttpRequest;
                            xhr.responseType = "blob";
                            xhr.open("GET", base + e.path + `?w=${maxKey}`);
                            xhr.onload = () => {
                                fn.showMsg(`${displayLanguage.str_06}${xhrNum+=1}/${arr.length}`, 0);
                                resolve(URL.createObjectURL(xhr.response));
                            };
                            xhr.send();
                        });
                    });
                    return srcs;
                });
            });
        },
        button: [4],
        insertImg: ["#previews,main>.group", 0],
        customTitle: () => fn.getText(["#title>h2", "#title>h1"]),
        fetch: 1,
        category: "hcomic"
    }, {
        name: "AnimeH",
        url: {
            h: "animeh.to"
        },
        SPA: () => document.URL.includes("/hchapter/") && !!fn.ge("//div[span[text()='Page:']]"),
        observerURL: true,
        imgs: () => {
            if (!_this.SPA()) return [];
            let url = fn.ge("link[data-hid]").href + "?tab=reading";
            let [max] = fn.gt("//div[span[text()='Page:']]").match(/\d+/);
            return fn.fetchDoc(url).then(dom => {
                let [, imgDir, ex] = fn.ge("#pictureViewer img", dom).dataset.src.match(/^(.+\/)\d+(\.\w+)$/i);
                return fn.arr(max, (v, i) => imgDir + (i + 1) + ex);
            });
        },
        capture: () => _this.imgs(),
        customTitle: () => {
            if (!_this.SPA()) return null;
            return fn.waitEle("main h1").then(e => fn.dt({
                t: e.innerText,
                d: "Hentai Manga"
            }));
        },
        category: "hcomic"
    }, {
        name: "Cathentai/Hentaibeeg/Hentaicolor/Nyahentai/圖片清單頁",
        url: {
            h: [
                "cathentai.net",
                "hentaibeeg.com",
                "hentaicolor.net",
                "nyahentai.info"
            ],
            p: /^\/[^/]+\/(#collapse)?$/
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu("//a[span[text()='List Read']]");
            return fn.fetchDoc(url).then(dom => fn.run(fn.gt("#listImgH", 1, dom)));
        },
        button: [4],
        insertImg: [
            ["#thumbnail-container", 2], 2
        ],
        go: 1,
        customTitle: () => fn.getText(["#info>h4", "#info>h1"]),
        category: "hcomic"
    }, {
        name: "Cathentai/Hentaibeeg/Hentaicolor/Nyahentai/List Read頁",
        url: {
            h: [
                "cathentai.net",
                "hentaibeeg.com",
                "hentaicolor.net",
                "nyahentai.info"
            ],
            p: /^\/read\/\d+\.html$/
        },
        imgs: () => fn.run(fn.gt("#listImgH")),
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => fn.title(/ - Cathentai| - Hentaicolor| - Hentaibeeg| - Nyahentai.info/, 1),
        category: "hcomic"
    }, {
        name: "3hentai圖片清單頁",
        host: ["3hentai.net"],
        reg: /^https?:\/\/3hentai\.net\/d\/\d+$/,
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr(".single-thumb>a>img");
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu(".single-thumb>a");
            let json = await fn.fetchDoc(url).then(dom => {
                let code = fn.gst("readerPages", dom);
                let [jsonCode] = code.match(/JSON[^;]+/);
                return fn.run(jsonCode);
            });
            let max = json.lastPage;
            let imgDir = json.baseUriImg.replace("%s", "");
            return fn.arr(max, (v, i) => imgDir + json.pages[(i + 1)].f);
        },
        button: [4],
        insertImg: [
            ["#thumbnail-gallery", 0], 2
        ],
        customTitle: () => fn.gt("#main-info>h1,#main-info>h2").replace("|", "-"),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "3hentai閱讀頁",
        host: ["3hentai.net"],
        reg: /^https?:\/\/3hentai\.net\/d\/\d+\/\d+$/,
        imgs: () => {
            const {
                readerPages
            } = _unsafeWindow;
            let max = readerPages.lastPage;
            let imgDir = readerPages.baseUriImg.replace("%s", "");
            return fn.arr(max, (v, i) => imgDir + readerPages.pages[(i + 1)].f);
        },
        button: [4],
        insertImg: [".reader-image", 2],
        customTitle: () => fn.gt(".reader-title").replace("|", "-"),
        category: "hcomic"
    }, {
        name: "山寨3hentai圖片清單頁",
        host: ["www.hentai321.top"],
        reg: /^https?:\/\/www\.hentai321\.top\/\?d\/\d+$/,
        init: () => {
            fn.createImgBox("#thumbnail-gallery", 2);
            fn.remove("#header-ban-agsy,#middle-ban-agsy");
        },
        imgs: () => fn.getImgA(".js-main-img", ".single-thumb>a"),
        thums: ".single-thumb img",
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: ".middle-title",
        go: 1,
        css: "#FullPictureLoadMainImgBox{max-width:1140px;margin-left:auto;margin-right:auto}",
        hide: "ins,#doujin-page-footer-ban-agsy,#main-content+div~*:not([id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],#comicRead,#fab,*[class^=fancybox])",
        category: "hcomic"
    }, {
        name: "HentaiFox圖片清單頁",
        host: ["hentaifox.com"],
        reg: /^https?:\/\/hentaifox\.com\/gallery\/\d+\/$/,
        include: "//a[text()=' Read Online']",
        init: async () => {
            await fn.wait((_, win) => !!ge(".gallery_thumb img") && ("g_th" in win));
            fn.createImgBox(".gallery_bottom");
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/includes/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            let [max] = fn.gt(".pages").match(/\d+/);
            let img = fn.ge(".gallery_thumb img");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: () => fn.gt(".info>h1").replace("|", "-"),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "HentaiFox閱讀頁",
        host: ["hentaifox.com"],
        reg: /^https?:\/\/hentaifox\.com\/g\/\d+\/\d+\/$/,
        init: () => fn.wait((_, win) => !!ge("#gimg") && ("g_th" in win)),
        imgs: () => {
            let max = fn.ge("#pages").value;
            let img = fn.ge("#gimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".full_image", 2],
        customTitle: () => fn.title(/ - Page \d+ - HentaiFox/).replace("|", "-"),
        category: "hcomic"
    }, {
        name: "HentaiZap圖片清單頁",
        host: ["hentaizap.com"],
        reg: /^https?:\/\/hentaizap\.com\/gallery\/\d+\/$/,
        init: () => fn.wait((_, win) => !!ge(".gp_th img") && ("g_th" in win)),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let _token = fn.attr('meta[name="csrf-token"]', "content");
            let server = fn.ge("#load_server").value;
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `_token=${_token}&server=${server}&u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            fn.createImgBox("#comments_div");
            let [max] = fn.gt(".info_pg").match(/\d+/);
            let img = fn.ge(".gp_th img");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 2
        ],
        customTitle: () => fn.gt(".gp_top_right>h1").replace("|", "-"),
        go: 1,
        category: "hcomic"
    }, {
        name: "HentaiZap閱讀頁",
        host: ["hentaizap.com"],
        reg: /^https?:\/\/hentaizap\.com\/g\/\d+\/\d+\/$/,
        init: () => fn.waitVar("g_th"),
        imgs: async () => {
            let max = fn.ge("#pages").value;
            let img = fn.ge("#fimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".mid_rd", 2],
        customTitle: () => fn.title(/ - Page \d+ - HentaiZap/).replace("|", "-"),
        category: "hcomic"
    }, {
        name: "HentaiRead閱讀頁",
        host: ["hentairead.com"],
        reg: /^https?:\/\/hentairead\.com\/hentai\/[^\/]+\/english\/p\/\d+\/$/,
        init: async () => {
            await fn.waitVar("chapter_preloaded_images");
            fn.remove(".page-link-hover,.bottom-nav,.ad");
        },
        imgs: () => _unsafeWindow.chapter_preloaded_images.map(e => e.src.replace(/\?quality=.+$/, "")),
        insertImg: ["#imagesList", 2],
        customTitle: () => fn.title(/ Page \d.+$/).trim(),
        category: "hcomic"
    }, {
        name: "HentaiRox圖片清單頁",
        host: ["HentaiRox.com"],
        reg: /^https?:\/\/hentairox\.com\/gallery\/\d+\/$/,
        include: "#append_thumbs",
        init: () => fn.createImgBox("#comments_div", 0),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_04, 0);
            await fn.waitEle("#append_thumbs img");
            fn.hideMsg();
            fn.showMsg(displayLanguage.str_05, 0);
            let server = fn.ge("#load_server").value;
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `server=${server}&u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            let [max] = fn.gt(".pages").match(/\d+/);
            let img = fn.ge(".gthumb img");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: () => fn.ge(".subtitle") ? fn.gt(".subtitle") : fn.gt("h1"),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "HentaiRox閱讀頁",
        host: ["HentaiRox.com"],
        reg: /^https?:\/\/hentairox\.com\/view\/\d+\/\d+\/$/,
        imgs: async () => {
            let max = fn.ge("#pages").value;
            let img = fn.ge("#gimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".pre_img", 2],
        customTitle: () => fn.title(/ - Page \d+ - HentaiRox/).replace("|", "-"),
        css: ".pre_img{max-height:unset!important}",
        category: "hcomic"
    }, {
        name: "HentaiEnvy圖片清單頁",
        host: ["hentaienvy.com"],
        reg: /^https?:\/\/hentaienvy\.com\/gallery\/\d+\/$/,
        include: ".gallery_thumbs",
        init: () => fn.createImgBox(".gallery_thumbs", 0),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_04, 0);
            await fn.waitEle("#thumbs_box img");
            fn.hideMsg();
            fn.showMsg(displayLanguage.str_05, 0);
            let _token = fn.attr('meta[name="csrf-token"]', "content");
            let server = fn.ge("#load_server").value;
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `_token=${_token}&server=${server}&u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            let [max] = fn.gt("//ul[span[text()='Pages:']]").match(/\d+/);
            let img = fn.ge(".th_gp img");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            await fn.waitVar("g_th");
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: () => fn.ge(".subtitle") ? fn.gt(".subtitle") : fn.gt("h1"),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "HentaiEnvy閱讀頁",
        host: ["hentaienvy.com"],
        reg: /^https?:\/\/hentaienvy\.com\/g\/\d+\/\d+\/$/,
        imgs: async () => {
            await fn.waitVar("g_th");
            let max = fn.ge("#pages").value;
            let img = fn.ge("#fimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".rd_fimg", 2],
        customTitle: () => fn.title(/ - Page \d+ - HentaiEnvy/).replace("|", "-"),
        css: ".rd_fimg{width:auto!important;max-height:unset!important}",
        category: "hcomic"
    }, {
        name: "lhentai.com/simplyhentai.red圖片清單頁",
        host: ["lhentai.com", "simplyhentai.red"],
        reg: /^https?:\/\/(lhentai\.com|simplyhentai\.red)\/g\/\d+$/,
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr(".gallerythumb img");
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu("a.gallerythumb");
            let iframe = await fn.iframeVar(url, "images_ext");
            let [imgDir] = fn.ge(".fit-horizontal", iframe.document).src.match(/.+\//);
            return iframe.images_ext.map((e, i) => `${imgDir}${(i + 1)}.${fn.ex(e)}`);
        },
        button: [4],
        insertImg: [
            [".thumbs", 2], 2
        ],
        go: 1,
        customTitle: () => fn.getText(["#info>h2", "#info>h1"]),
        category: "hcomic"
    }, {
        name: "lhentai.com/simplyhentai.red閱讀頁",
        host: ["lhentai.com", "simplyhentai.red"],
        reg: /^https?:\/\/(lhentai\.com|simplyhentai\.red)\/g\/\d+\/\d+\/$/,
        imgs: () => {
            let [imgDir] = fn.ge(".fit-horizontal").src.match(/.+\//);
            return _unsafeWindow.images_ext.map((e, i) => `${imgDir}${(i + 1)}.${fn.ex(e)}`);
        },
        button: [4],
        insertImg: ["#page-container", 2],
        category: "hcomic"
    }, {
        name: "EAHentai",
        host: ["eahentai.com"],
        reg: /^https?:\/\/eahentai\.com\/a\/\d+$/,
        init: async () => {
            let id = fn.lp.match(/\d+/)[0];
            let fetchJson = await fetch(`/api/image/album/${id}`).then(res => res.json()).then(arr => arr[0]);
            siteJson = fetchJson;
            await fn.waitEle(".gallery-img");
            fn.createImgBox(".gallery-container", 2);
        },
        imgs: () => {
            thumbnailSrcArray = siteJson.images.map(e => "https://i.eahentai.com/file/ea-gallery/" + e.thumbnailUri);
            return siteJson.images.map(e => "https://i.eahentai.com/file/ea-gallery/" + e.imageUri);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: () => siteJson.title,
        category: "hcomic"
    }, {
        name: "Fhentai圖片清單頁",
        url: {
            h: "fhentai.net",
            p: "/f/"
        },
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr(".rounded-md:has(>.grid) img");
            return thumbnailSrcArray.map(e => e.replace("/thumb/", "/raw/"));
        },
        button: [4],
        insertImg: [".rounded-md:has(>.grid)", 2],
        go: 1,
        customTitle: "main h1",
        category: "hcomic"
    }, {
        name: "Fhentai閱讀頁",
        url: {
            h: "fhentai.net",
            p: "/read/"
        },
        imgs: "main .rounded-md img",
        button: [4],
        insertImg: ["main .rounded-md", 2],
        customTitle: "main h1",
        category: "hcomic"
    }, {
        name: "M-Hentai圖片清單頁",
        host: ["m-hentai.net"],
        reg: /^https?:\/\/m-hentai\.net\/gallery\?id=\d+$/,
        init: () => fn.createImgBox(".bookthumbnailcontainer", 2),
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr(".bookthumbnail .lazyloadimage");
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu(".bookthumbnail>a");
            return fn.iframeVar(url, "displayimagelist").then(w => w.displayimagelist.map(e => e.image_url));
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: () => fn.getText([".gallerysubtitle", ".gallerytitle"]),
        category: "hcomic"
    }, {
        name: "M-Hentai閱讀頁",
        host: ["m-hentai.net"],
        reg: /^https?:\/\/m-hentai\.net\/read\?index=\d+/,
        imgs: () => _unsafeWindow.displayimagelist.map(e => e.image_url),
        button: [4],
        insertImg: [".imagereadercontainer", 2],
        insertImgAF: () => fn.run("$(document).off()"),
        customTitle: () => fn.title(/ - Page .+/),
        category: "hcomic"
    }, {
        name: "HentaiNexus圖片清單頁",
        host: ["hentainexus.com"],
        reg: /^https?:\/\/hentainexus\.com\/view\/\d+$/,
        init: () => fn.createImgBox(".box:has(>.is-multiline)", 2),
        imgs: async () => {
            thumbnailSrcArray = fn.getImgSrcArr(".card-image img");
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu("//a[div[@class='card']]");
            return fn.iframe(url, {
                waitVar: "pageData",
                cb: async (_, frame) => {
                    await fn.wait(() => isArray(frame.pageData));
                }
            }).then(async (object) => {
                const {
                    frame
                } = object;
                let CDN_Srcs = frame.pageData.map(e => e.image);
                let siteSrcs = CDN_Srcs.map(e => e.replace(/i\d\.wp\.com\/|\?filter=null/g, ""));
                fn.showMsg(displayLanguage.str_56, 0);
                let status = await fn.xhrHEAD(siteSrcs[0]).then(res => res.status);
                fn.hideMsg();
                return status === 200 ? siteSrcs : CDN_Srcs;
            });
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: ".title",
        category: "hcomic"
    }, {
        name: "HentaiNexus閱讀頁",
        host: ["hentainexus.com"],
        reg: /^https?:\/\/hentainexus\.com\/read\/\d+/,
        imgs: async () => {
            let CDN_Srcs = _unsafeWindow.pageData.map(e => e.image);
            let siteSrcs = CDN_Srcs.map(e => e.replace(/i\d\.wp\.com\/|\?filter=null/g, ""));
            fn.showMsg(displayLanguage.str_56, 0);
            let status = await fn.xhrHEAD(siteSrcs[0]).then(res => res.status);
            return status === 200 ? siteSrcs : CDN_Srcs;
        },
        button: [4],
        insertImg: ["#pageChangeSnap", 2],
        customTitle: () => _unsafeWindow.baseTitle.replace(" :: HentaiNexus", ""),
        category: "hcomic"
    }, {
        name: "HentaiLoop圖片清單頁",
        host: ["hentailoop.com"],
        reg: /^https?:\/\/hentailoop\.com\/manga\/[^\/]+\/$/,
        init: () => fn.createImgBox(".preview", 2),
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            thumbnailSrcArray = await fetch("/wp-admin/admin-ajax.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `action=loadpreviews&postID=${_unsafeWindow.ajaxData.postID}`,
                "method": "POST"
            }).then(res => res.text()).then(text => fn.doc(text)).then(dom => [...dom.images].map(e => e.src));
            let url = fn.gu(".previews>a");
            return fn.iframeVar(url, "ajax").then(w => {
                let html = w.ajax.pages.join("");
                let dom = fn.doc(html);
                return [...dom.images].map(e => e.dataset.src ?? e.src);
            });
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: "//meta[@content='4']/preceding-sibling::span[1]",
        category: "hcomic"
    }, {
        name: "HentaiLoop閱讀頁",
        host: ["hentailoop.com"],
        reg: /^https?:\/\/hentailoop\.com\/manga\/[^\/]+\/read/,
        init: () => fn.createImgBox(".manga-read-wrapp", 2),
        imgs: () => {
            let html = _unsafeWindow.ajax.pages.join("");
            let dom = fn.doc(html);
            return [...dom.images].map(e => e.dataset.src ?? e.src);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".manga-read-buttons,.manga-read-wrapp"], 2
        ],
        customTitle: () => fn.title(/Page \d+ of | - Hentai.+|\(by[\w\s]+\)/ig).trim(),
        category: "hcomic"
    }, {
        name: "nhentai.xxx閱讀頁",
        host: ["nhentai.xxx"],
        reg: /^https?:\/\/nhentai\.xxx\/g\/\d+\/\d+\/$/,
        imgs: () => {
            let img = fn.ge("#fimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            let max = fn.ge("#pages").value;
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th.fl[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".reader_overlay", 2],
        category: "hcomic"
    }, {
        name: "nhentai.to/nhentai.website閱讀頁",
        host: ["nhentai.to", "nhentai.website"],
        reg: /^https?:\/\/nhentai\.(to|website)\/g\/\d+\/\d+$/,
        init: () => fn.waitVar("reader"),
        imgs: () => {
            const {
                reader
            } = _unsafeWindow;
            let imgDir = reader.media_url + "/galleries/" + reader.gallery.media_id + "/";
            return reader.gallery.images.pages.map((e, i) => `${imgDir}${(i + 1)}.${fn.ex(e.t)}`);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => {
            const {
                reader
            } = _unsafeWindow;
            return reader.gallery.title.japanese ?? reader.gallery.title.english;
        },
        category: "hcomic"
    }, {
        name: "MangaHen圖片清單頁",
        host: ["manga-hen.com"],
        reg: /^https?:\/\/manga-hen\.com\/manga\/[\w-]+\/$/,
        init: () => fn.createImgBox(".rounded-lg", 2),
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".img-thumb img,.lazy-img-thumb img");
            return fn.xhrDoc(fn.gu(".img-thumb>a"), {
                cookie: "reader_mode=1"
            }).then(dom => fn.gae(".justify-between~img[data-src]", dom));
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: () => fn.getText(["h2[class^=text]", "h1[class^=text]"]),
        category: "hcomic"
    }, {
        name: "TMOHentai圖片清單頁",
        host: ["tmohentai.com"],
        reg: /^https?:\/\/tmohentai\.com\/contents\/\w+$/i,
        imgs: async () => {
            await fn.waitEle("div[style*='background']");
            let div = fn.ge("div[style*='background']");
            let [, src] = div.style.background.split('"');
            let [imgDir] = src.match(/.+\//);
            let max = fn.gae("div[style*='background']").length;
            return fn.arr(max, (v, i) => imgDir + String(i).padStart(3, "0") + ".webp");
        },
        button: [4],
        insertImg: [
            ["//div[div[@class='well']]", 2], 2
        ],
        go: 1,
        customTitle: ".panel-title h3",
        category: "hcomic"
    }, {
        name: "TMOHentai閱讀頁",
        host: ["tmohentai.com"],
        reg: /^https?:\/\/tmohentai\.com\/reader\/\w+\/paginated\//i,
        imgs: async () => {
            await fn.waitEle("img.content-image");
            let img = fn.ge("img.content-image");
            let src = img.dataset.original ?? img.src;
            let [imgDir] = src.match(/.+\//);
            let max = fn.gae("#select-page option").length;
            return fn.arr(max, (v, i) => imgDir + String(i).padStart(3, "0") + ".webp");
        },
        button: [4],
        insertImg: [".reader-info+.text-center", 2],
        customTitle: ".reader-title",
        category: "hcomic"
    }, {
        name: "Download Doujin",
        host: ["cin.cx", "cin.mom"],
        url: {
            h: "cin",
            p: /^\/v\/\d+$/,
            e: "#doujin-page"
        },
        checkStatus: async (src) => {
            let host = new URL(src).host;
            let hosts = ["a", "b", "c", "d", "e", "f", "g"].map(e => host.replace(/^[a-g]/i, e));
            let cs = hosts.map(h => src.replace(host, h));
            for (let url of cs) {
                let status = await fetch(url, {
                    method: "HEAD"
                }).then(res => res.status);
                if (status == 200) {
                    return url;
                }
            }
            return src;
        },
        init: async () => {
            await fn.waitEle("#doujin-page img");
            fn.createImgBox("#doujin-page", 2);
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let srcs = _unsafeWindow.__NEXT_DATA__.props.pageProps.data.images.pages.map(e => e.t);
            let fetchNum = 0;
            return srcs.map(async (src, i, arr) => {
                await delay(i * 500);
                src = await _this.checkStatus(src);
                return fetch(src).then(res => res.blob()).then(blob => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${arr.length}`, 0);
                    return URL.createObjectURL(blob);
                });
            });
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#doujin-page"], 3
        ],
        customTitle: () => fn.dt({
            s: "[class^='styles_info']>div",
            d: [
                "🇨🇳 ",
                "🇯🇵 ",
                "🇬🇧 "
            ]
        }),
        gallery: 1,
        fetch: 1,
        category: "hcomic"
    }, {
        name: "Pururin圖片清單頁",
        host: ["pururin.to"],
        reg: /^https?:\/\/pururin\.to\/gallery\/\d+\/.+/,
        imgs: () => {
            let url = fn.gu(".gallery-preview>a");
            return fn.fetchDoc(url).then(dom => {
                let ele = fn.ge(".img-viewer", dom);
                let svr = ele.dataset.svr;
                let data = JSON.parse(ele.dataset.img);
                let arr = data.images.sort((a, b) => a.page - b.page);
                arr = arr.map(e => svr + "/" + data.directory + "/" + e.filename);
                thumbnailSrcArray = arr.map(e => e.replace(/(\.\w+)$/, "t$1"));
                return arr;
            });
        },
        button: [4],
        insertImg: [
            [".gallery-preview", 2], 2
        ],
        endColor: "white",
        go: 1,
        insertImgAF: () => {
            if (options.icon == 1 || siteData.icon == 1) addFullPictureLoadButton();
            if (!hasTouchEvent && ShowFullPictureLoadFixedMenu === 1) addFullPictureLoadFixedMenu();
        },
        customTitle: () => fn.ge("[placeholder=Japanese]")?.value || fn.ge("[placeholder='Alternative names']")?.value,
        category: "none"
    }, {
        name: "Pururin閱讀頁",
        host: ["pururin.to"],
        reg: /^https?:\/\/pururin\.to\/read\/\d+\/\d+\/.+/,
        imgs: () => {
            let ele = fn.ge(".img-viewer");
            let svr = ele.dataset.svr;
            let data = JSON.parse(ele.dataset.img);
            //按頁數排列
            let arr = data.images.sort((a, b) => a.page - b.page);
            arr = arr.map(e => svr + "/" + data.directory + "/" + e.filename);
            thumbnailSrcArray = arr.map(e => e.replace(/(\.\w+)$/, "t$1"));
            return arr;
        },
        button: [4],
        insertImg: [".img-viewer", 2],
        endColor: "white",
        customTitle: () => fn.ge("[placeholder=Japanese]")?.value || fn.ge("[placeholder='Alternative names']")?.value,
        css: ".box.img-reader .img-viewer{position:unset!important;white-space:unset!important}",
        category: "hcomic"
    }, {
        name: "9hentai圖片清單頁",
        host: ["9hentai.com"],
        reg: /^https?:\/\/9hentai\.\w+\/g\/\d+\/$/,
        init: async () => {
            let json = await fetch("/api/getBookByID", {
                method: "POST",
                body: JSON.stringify({
                    id: Number(/\d+/.exec(fn.lp).at(0) ?? 0)
                }),
                headers: {
                    "Content-Type": "application/json"
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: () => {
            let arr = fn.arr(siteJson.results.total_page, (v, i) => `${siteJson.results.image_server + siteJson.results.id}/${i + 1}.jpg`);
            thumbnailSrcArray = arr.map(e => e.replace(/(\d+)(\.\w+)$/, "preview/$1t$2"));
            return arr;
        },
        button: [4],
        insertImg: [
            [".pt-0 .card-body", 2], 2
        ],
        endColor: "white",
        go: 1,
        customTitle: () => siteJson.results.alt_title ?? siteJson.results.title,
        category: "hcomic"
    }, {
        name: "9hentai閱讀頁",
        host: ["9hentai.com"],
        reg: /^https?:\/\/9hentai\.\w+\/g\/\d+\/\d+\/$/,
        init: async () => {
            let json = await fetch("/api/getBookByID", {
                method: "POST",
                body: JSON.stringify({
                    id: Number(/\d+/.exec(fn.lp).at(0) ?? 0)
                }),
                headers: {
                    "Content-Type": "application/json"
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: () => {
            let arr = fn.arr(siteJson.results.total_page, (v, i) => `${siteJson.results.image_server + siteJson.results.id}/${i + 1}.jpg`);
            thumbnailSrcArray = arr.map(e => e.replace(/(\d+)(\.\w+)$/, "preview/$1t$2"));
            return arr;
        },
        button: [4],
        insertImg: [".image-viewer", 2],
        endColor: "white",
        customTitle: () => siteJson.results.alt_title ?? siteJson.results.title,
        category: "hcomic"
    }, {
        name: "Manga Mischief圖片清單頁",
        host: ["xmanga.org"],
        reg: /^https?:\/\/xmanga\.org\/album\/[\w-]+\/$/,
        init: async () => {
            let [, , albumId] = fn.lp.split("/");
            let api = `https://mangamischief.com/backend/image?albumId=${albumId}`;
            let json = await fetch(api).then(res => res.json());
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
            await fn.waitEle("div:has(>.max-w-gallery) img");
        },
        imgs: () => siteJson.data.map(e => e.url),
        button: [4],
        insertImg: ["div:has(>.max-w-gallery)", 2],
        endColor: "white",
        customTitle: "h1.text-lg",
        category: "hcomic"
    }, {
        name: "AsmHentai圖片清單頁",
        host: ["asmhentai.com"],
        reg: /^https?:\/\/asmhentai\.com\/g\/\d+\/$/,
        init: () => fn.createImgBox(".gallery"),
        imgs: async () => {
            if (fn.ge("#load_id")) {
                fn.showMsg(displayLanguage.str_05, 0);
                let _token = fn.attr('meta[name="csrf-token"]', "content");
                let id = fn.ge("#load_id").value;
                let dir = fn.ge("#load_dir").value;
                let t_pages = fn.ge("#t_pages").value;
                thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                    "headers": {
                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                        "x-requested-with": "XMLHttpRequest"
                    },
                    "body": `_token=${_token}&id=${id}&dir=${dir}&visible_pages=0&t_pages=${t_pages}&type=2`,
                    "method": "POST"
                }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            } else {
                thumbnailSrcArray = fn.getImgSrcArr("#append_thumbs img");
            }
            return thumbnailSrcArray.map(e => e.replace("t.", "."));
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        endColor: "white",
        go: 1,
        customTitle: () => fn.getText([".info>h2", ".info>h1"]),
        category: "hcomic"
    }, {
        name: "AsmHentai閱讀頁",
        host: ["asmhentai.com"],
        reg: /^https?:\/\/asmhentai\.com\/gallery\/\d+\/\d+\/$/,
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let _token = fn.attr('meta[name="csrf-token"]', "content");
            let id = fn.ge("#gallery_id").value;
            let dir = fn.ge("#image_dir").value;
            let t_pages = fn.ge("#pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `_token=${_token}&id=${id}&dir=${dir}&visible_pages=0&t_pages=${t_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            return thumbnailSrcArray.map(e => e.replace("t.", "."));
        },
        button: [4],
        insertImg: [".rd_fimg", 2],
        endColor: "white",
        customTitle: () => fn.title(" Page", 1),
        css: ".preloader{text-indent:unset !important}",
        category: "hcomic"
    }, {
        name: "MultPorn閱讀頁",
        url: {
            h: "multporn.net",
            e: "//script[contains(text(),'configUrl')]"
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gst("configUrl").match(/configUrl":"[^,]+/g)[0].slice(12, -1).replaceAll("\\", "");
            return fetch(url).then(res => res.text()).then(text => {
                let xml = fn.xml(text);
                let imgs = fn.gae("image", xml);
                thumbnailSrcArray = imgs.map(e => e.getAttribute("thumbURL"));
                return imgs.map(e => e.getAttribute("linkURL"));
            });
        },
        button: [4],
        insertImg: [
            [".juicebox-parent", 2], 2
        ],
        endColor: "white",
        go: 1,
        autoDownload: [0],
        next: "//a[text()='Next Part']",
        prev: "//a[text()='Previous Part']",
        customTitle: "#page-title",
        category: "hcomic"
    }, {
        name: "KingComiX閱讀頁",
        host: ["kingcomix.com"],
        reg: /^https?:\/\/kingcomix\.com\/[^\/]+\/$/,
        imgs: "figure img, .entry-content img.lazy",
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: () => fn.gt("h1.singleTitle-h1").replace(" – Kingcomix", ""),
        category: "hcomic"
    }, {
        name: "MyReadingManga",
        url: {
            h: "myreadingmanga.info",
            e: ".entry-content img"
        },
        imgs: () => fn.getImgA(".entry-content img", ".entry-pagination a"),
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".entry-title",
        category: "hcomic"
    }, {
        name: "HENTAISET.COM閱讀頁 / HENTAIVID.NET閱讀頁",
        host: ["www.hentaiset.com", "hentaivid.net"],
        reg: [
            /^https?:\/\/www\.hentaiset\.com\/\w+\/\w+\//i,
            /^https?:\/\/hentaivid\.net\/photo\/\w+\/[^\/]+\/$/i
        ],
        init: () => fn.createImgBox("#lightgallery", 2),
        imgs: "#lightgallery li.thumb,#lightgallery div.thumb",
        thums: "#lightgallery img[is='lazyload-image']",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#lightgallery"], 2
        ],
        customTitle: ".main-container h1",
        category: "hcomic"
    }, {
        name: "Neko Hentai閱讀頁",
        host: ["neko-hentai.net"],
        reg: /^https?:\/\/neko-hentai\.net\//i,
        include: "#manga-content img",
        imgs: "#manga-content img",
        button: [4],
        insertImg: ["#manga-content", 2],
        endColor: "white",
        customTitle: () => fn.title(/ - Neko Hentai.*$/),
        category: "hcomic"
    }, {
        name: "Super Hentai閱讀頁",
        host: ["superhentai.blog"],
        reg: /^https?:\/\/superhentai\.blog\/[^\/]+\/$/i,
        include: ".gallery",
        imgs: ".gallery img",
        button: [4],
        insertImg: [".gallery", 2],
        endColor: "white",
        customTitle: "#single h1",
        category: "hcomic"
    }, {
        name: "HENTAICELEB.COM閱讀頁",
        host: ["www.hentaiceleb.com"],
        reg: /^https?:\/\/www\.hentaiceleb\.com\/\w+\/\w+\/[^\.]+\.html$/i,
        imgs: ".gallery-thumbs a[data-src]",
        button: [4],
        insertImg: [".media-bg", 2],
        endColor: "white",
        customTitle: ".full-main-col h1",
        category: "hcomic"
    }, {
        name: "HENTAIVSMANGA.COM圖片清單頁",
        host: ["hentaivsmanga.com"],
        reg: /^https?:\/\/hentaivsmanga\.com\/content\/\w+\/[^\/]+\/$/i,
        imgs: () => fn.getImgA("#image-container img", "#thumbnail-container a"),
        thums: "#thumbnail-container img[is='lazyload-image']",
        button: [4],
        insertImg: [
            ["#thumbnail-container", 2], 2
        ],
        go: 1,
        customTitle: () => fn.getText(["#info>h2", "#info>h1"]),
        category: "hcomic"
    }, {
        name: "HENTAIVSMANGA.COM閱讀頁",
        host: ["hentaivsmanga.com"],
        reg: /^https?:\/\/hentaivsmanga\.com\/content\/\w+\/[^\/]+\/\d+\/$/i,
        imgs: () => {
            let max = fn.gt(".num-pages");
            let url = fn.url.replace(/\d+\/$/, "");
            let links = fn.arr(max, (v, i) => url + (i + 1) + "/");
            return fn.getImgA("#image-container img", links);
        },
        button: [4],
        insertImg: ["#image-container", 2],
        customTitle: () => fn.title(" XXX Manga and Hentai"),
        category: "hcomic"
    }, {
        name: "HENTAICREDO.COM圖片清單頁",
        host: ["www.hentaicredo.com"],
        reg: /^https?:\/\/www\.hentaicredo\.com\/content\/\w+\/[^\/]+\/$/i,
        imgs: () => {
            let [thumbs] = fn.gae(".thumbs");
            let imgs = fn.gae("img", thumbs);
            let links = fn.gau("a", thumbs);
            thumbnailSrcArray = fn.getImgSrcArr(imgs);
            return fn.getImgA(".big-picture>img", links);
        },
        button: [4],
        insertImg: [".thumbs", 2],
        customTitle: "h2",
        category: "hcomic"
    }, {
        name: "HentaiHere閱讀頁",
        host: ["hentaihere.com"],
        reg: /^https?:\/\/hentaihere\.com\/m\/\w+\/\d+\/\d+\/$/i,
        init: async () => {
            await fn.waitVar(["rff_imageList", "jQuery"]);
            setTimeout(() => fn.run("jQuery(document).off();"), 1000);
        },
        imgs: () => _unsafeWindow.rff_imageList.map(e => "https://hentaicdn.com/hentai" + e),
        button: [4],
        insertImg: ["#reader-content", 2],
        autoDownload: [0],
        next: "//li[a[@class='bg-info']]/following-sibling::li[1]/a",
        prev: 1,
        customTitle: () => fn.gt("#detail span") + " - " + fn.gt("#chapter span"),
        hide: ".afs_ads,[data-type]",
        category: "hcomic"
    }, {
        name: "HentaiPaw圖片清單頁/Hentai-One圖片清單頁",
        url: {
            h: ["hentaipaw.com", "ch.hentai-one.com"],
            p: "/articles/"
        },
        init: () => fn.waitEle(["next-route-announcer", ".grid .group>img"]),
        imgs: async () => {
            fn.createImgBox(".container:has(>.grid)");
            fn.showMsg("獲取數據中...", 0);
            let url = fn.gu(".container:has(>.grid) a");
            return fn.fetchDoc(url).then(dom => {
                let code = fn.gst("slides", dom);
                let arr = JSON.parse(code.match(/\\"slides\\":([^\]]+\])/)[1].replaceAll("\\", ""));
                return arr.map(e => e.src);
            });
        },
        thums: ".grid .group>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "//div[@id='FullPictureLoadMainImgBox']/preceding-sibling::div[1]"], 2, 2000
        ],
        insertImgAF: () => {
            let loop = setInterval(() => {
                if (!fn.ge(".FullPictureLoadImage")) {
                    fn.immediateInsertImg();
                }
            }, 500);
            setTimeout(() => clearInterval(loop), 10000);
        },
        customTitle: () => {
            if (fn.lh === "ch.hentai-one.com") {
                let text = fn.gt("h1.text-wrap");
                return text.includes("|") ? text.split("|")[1].trim() : text;
            } else {
                return fn.gt("h1.text-wrap").replace(/\/|\|/g, " ");
            }
        },
        css: "#article-details{margin-top:5rem!important}",
        hide: "#article-details+.mx-auto,.container:has(>div>script),#button-group a",
        category: "hcomic"
    }, {
        name: "色图喵h漫画圖片清單頁",
        reg: /^https?:\/\/www\.setumeow\.com\/c\//,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".thumbsdiv img");
            return thumbnailSrcArray.map(src => src.replace("/t/", "/i/").replace("t.", "."));
        },
        button: [4],
        insertImg: [".thumbsdiv", 2],
        customTitle: "#info h1",
        category: "hcomic"
    }, {
        name: "HDpornComics圖片清單頁",
        host: ["hdporncomics.com"],
        reg: /^https?:\/\/hdporncomics\.com\/[^/]+\/([^/]+\/)?$/i,
        include: ".my-gallery.scrollmenu",
        imgs: ".my-gallery a[data-size]",
        thums: ".my-gallery a[data-size] img",
        button: [4],
        insertImg: [
            [".postContent>.items-center,#likeDislikeVue", 2], 2
        ],
        go: 1,
        customTitle: () => fn.dt({
            s: "#infoBox>h1",
            d: [
                " – Gay Manga",
                " Comic Porn"
            ]
        }),
        category: "hcomic"
    }, {
        name: "HDpornComics閱讀頁",
        host: ["hdporncomics.com"],
        reg: /^https?:\/\/hdporncomics\.com\/manhwa\/[^/]+\/chapter/i,
        imgs: "#imageContainer>img",
        button: [4],
        insertImg: ["#imageContainer", 2],
        autoDownload: [0],
        next: "//a[contains(text(),'Next')]",
        prev: "//a[contains(text(),'Prev')]",
        customTitle: () => fn.gt(".list-reset li:nth-child(5)>a") + " - " + fn.gt("option[selected]"),
        category: "hcomic"
    }, {
        name: "Doujins圖片清單頁",
        host: ["doujins.com"],
        reg: /^https?:\/\/doujins\.com\/.+\/.+/i,
        include: "#thumbnails",
        init: () => fn.waitEle(".doujin"),
        imgs: () => {
            thumbnailSrcArray = fn.gae("div[data-hash]").map(e => "https://static.doujins.com/t-" + e.dataset.hash + ".jpg");
            return fn.gae(".doujin[data-file]").map(e => e.dataset.file);
        },
        button: [4],
        insertImg: [
            ["#thumbnails", 2], 2
        ],
        go: 1,
        customTitle: ".folder-title>a:last-child",
        category: "hcomic"
    }, {
        name: "Simply Hentai閱讀頁",
        host: ["www.simply-hentai.com"],
        reg: /^https?:\/\/www.simply-hentai.com\/[^\/]+\/[^\/]+\/page\/\d+/i,
        init: async () => {
            await fn.waitEle("#__NEXT_DATA__");
            let json = JSON.parse(fn.gt("#__NEXT_DATA__"));
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: () => {
            thumbnailSrcArray = siteJson.props.pageProps.data.pages.map(e => e.sizes.small_thumb);
            return siteJson.props.pageProps.data.pages.map(e => e.sizes.full)
        },
        button: [4],
        insertImg: ["#reader-image", 2],
        insertImgAF: () => {
            let loop = setInterval(() => !fn.ge(".FullPictureLoadImage") ? fn.immediateInsertImg() : null, 500);
            setTimeout(() => clearInterval(loop), 10000);
        },
        customTitle: () => siteJson.props.pageProps.data.title.replace(/\/|\|/g, "-"),
        category: "hcomic"
    }, {
        name: "Hanime1圖片清單頁",
        host: ["hanime1.me"],
        link: "https://hanime1.me/comics",
        reg: /^https?:\/\/hanime1\.me\/comic\/\d+$/,
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu(".comics-thumbnail-wrapper>a");
            return fn.fetchDoc(url).then(dom => {
                let imgDir = fn.ge("#current-page-image", dom).dataset.prefix;
                let code = fn.gst("extensions", dom);
                let extensions = fn.run(code.match(/\[.+\]/)[0].replaceAll("&quot;", '"'));
                return extensions.map((e, i) => {
                    if (imgDir.includes("nhentai")) {
                        return `${imgDir}${(i + 1)}.${fn.ex(e)}`;
                    } else {
                        return imgDir + e + ".jpg";
                    }
                });
            });
        },
        button: [4],
        insertImg: [".comics-thumbnail-wrapper", 2],
        endColor: "white",
        go: 1,
        customTitle: "h4.title",
        referer: "src",
        category: "hcomic"
    }, {
        name: "Hanime1閱讀頁",
        host: ["hanime1.me"],
        link: "https://hanime1.me/comics",
        reg: /^https?:\/\/hanime1\.me\/comic\/\d+\/\d+$/,
        imgs: async () => {
            let imgDir = fn.ge("#current-page-image").dataset.prefix;
            return _unsafeWindow.extensions.map((e, i) => {
                if (imgDir.includes("nhentai")) {
                    return `${imgDir}${(i + 1)}.${fn.ex(e)}`;
                } else {
                    return imgDir + e + ".jpg";
                }
            });
        },
        button: [4],
        insertImg: ["#comic-content-wrapper", 2],
        endColor: "white",
        customTitle: () => fn.dt({
            t: fn.ge("//meta[@property='og:title']").content,
            d: /第\d+頁 - /
        }),
        referer: "src",
        category: "hcomic"
    }, {
        name: "My Hentai Gallery圖片清單頁",
        host: ["myhentaigallery.com"],
        reg: /^https?:\/\/myhentaigallery\.com\/g\/\d+$/,
        imgs: () => {
            thumbnailSrcArray = fn.gae(".comic-thumb>img").map(e => e.src);
            return thumbnailSrcArray.map(e => e.replace("thumbnail", "original"));
        },
        button: [4],
        insertImg: [
            ["//div[@class='comic-listing'][center[center[ul[@class='comics-grid clear']]]]", 0], 2
        ],
        endColor: "white",
        go: 1,
        customTitle: ".comic-description>h1",
        category: "hcomic"
    }, {
        name: "XYZ PORN COMICS圖片清單頁",
        host: ["xyzcomics.com"],
        reg: /^https?:\/\/xyzcomics\.com\/[^\/]+\/$/,
        include: ".jig-link>img",
        imgs: ".jig-link",
        thums: ".jig-link>img",
        button: [4],
        insertImg: [
            [".entry-content", 0], 2
        ],
        endColor: "white",
        go: 1,
        customTitle: ".entry-title",
        category: "hcomic"
    }, {
        name: "IMHentai圖片清單頁",
        host: ["imhentai.xxx"],
        reg: /^https?:\/\/imhentai\.xxx\/gallery\/\d+\//,
        init: async () => {
            await fn.waitVar("g_th");
            fn.createImgBox("#comments_div", 0);
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let server = fn.ge("#load_server").value;
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `server=${server}&u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            return fn.getImhentaiSrc();
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        customTitle: () => fn.waitEle(".subtitle").then(() => {
            let t = fn.gt(".subtitle");
            return t.length > 0 ? t : fn.gt("h1").replace(/\||\+/g, "");
        }),
        go: 1,
        topButton: true,
        category: "hcomic"
    }, {
        name: "IMHentai閱讀頁",
        host: ["imhentai.xxx"],
        reg: /^https?:\/\/imhentai\.xxx\/view\/\d+\/\d+\//,
        init: "setTimeout(()=>{fn.ge('.pre_img').removeAttribute('style');$('a.next_img').unbind('click');},1000)",
        imgs: () => fn.getImhentaiSrc(),
        button: [4],
        insertImg: [".pre_img", 2],
        customTitle: () => fn.title("-", 1),
        category: "hcomic"
    }, {
        name: "HentaiEra圖片清單頁",
        host: ["hentaiera.com"],
        reg: /^https?:\/\/hentaiera\.com\/gallery\/\d+\/$/,
        include: "#append_thumbs",
        init: async () => {
            await fn.waitVar("g_th");
            fn.createImgBox("#thumbs_gallery_div", 2);
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let server = fn.ge("#load_server").value;
            let u_id = fn.ge("#gallery_id").value;
            let g_id = fn.ge("#load_id").value;
            let img_dir = fn.ge("#load_dir").value;
            let total_pages = fn.ge("#load_pages").value;
            thumbnailSrcArray = await fn.fetchDoc("/inc/thumbs_loader.php", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "x-requested-with": "XMLHttpRequest"
                },
                "body": `server=${server}&u_id=${u_id}&g_id=${g_id}&img_dir=${img_dir}&visible_pages=0&total_pages=${total_pages}&type=2`,
                "method": "POST"
            }).then(dom => [...dom.images].map(e => e.dataset.src ?? e.src));
            let max = fn.ge("#load_pages").value;
            let img = fn.ge(".gthumb img");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/^.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: () => fn.getText([".subtitle", "h1"]),
        category: "hcomic"
    }, {
        name: "HentaiEra閱讀頁",
        host: ["hentaiera.com"],
        reg: /^https?:\/\/hentaiera\.com\/view\/\d+\/\d+\/$/,
        init: async () => {
            await fn.waitVar("g_th");
            let html = fn.ge(".pre_img img").outerHTML;
            fn.ge(".pre_img").outerHTML = `<div class="imgBox">${html}</div>`;
        },
        imgs: () => {
            let max = fn.ge("#pages").value;
            let img = fn.ge("#gimg");
            let src = img.dataset.src ?? img.src;
            let [imgDir] = src.match(/.+\//);
            return fn.arr(max, (v, i) => `${imgDir}${(i + 1)}.${fn.ex(_unsafeWindow.g_th[(i + 1)][0])}`);
        },
        button: [4],
        insertImg: [".imgBox", 2],
        customTitle: () => fn.title(/ - Page \d+ - HentaiEra/),
        category: "hcomic"
    }, {
        name: "TSUMINO圖片清單頁",
        host: ["www.tsumino.com"],
        reg: /^https?:\/\/www\.tsumino\.com\/entry\/\d+/,
        include: "#thumbnails-container",
        delay: 300,
        imgs: async () => {
            let prges = fn.ge("div[data-pages]").dataset.pages;
            fn.showMsg(displayLanguage.str_05, 0);
            let imgDir;
            let key = await fn.fetchDoc(fn.gu("#thumbnails-container a")).then(dom => {
                let url = fn.ge("div[data-cdn]", dom).dataset.cdn;
                let newUrl = new URL(url);
                imgDir = newUrl.origin + newUrl.pathname.replace("[PAGE]", "");
                return newUrl.search;
            });
            return fn.arr(prges, (v, i) => imgDir + (i + 1) + key);
        },
        button: [4],
        insertImg: [
            ["#thumbnails-container", 2, "#thumbnails-container"], 2
        ],
        go: 1,
        customTitle: () => {
            let title = fn.gt(".book-data");
            if (/ \/ /.test(title)) {
                return title.split(" / ").at(-1);
            } else if (/ \| /.test(title)) {
                let s = title.split(" | ");
                return s.length == 2 ? s.at(-1) : title;
            }
            return title;
        },
        category: "hcomic"
    }, {
        name: "TSUMINO閱讀頁",
        host: ["www.tsumino.com"],
        reg: /^https?:\/\/www\.tsumino\.com\/Read\/Index\/\d+\?page=\d+$/,
        imgs: async () => {
            await fn.waitEle(".reader-img");
            let [max] = fn.gt("//h1[span[@id='pageNumberText']]").match(/\d+$/);
            let url = fn.ge("div[data-cdn]").dataset.cdn;
            let newUrl = new URL(url);
            let imgDir = newUrl.origin + newUrl.pathname.replace("[PAGE]", "");
            let key = newUrl.search;
            return fn.arr(max, (v, i) => imgDir + (i + 1) + key);
        },
        button: [4],
        insertImg: [".reader-page", 2],
        category: "hcomic"
    }, {
        name: "nHentai圖片清單頁/HentaiHand圖片清單頁",
        host: ["nhentai.com", "hentaihand.com"],
        reg: /^https?:\/\/(nhentai\.com|hentaihand\.com)\/en\/comic\/[^\/]+$/,
        init: async () => {
            let comic = fn.lp.split("/").at(3);
            let csrfToken = fn.ge("meta[name='csrf-token']").content;
            let [, xsrfToken] = document.cookie.match(/XSRF-TOKEN=(\w+)/);
            let json = await fetch(`/api/comics/${comic}/images`, {
                "headers": {
                    "accept": "application/json, text/plain, */*",
                    "x-csrf-token": csrfToken,
                    "x-requested-with": "XMLHttpRequest",
                    "x-xsrf-token": xsrfToken
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: async () => {
            await fn.waitEle(".comic-gallery img");
            thumbnailSrcArray = siteJson.images.map(e => e.thumbnail_url);
            return siteJson.images.map(e => e.source_url);
        },
        button: [4],
        insertImg: [
            ["//div[div[contains(@class,'comic-gallery')]]", 0, ".box-header,.comic-gallery"], 2, 1000
        ],
        go: 1,
        customTitle: () => siteJson.comic.alternative_title ?? siteJson.comic.title,
        category: "hcomic"
    }, {
        name: "nHentai閱讀頁/HentaiHand閱讀頁",
        host: ["nhentai.com", "hentaihand.com"],
        reg: /^https?:\/\/(nhentai\.com|hentaihand\.com)\/\w+\/comic\/[^/]+\/reader\//i,
        init: async () => {
            let comic = fn.lp.split("/").at(3);
            let csrfToken = fn.ge("meta[name='csrf-token']").content;
            let [, xsrfToken] = document.cookie.match(/XSRF-TOKEN=(\w+)/);
            let json = await fetch(`/api/comics/${comic}/images`, {
                "headers": {
                    "accept": "application/json, text/plain, */*",
                    "x-csrf-token": csrfToken,
                    "x-requested-with": "XMLHttpRequest",
                    "x-xsrf-token": xsrfToken
                }
            }).then(res => res.json());
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: async () => {
            await fn.waitEle(".vertical-image img[data-src]");
            thumbnailSrcArray = siteJson.images.map(e => e.thumbnail_url);
            return siteJson.images.map(e => e.source_url);
        },
        button: [4],
        insertImg: [".reader", 2],
        customTitle: () => siteJson.comic.alternative_title ?? siteJson.comic.title,
        category: "hcomic"
    }, {
        name: "同人エロ漫画・エロ同人誌ならエロコミックハンター",
        host: ["ero-comic-hunter.net"],
        reg: /^https?:\/\/ero-comic-hunter\.net\/\d+\.html$/,
        imgs: "#single-more_wid~a[href*='/wp-content/uploads/']",
        customTitle: ".kijibox_title a",
        category: "hcomic"
    }, {
        name: "エロ漫画コング|無料エロマンガ",
        host: ["eromanga-kong.com"],
        reg: /^https?:\/\/eromanga-kong\.com\/[^\/]+\/[^\/]+\/$/,
        include: "#article",
        imgs: "//article[@id='article']//a[img]",
        customTitle: "header>h2",
        category: "hcomic"
    }, {
        name: "Hentai2Read",
        host: ["hentai2read.com"],
        reg: /^https?:\/\/hentai2read\.com\/\w+\/\d+\/(\d+\/)?$/,
        imgs: () => _unsafeWindow.gData.images.map(e => "https://static.hentai.direct/hentai" + e),
        button: [4],
        insertImg: ["#js-reader", 2],
        autoDownload: [0],
        next: "//li[a[contains(@class,'bg-info')]]/preceding-sibling::li[1]/a",
        prev: 1,
        customTitle: () => fn.gt(".reader-left-text.text-ellipsis").replace(/\//g, "-"),
        category: "hcomic"
    }, {
        name: "XlecX",
        host: ["xlecx.one"],
        reg: /^https?:\/\/xlecx\.one\/[\w-]+\.html$/,
        imgs: () => fn.getImgSrcArr(".ug-thumb-image,img[data-src]").map(e => e.replace("thumbs/", "")),
        button: [4],
        insertImg: [
            [".page__col-left", 0], 2
        ],
        go: 1,
        customTitle: ".page__col-left>h1",
        category: "hcomic"
    }, {
        name: "HentaiPal.com",
        host: ["hentaipal.com"],
        reg: /^https?:\/\/hentaipal\.com\/content\/[^\/]+\/[^\/]+\/index\.html$/,
        init: () => fn.remove("iframe[src*='ad'],font[color=red],div:has(>div.row a[href='switch.html'])"),
        imgs: async () => {
            let max;
            try {
                [, max] = fn.gu(".imgpagebar>a:last-child").match(/page-(\d+)/);
            } catch {
                max = 1;
            }
            if (max > 1) {
                let links = [];
                let url = siteUrl.replace("index.html", "");
                for (let i = 2; i <= max; i++) {
                    links.push(url + "page-" + i + ".html");
                }
                await fn.getEle(links, "div:has(>.picbox)", ["div:has(>div>.picbox)", 0]);
            }
            return fn.getImgA("main img[style^=m]", ".picbox>a");
        },
        button: [4],
        insertImg: ["div:has(>div>.picbox)", 2],
        customTitle: () => fn.title(" - HentaiPal.Com"),
        category: "hcomic"
    }, {
        name: "HentaiPal.com 分類自動翻頁",
        enable: 1,
        reg: /^https?:\/\/hentaipal\.com\//,
        init: () => fn.remove("iframe[src*='ad']"),
        autoPager: {
            ele: "div:has(>div>div>.picbox)",
            observer: "div:has(>.picbox)",
            next: ".imgpagebar a:has(.glyphicon-arrow-right)",
            re: ".imgpagebar",
            pageNum: () => nextLink.match(/page-(\d+)/)[1]
        },
        css: ".autoPagerTitle{width:100%!important}",
        category: "autoPager"
    }, {
        name: "HentaiPorns",
        host: ["hentaiporns.net"],
        reg: /^https?:\/\/hentaiporns\.net\/[^\/]+\/$/,
        include: ".gallery",
        init: () => fn.createImgBox(".gallery", 2),
        imgs: ".gallery-item a",
        thums: ".gallery-item a>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".gallery"], 2, 1000
        ],
        customTitle: () => fn.getText(["#gn+h1", "#gn,.entry-title"]),
        fancybox: {
            v: 3,
            css: false
        },
        category: "hcomic"
    }, {
        name: "8muses",
        host: ["comics.8muses.com"],
        reg: /^https?:\/\/comics\.8muses\.com\/comics\/album\/[\w-]+\/[\w-]+\//i,
        include: ".gallery",
        exclude: ".image-title>.title-text",
        imgs: () => {
            let srcs = fn.gae("img[data-src]").map(e => e.dataset.src.replace("/image/th/", "https://comics.8muses.com/image/fl/"));
            let xhrNum = 0;
            fn.showMsg("fn.xhrHEAD...", 0);
            return srcs.map(async src => {
                let res = await fn.xhrHEAD(src);
                fn.showMsg(`fn.xhrHEAD(${xhrNum+=1}/${srcs.length})`, 0);
                let status = res.status;
                return status == 404 ? src.replace("/fl/", "/fm/") : src;
            });
        },
        button: [4],
        insertImg: [
            [".gallery", 2], 1
        ],
        endColor: "white",
        go: 1,
        category: "hcomic"
    }, {
        name: "Manga18.club/hanman18.com/18PornComic/Doujin18.net/CNdoujin.net",
        init: async () => {
            await fn.waitVar("jQuery");
            fn.run("jQuery(document).off();");
        },
        url: {
            h: [
                "manga18.club",
                "hanman18.com",
                "18porncomic.com",
                "doujin18.net",
                "cndoujin.net"
            ],
            e: "//script[contains(text(),'slides_p_path')]"
        },
        imgs: () => _unsafeWindow.slides_p_path.map(e => atob(e)),
        capture: () => _this.imgs(),
        autoDownload: [0],
        next: () => _unsafeWindow.next_chapter === "" ? null : _unsafeWindow.next_chapter,
        prev: 1,
        customTitle: () => {
            if (fn.lh === "manga18.club" || fn.lh === "hanman18.com" || fn.lh === "18porncomic.com") {
                return document.title;
            } else {
                return fn.gt(".story_name>h1");
            }
        },
        category: "hcomic"
    }, {
        name: "Hentai.bang14.com",
        host: ["hentai.bang14.com"],
        reg: /^https?:\/\/hentai\.bang14\.com\/[^\/]+\/$/,
        include: ".entry-content",
        imgs: ".entry-content img",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: ".nav-previous a[rel=prev]",
        prev: ".nav-previous a[rel=next]",
        customTitle: "h1.entry-title",
        category: "hcomic"
    }, {
        name: "MANGA DISTRICT/apcomics",
        url: {
            h: ["mangadistrict.com", "apcomics.org"]
        },
        imgs: ".reading-content img",
        button: [4],
        insertImg: [".reading-content", 2],
        endColor: "white",
        autoDownload: [0],
        next: "a.next_page",
        prev: "a.prev_page",
        customTitle: "#chapter-heading",
        category: "hcomic"
    }, {
        name: "AllPornComic",
        host: ["allporncomic.com"],
        reg: /^https?:\/\/allporncomic\.com\/porncomic\/[^\/]+\/[^\/]+\/$/i,
        include: ".read-container",
        imgs: ".wp-manga-chapter-img",
        button: [4],
        insertImg: [".read-container", 2],
        endColor: "white",
        autoDownload: [0],
        next: "a.next_page",
        prev: "a.prev_page",
        customTitle: "#chapter-heading",
        category: "hcomic"
    }, {
        name: "Hachirumi.com",
        host: ["hachirumi.com"],
        reg: /^https?:\/\/hachirumi.com\/read\/manga\/[^\/]+\/.+/,
        init: () => fn.waitVar("Reader"),
        imgs: () => {
            const chapters = Object.values(_unsafeWindow.Reader.current.chapters);
            return chapters.map(e => Object.values(e.images)[0]).flat().map(url => fn.lo + url);
        },
        capture: () => _this.imgs(),
        customTitle: () => _unsafeWindow.Reader.current.title,
        category: "hcomic"
    }, {
        name: "7mmtvH漫畫貼圖",
        url: {
            h: "7mmtv.sx",
            p: "hcomic",
            e: "//script[contains(text(),'Large_cgurl')]"
        },
        imgs: () => {
            const {
                Large_cgurl
            } = _unsafeWindow;
            let arr = Large_cgurl.map(e => /imgur/.test(e) ? e : null).filter(item => item);
            return arr.length == 0 ? Large_cgurl : arr;
        },
        button: [4],
        insertImg: ["#show_cg_html", 2],
        insertImgAF: () => fn.remove("iframe"),
        customTitle: () => fn.dt({
            t: fn.title(" - 7mmtv.sx", 1)
        }),
        hide: ".ut1_img_content_js,.ut_cg1_top",
        category: "hcomic"
    }, {
        name: "18H",
        host: ["18h.mm-cg.com"],
        reg: /^https?:\/\/18h\.mm-cg\.com\/(zh\/?)\w+_content\/\d+\/content\.html$/i,
        imgs: () => _unsafeWindow.Large_cgurl,
        button: [4],
        insertImg: ["#show_cg_html", 2],
        customTitle: () => fn.title("-", 1),
        category: "hcomic"
    }, {
        name: "H 次元",
        host: ["h-ciyuan.com"],
        reg: /^https?:\/\/h-ciyuan\.com\/\d+\/\d+\/.+\//,
        include: "a[data-fancybox],.rl-gallery-container a",
        imgs: "a[data-fancybox],.rl-gallery-container a",
        thums: "a[data-fancybox] img,.rl-gallery-container a img",
        button: [4],
        //insertImg: [".entry-content", 2],
        insertImg: [
            [".entry-content,.rl-gallery-container", 2], 2
        ],
        go: 1,
        next: ".nav-previous>a",
        prev: ".nav-next>a",
        customTitle: ".post-title",
        category: "hcomic"
    }, {
        name: "淫漫画",
        host: ["www.yinmh.com", "www.yinmh.top", "www.yinmh.xyz"],
        reg: /^https?:\/\/www\.yinmh\.(com|top|xyz)\/\d+\.html$/,
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            return fn.fetchDoc(siteUrl).then(dom => fn.gae(".left>.image img.lazy", dom).map(e => e.getAttribute("img") ?? e.src));
        },
        button: [4],
        insertImg: [".left>.image", 2],
        customTitle: ".box>h1",
        category: "hcomic"
    }, {
        name: "漫畫車 閱讀頁",
        host: ["www.manhuache.com", "m.manhuache.com"],
        url: {
            h: "manhuache",
            p: "/chapter/"
        },
        init: async () => {
            let chapterName = fn.gt(".text-center.mt-3.mb-4");
            if (!/^第\d+話$/.test(chapterName)) {
                await fn.getNP("picture img", "//a[span[text()='下一章']][contains(@href,'chapter')]");
            }
        },
        imgs: () => fn.getImgSrcArr("picture img").map(src => src.replace(".thumb.jpg", "")),
        button: [4],
        insertImg: ["picture", 2],
        next: "//a[span[text()='下一章']][contains(@href,'chapter')]",
        prev: "//a[span[text()='上一章']]",
        customTitle: () => fn.title(/\s-\d+/).replace(/\(\d+P\)|第.章/gi, "").replace(/[\s-]+$/, "").trim(),
        category: "hcomic"
    }, {
        name: "漫畫車 目錄頁",
        host: ["www.manhuache.com", "m.manhuache.com"],
        url: {
            h: "manhuache",
            p: "/book/",
            e: ["#chapterGroupListJsonAsc,#chapterGroupListAsc", "//li/a[contains(text(),'成人寫真')][not(@class)]"]
        },
        init: () => fn.createImgBox("#chapterContentContainer~.module-title", 1),
        imgs: () => {
            let links = JSON.parse(document.querySelector("#chapterGroupListJsonAsc,#chapterGroupListAsc").value).flat().map(e => "/chapter/" + e.id);
            return fn.getImgA("picture img", links, 0, [".thumb.jpg", ""]);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        go: 1,
        customTitle: ".book-title-name",
        category: "hcomic"
    }, {
        name: "漫畫車 目錄頁",
        host: ["www.manhuache.com", "m.manhuache.com"],
        url: {
            h: "manhuache",
            p: "/book/",
            e: "#chapterGroupListJsonAsc,#chapterGroupListAsc"
        },
        init: () => fn.createImgBox("#chapterContentContainer~.module-title", 1),
        imgs: () => {
            let links = JSON.parse(document.querySelector("#chapterGroupListJsonAsc,#chapterGroupListAsc").value).flat().map(e => "/chapter/" + e.id);
            return fn.getImgA("picture img", links, 0, [".thumb.jpg", ""]);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: ".book-title-name",
        category: "hcomic"
    }, {
        name: "漫畫聯合國",
        host: ["www.comicun.com"],
        reg: /^https?:\/\/www\.comicun\.com\/index-look(-cid)?-name-.+/,
        FixURL: url => {
            if (/index-look-cid-name-/.test(url)) {
                let arr = url.split("-");
                let str = "";
                for (let i = 0; i < arr.length; i++) {
                    if (i == 7) {
                        str += arr[i];
                    } else if (i == 5) {
                        str += "cid-" + arr[i] + "-";
                    } else if (i != 2) {
                        str += arr[i] + "-";
                    }
                }
                return decodeURIComponent(str);
            } else {
                return decodeURIComponent(url);
            }
        },
        init: () => {
            fn.run("$(document).unbind('click');");
            if (/index-look-cid-name-/.test(siteUrl)) location.href = _this.FixURL(siteUrl);
            fn.gae("//a[text()='下一章'] | //a[text()='上一章']").forEach(a => (a.href = _this.FixURL(a.href)));
        },
        imgs: (url = siteUrl, dom, msg = 1, request = 0) => fn.getImg("#ComicPic", fn.ge("#total", dom).value, 20, null, 20, url, msg, request),
        button: [4, "24%", 1],
        insertImg: [".e", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: 1,
        customTitle: (dom) => {
            let arr = fn.gt(".b", 1, dom).split("-");
            return arr[2].trim() + " - " + arr[3].trim();
        },
        preloadNext: async (nextDoc, obj) => fn.picPreload(await obj.imgs(nextLink, nextDoc, 0, 1), obj.customTitle(nextDoc), "next"),
        hide: "body{overflow:unset!important}.awesome970",
        category: "comic"
    }, {
        name: "丽图·污漫画",
        host: ["litu100.xyz"],
        reg: /^https?:\/\/litu\d+\.xyz\/comic\/id-\w+\/\d+\.html$/,
        imgs: ".article.comic img",
        button: [4],
        insertImg: [".article.comic", 2],
        autoDownload: [0],
        next: "a.next",
        prev: "a.prev",
        customTitle: () => fn.dt({
            s: ".breadcrumb span:nth-child(2)",
            d: "首页"
        }),
        hide: ".banner_ad",
        category: "hcomic"
    }, {
        name: "漫小肆",
        host: ["www.mxsweb.cc"],
        url: {
            h: [
                "www.jjmhw.cc",
                "www.ikanmh.xyz",
                "www.ikanhm.xyz",
                "www.92hm.life",
                /^www\.mxs\d{1,2}\.cc$/
            ],
            p: "chapter"
        },
        init: () => fn.remove("//body/div[div[@id][@style][a]]|//body/div[div[@id][@style]][a[@id][@style]]"),
        imgs: "img[data-original]",
        button: [4],
        insertImg: [".comicpage,#cp_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => {
            if (fn.ge(".title")) {
                return fn.gt(".title");
            } else {
                return fn.ge("meta[name='Description']")?.content?.replace("当前阅读的是", "");
            }
        },
        referer: "src",
        category: "hcomic"
    }, {
        name: "Avbebe",
        host: ["avbebe.com"],
        link: "https://avbebe.com/archives/category/%e6%88%90%e4%ba%bah%e6%bc%ab%e7%95%ab",
        reg: /^https?:\/\/avbebe\.com\/archives\/\d+/,
        include: "//a[@rel='category tag' and text()='成人漫畫']",
        imgs: ".elementor-widget-container>p>img,.content-inner>p>img",
        button: [4],
        insertImg: [
            ["//p[img]", 2, "//p[img]"], 2
        ],
        customTitle: ".jeg_post_title",
        fancybox: {
            v: 3,
            css: false
        },
        category: "hcomic"
    }, {
        name: "ACG漫画网",
        host: ["acgmhx.com", "acgxmh.com", "acgsmh.com", "hentai-acg.com", "porn-comic.com"],
        url: {
            e: [".header>.header-con>.logo", ".manga-page,.main-picture"],
            p: /^\/([\w-]+\/)?(h|hentai|cos|webtoon|western)\/\d+\.html$/
        },
        //imgs: () => fn.getImg(".manga-page img,.main-picture img", fn.gt("#pages>*:last-child", 2), 5),
        imgs: async () => {
            await fn.getNP(".manga-page img,.main-picture img", "#pages span+a:not(.a1)", null, "#pages", 200);
            return fn.gae(".manga-page img,.main-picture img");
        },
        button: [4],
        insertImg: [".manga-page,.main-picture", 2],
        autoDownload: [0],
        next: ".next_pics>.fr>a[href$=html],.post-next a",
        prev: ".next_pics>.fl>a[href$=html],.post-pre a",
        customTitle: "h2.title,h1.title,.entry-header>h1",
        hide: ".pre_picture,.next_picture,[class^=ad300],[class^=ad900]",
        category: "hcomic"
    }, {
        name: "ACG漫画网",
        host: ["www.acgnbus.com", "acgnbus.com"],
        url: {
            e: ["#page.site", ".main-picture"],
            p: /^\/\w+\/\d+\.html$/,
            d: "m"
        },
        //imgs: () => fn.getImg(".main-picture img", fn.gt("//a[text()='下一页'][@class='a1']", 2), 5),
        imgs: async () => {
            await fn.getNP(".main-picture", "#pages span+a:not(.a1)", null, "#pages", 200);
            return fn.gae(".main-picture img");
        },
        button: [4],
        insertImg: [".entry-content", 2],
        next: ".post-next a",
        prev: ".post-pre a",
        customTitle: ".entry-header>h1",
        hide: ".pre_picture,.next_picture,.tips,.adbox",
        category: "hcomic"
    }, {
        name: "天黑漫画",
        host: "tianhei-acg.com",
        reg: /^https?:\/\/tianhei-acg\.com\/[^\/]+\/$/,
        imgs: ".wp-posts-content img[data-src]",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: "h1.article-title",
        fancybox: {
            blacklist: 1
        },
        category: "nsfw1"
    }, {
        name: "NiceCat",
        host: "web.nicecat.cc",
        reg: /^https?:\/\/web\.nicecat\.cc\//,
        SPA: () => document.URL.includes("/comic/info/") && ("headers" in localStorage),
        observerURL: true,
        comicUid: () => document.URL.match(/\/id\.(.+)$/)[1],
        getHeaders: () => JSON.parse(localStorage.getItem("headers")),
        init: () => {
            const ajaxHooker = addAjaxHookerLibrary();
            ajaxHooker.filter([{
                url: "/api/ComicInfo/info"
            }, {
                url: "/api/ComicOrder/getComicOrder"
            }]);
            ajaxHooker.hook(request => {
                if (localStorage.getItem("headers") !== JSON.stringify(request.headers)) {
                    localStorage.setItem("headers", JSON.stringify(request.headers));
                }
                if (getType(request.data) === "FormData") {
                    let object = Object.fromEntries([...request.data.entries()]);
                    if ("dateKey" in object) {
                        if (localStorage.getItem("dateKey") !== object.dateKey) {
                            localStorage.setItem("dateKey", object.dateKey);
                        }
                    }
                }
            });
        },
        imgs: (msg = 1) => {
            if (_this.SPA()) {
                fn.createImgBox("#recommend-info-body", 1);
                if (msg === 1) fn.showMsg(displayLanguage.str_05, 0);
                let formData = new FormData();
                formData.append("comicUid", _this.comicUid());
                formData.append("sort", "0");
                formData.append("dateKey", ("dateKey" in localStorage) ? localStorage.getItem("dateKey") : "SA4J0Br8W5fFPNb+Uhi0ugL0JXkOvcEw1BGid0UiosA=");
                return fetch("/api/ComicOrder/getComicOrder", {
                    "headers": _this.getHeaders(),
                    "body": formData,
                    "method": "POST"
                }).then(res => res.json()).then(json => json.data.imageData.map(e => e.imageUrl));
            } else {
                return [];
            }
        },
        capture: () => _this.imgs(0),
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: () => {
            if (_this.SPA()) {
                let formData = new FormData();
                formData.append("uid", _this.comicUid());
                return fetch("/api/ComicInfo/info", {
                    "headers": _this.getHeaders(),
                    "body": formData,
                    "method": "POST"
                }).then(res => res.json()).then(json => json.data.comicData.name_two ?? json.data.comicData.name_one).then(str => str.replaceAll("/", "∕"));
            } else {
                return null;
            }
        },
        category: "hcomic"
    }, {
        name: "紳士漫畫 圖片清單頁",
        link: "https://wnacg.date/,https://wnacg01.org/",
        //第3方API直接取得"寫真 & Cosplay"分類一整頁的畫廊資料
        //https://meoden.net/gallery?page=1&site=WN&siteTag=
        //https://meoden.net/api/gallery/wnacg?page=1
        url: {
            t: "紳士漫畫",
            p: "/photos-index-aid-"
        },
        init: async () => {
            fn.remove(".dlh,iframe:not(#FullPictureLoadIframe)");
            fn.remove("//body/div[a[img]] | //div[@class='Introduct']/a[div[img]] | //div[a[img[@alt='Game Tip']]]");
            fn.addMutationObserver(() => fn.remove(".dlh,iframe:not(#FullPictureLoadIframe)"));
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let [galleryId] = fn.lp.match(/\d+/);
            let galleryUrl = `/photos-gallery-aid-${galleryId}.html`;
            return fetch(galleryUrl).then(res => res.text()).then(text => text.match(/\/\/[\w\.]+\/data\/[^"'\\]+/gi));
        },
        button: [4],
        insertImg: [
            [".gallary_wrap,.Introduct", 0, ".gallary_wrap>.cc"], 2
        ],
        customTitle: () => fn.dt({
            d: / - 紳士漫畫.*$| - 绅士漫画.*$|-紳士漫畫.*$|-绅士漫画.*$/
        }),
        category: "hcomic"
    }, {
        name: "紳士漫畫 下拉閱讀頁",
        url: {
            t: "紳士漫畫",
            p: /^\/photos-(slide|slidelow|list|slist)-aid-\d+\.html$/
        },
        imgs: () => _unsafeWindow.imglist.map(e => e.url),
        button: [4],
        insertImg: ["#img_list", 2],
        customTitle: () => fn.dt({
            d: " - 列表"
        }),
        hide: "div[align=center],#control_block",
        category: "hcomic"
    }, {
        name: "紳夜漫畫",
        url: {
            h: "syacomic",
            t: "紳夜漫畫"
        },
        SPA: () => {
            if (document.URL.includes("/detail/")) {
                let [id] = new URL(document.URL).pathname.match(/\d+/);
                return fetch(`https://api.nftbaoyi.com/comic/${id}`).then(res => res.json()).then(async json => {
                    siteJson = json;
                    debug("\n此頁JSON資料\n", siteJson);
                    await fn.waitEle(".grid img");
                    fn.createImgBox(".grid", 1);
                    return json;
                });
            } else {
                return false;
            }
        },
        observerURL: true,
        imgs: () => siteJson?.book_pages?.map(e => e.img_url) || [],
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".grid,a.justify-center,div:has(>a.block),div:has(>.custom-pagination)"], 2
        ],
        customTitle: () => fn.dt({
            t: siteJson?.name
        }),
        hide: "body>ins,div:not([id],[class]):has(div.items-center)",
        category: "hcomic"
    }, {
        name: "Comics",
        host: ["pixiv.app"],
        reg: /^https?:\/\/pixiv\.app\/[\w-]+\/comics\/\w+$/i,
        SPA: () => document.URL.includes("/comics/"),
        observerURL: true,
        init: () => fn.waitEle("footer[class]"),
        imgs: ".bg-slate-100 img,.shadow-md img",
        customTitle: "h1",
        category: "hcomic"
    }, {
        name: "头牌漫画网/顶点漫画/第一漫画网",
        link: "https://xs8.me/,https://mh8.in/",
        host: ["dmmtu.com", "dmmpic.com", "dymmt.com", "kkmnt.com", "mmxzt.com"],
        url: {
            t: ["头牌漫画网", "顶点漫画", "顶点韩漫", "第一漫画网"],
            p: /^\/chapter\/\d+\.html$/
        },
        init: async () => {
            const last = doc => !fn.ge(".mip-box-body img", doc);
            await fn.getNP(".mip-box-body img", "//a[text()='下一页']", last, ".info");
            fn.createImgBox(".info", 2);
        },
        imgs: ".mip-box-body img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".mip-box-body>img"], 2
        ],
        autoDownload: [0],
        next: "a[title='下一章']",
        prev: "a[title='上一章']",
        customTitle: ".mip-box-heading",
        fancybox: {
            blacklist: 1
        },
        hide: "body>div[class][style]",
        category: "hcomic"
    }, {
        name: "VN漫画网 下拉阅读",
        host: ["www.vnacg.com"],
        reg: /^https?:\/\/(www|m)\.vnacg\.com\/show\/\d+\.html/,
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let api = `/e/extend/api/show.php?id=${_unsafeWindow.info.id}&page=`;
            let max = await fetch(`${api}1`).then(res => res.json()).then(res => res.pages);
            let fetchNum = 0;
            let resArr = fn.arr(max, (v, i) => fetch(`${api + (i + 1)}`).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                return json.data;
            }));
            return Promise.all(resArr).then(data => data.flat().map(e => e.src));
        },
        button: [4],
        insertImg: [".show,.read", 2],
        customTitle: () => fn.title("_免费阅读", 1),
        category: "hcomic"
    }, {
        name: "VN漫画网 清單頁",
        host: ["www.vnacg.com"],
        reg: /^https?:\/\/www\.vnacg\.com\/detail\/\d+\.html/,
        observerClick: ".layui-flow-more>a",
        category: "autoPager"
    }, {
        name: "TWHentai/台灣成人H漫/十八禁成人H漫 圖片清單頁",
        host: ["twhentai.com", "mttang.club", "hentai.desi"],
        reg: /^https?:\/\/(twhentai\.com|mttang\.club|(\w+\.)?hentai\.desi)\/\??(hentai_manga|hentai_doujin|hentai_western)\/\d+\/$/,
        imgs: async () => {
            await fn.getNP("//div[div[a[@class='thumbnail'][img]]]", ".pagination li.active+li:not(.disabled)>a", null, ".pagination");
            thumbnailSrcArray = fn.getImgSrcArr(".recommended img");
            return thumbnailSrcArray.map(e => e.replace("-thumb265x385", ""));
        },
        button: [4],
        insertImg: [
            [".footer", 1], 2
        ],
        go: 1,
        customTitle: () => {
            if (/twhentai|mttang/.test(fn.lh)) {
                return fn.gt(".recommended-info h3");
            } else {
                let h3s = fn.gae(".recommended-info h3");
                return h3s.length > 1 ? h3s[1].innerText : h3s[0].innerText;
            }
        },
        category: "hcomic"
    }, {
        name: "松鼠症倉庫 閱讀頁",
        host: ["ahri8.top"],
        url: {
            e: "//div[@id='logo-group']//a[contains(text(),'松鼠症倉庫') or contains(text(),'松鼠症仓库')]",
            p: "readOnline"
        },
        imgs: () => {
            const {
                Original_Image_List,
                HTTP_IMAGE
            } = _unsafeWindow;
            return Original_Image_List.map(e => HTTP_IMAGE + e.new_filename + "_w1500." + e.extension);
        },
        button: [4],
        insertImg: ["#Big_Image", 2],
        customTitle: () => fn.dt({
            s: ".page-header",
            d: "線上閱讀"
        }),
        hide: "#content>.col-lg-12,[id^=read_online_ads_area],#Big_Image~*",
        category: "hcomic"
    }, {
        name: "松鼠症倉庫 詳情頁",
        host: ["ahri8.top"],
        url: {
            e: "//div[@id='logo-group']//a[contains(text(),'松鼠症倉庫') or contains(text(),'松鼠症仓库')]",
            p: "/post",
            s: "ID="
        },
        init: () => {
            let e = fn.ge("//a[text()='預覽圖片']");
            e.innerText = "圖片";
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu("#more-information1 a:has(i.fa-book)");
            await fn.getCode(url, {
                mode: "dom",
                key: "Original_Image_List"
            });
            const {
                Original_Image_List,
                HTTP_IMAGE
            } = _unsafeWindow;
            return Original_Image_List.map(e => HTTP_IMAGE + e.new_filename + "_w1500." + e.extension);
        },
        button: [4],
        insertImg: ["#more-information1>div:has(img)", 2],
        category: "hcomic"
    }, {
        name: "Caitlin.top/Ahri Gallery分機 閱讀頁",
        host: ["caitlin.top", "ahri-gallery-xfjd-2024-04-25.top", "ahri-gallery-jq5s6-2024-04-29.top", "c922myqccl00207.top"],
        url: () => fn.checkUrl({
            h: "caitlin.top",
            p: "index",
            s: "readOnline"
        }) || fn.checkUrl({
            e: "//a[starts-with(text(),'Ahri Gallery')]",
            p: "index",
            s: "reader"
        }),
        imgs: () => {
            const {
                Image_List,
                IMAGE_SERVER,
                image_server_id,
                IMAGE_FOLDER
            } = _unsafeWindow;
            const getExtension = ext => {
                switch (ext) {
                    case "gif":
                        return "gif";
                    case "webp":
                        return "webp";
                    default:
                        return "jpg";
                }
            };
            let counter = 0;
            let srcArr = [];
            for (let Image of Image_List) {
                let ext = getExtension(Image.extension.toLowerCase());
                let src = IMAGE_SERVER[image_server_id][counter] + IMAGE_FOLDER + Image.sort + "." + ext;
                srcArr.push(src);
                counter += 1;
                if (counter >= Object.keys(IMAGE_SERVER[image_server_id]).length) {
                    counter = 0;
                }
            }
            return srcArr;
        },
        button: [4],
        insertImg: ["#Big_Image", 2],
        customTitle: ".page-header,.gallery_title",
        hide: "#content>.col-lg-12,[id^=read_online_ads_area],#Big_Image~*",
        category: "hcomic"
    }, {
        name: "Caitlin.top/Ahri Gallery分機 詳情頁",
        host: ["caitlin.top", "ahri-gallery-xfjd-2024-04-25.top", "ahri-gallery-jq5s6-2024-04-29.top", "c922myqccl00207.top"],
        url: () => fn.checkUrl({
            h: "caitlin.top",
            p: "index",
            s: "article"
        }) || fn.checkUrl({
            e: "//a[starts-with(text(),'Ahri Gallery')]",
            p: "index",
            s: "article"
        }),
        init: () => {
            if (fn.ge("//a[text()='Read']")) {
                fn.createImgBox(".container:has(.gallery_card)");
            } else {
                fn.createImgBox("#more-information1>div.row:has(img)", 2);
            }
            _unsafeWindow.onscroll = null;
        },
        imgs: async () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url;
            if (fn.ge("//a[text()='Read']")) {
                url = fn.gu("//a[text()='Read']");
            } else {
                url = fn.gu("#more-information1 a:has(i.fa-book)");
            }
            await fn.getCode(url, {
                mode: "dom",
                key: "Image_List"
            });
            const {
                Image_List,
                IMAGE_SERVER,
                image_server_id,
                IMAGE_FOLDER
            } = _unsafeWindow;
            const getExtension = ext => {
                switch (ext) {
                    case "gif":
                        return "gif";
                    case "webp":
                        return "webp";
                    default:
                        return "jpg";
                }
            };
            let counter = 0;
            let srcArr = [];
            for (let Image of Image_List) {
                let ext = getExtension(Image.extension.toLowerCase());
                let src = IMAGE_SERVER[image_server_id][counter] + IMAGE_FOLDER + Image.sort + "." + ext;
                srcArr.push(src);
                counter += 1;
                if (counter >= Object.keys(IMAGE_SERVER[image_server_id]).length) {
                    counter = 0;
                }
            }
            return srcArr;
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#more-information1>div.row:has(img)"], 2
        ],
        customTitle: () => fn.getText([".row>.col-xs-12>h2", "div.name>h2", ".gallery_title", ".gallery_title2"]),
        category: "hcomic"
    }, {
        name: "蚂蚁搬运网/紳士泛漫畫",
        link: "https://hacg.antbyw.com/plugin.php?id=jameson_manhua",
        url: {
            h: ["www.antbyw.com", /\.itsacg\.com$/],
            s: "=read",
            d: "pc"
        },
        imgs: ".uk-zjimg img",
        button: [4],
        insertImg: [".uk-zjimg", 2],
        autoDownload: [0],
        next: "//a[contains(text(),'下一章')]",
        prev: "//a[contains(text(),'上一章')]",
        customTitle: () => {
            let ct = fn.gt(".uk-breadcrumb>li:nth-child(4)");
            let nt = fn.gt(".uk-breadcrumb>li:nth-child(5)");
            if (ct.includes("|")) {
                ct = ct.split("|")[0].trim();
            }
            ct = ct.replace(/【.+】/g, "").trim();
            if (nt === "阅读浏览") {
                return ct;
            } else {
                return ct + " - " + nt;
            }
        },
        category: "comic"
    }, {
        name: "蚂蚁搬运网M/紳士泛漫畫M",
        link: "https://hacg.antbyw.com/plugin.php?id=jameson_manhua",
        url: {
            h: ["www.antbyw.com", "www.itsacg.com"],
            s: "=read",
            d: "m"
        },
        imgs: ".zjimg>img",
        button: [4],
        insertImg: [
            [".zjimg", 1, ".zjimg"], 2
        ],
        customTitle: () => fn.dt({
            t: fn.title("_", 3),
            d: [
                /【.+】/g,
                "_阅读浏览"
            ]
        }),
        category: "comic"
    }, {
        name: "ACG糖",
        host: ["acgotang.com"],
        url: {
            e: "//div[@class='content']//a[text()='ACG糖']",
            p: /^\/\w+\/\w+\.html$/
        },
        imgs: () => {
            let max = fn.gt("//a[text()='下一页']", 2);
            return fn.getImg(".manga-picture img", max, 5);
        },
        button: [4],
        insertImg: [".manga-page", 2],
        autoDownload: [0],
        next: ".next-toon a",
        prev: ".pre-toon a",
        customTitle: ".title",
        category: "hcomic"
    }, {
        name: "Roku Hentai",
        host: ["rokuhentai.com"],
        reg: /^https?:\/\/rokuhentai\.com\/\w+$/,
        include: ".site-page-card__media",
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.url + "/0";
            return fn.fetchDoc(url).then(dom => fn.getImgSrcArr(".site-reader__image", dom));
        },
        button: [4],
        insertImg: [
            [".site-manga-info+.mdc-layout-grid", 2], 2
        ],
        go: 1,
        customTitle: () => fn.title(" - Roku Hentai"),
        hide: ".site-bottom-ad-slot",
        fetch: 1,
        category: "hcomic"
    }, {
        name: "Roku Hentai",
        host: ["rokuhentai.com"],
        reg: /^https?:\/\/rokuhentai\.com\/\w+\/\d+$/,
        imgs: ".site-reader__image",
        button: [4],
        insertImg: [".site-reader", 2],
        customTitle: () => fn.title(" - Roku Hentai"),
        css: ".site-reader--right-to-left,.site-reader--left-to-right{overflow-x:auto!important;overflow-y:auto!important}.site-reader{padding-bottom:0px!important}.site-reader{display:block!important;}.site-bottom-ad-slot{display:none!important}",
        fetch: 1,
        category: "hcomic"
    }, {
        name: "177 漫画/XXIAV寫真館",
        url: {
            h: ["www.177pica.com", "www.177picyy.com", "www.xxiav.com"],
            p: /^\/html\/\d+\/\d+\/\d+\.html$/
        },
        imgs: () => fn.getImg(".single-content img[data-lazy-src]", (fn.gt(".page-links>*:last-child", 2) || 1), 10),
        button: [4],
        insertImg: [".single-content", 2],
        autoDownload: [0],
        next: "a[rel=prev]",
        prev: 1,
        customTitle: ".entry-title",
        category: "hcomic"
    }, {
        name: "18H 宅宅愛動漫",
        host: ["18h.animezilla.com"],
        reg: /^https?:\/\/18h\.animezilla\.com\/manga\/\d+/,
        imgs: () => {
            let max;
            try {
                max = fn.gu(".last").split("/").at(-1);
            } catch {
                max = 1;
            }
            return fn.getImgO("#comic", max, "4", null, 0, ".entry-title,.wp-pagenavi", siteUrl, 0);
        },
        button: [4],
        insertImg: ["#page-current", 1],
        customTitle: () => fn.dt({
            s: "h1.entry-title",
            d: /\s?\[\d+P\](\s?-\s?\d+\/\d+\s?)?/i
        }),
        category: "hcomic"
    }, {
        name: "色漫网",
        url: {
            h: "www.cartoon18.com",
            p: "/v/",
            e: ".title+div>a.btn-info"
        },
        init: () => fn.createImgBox(".row.mb-4", 2),
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let urls = fn.gau(".title+div>a.btn-info");
            return fn.getImgA("img[data-src],#lightgallery a,.gallary a", urls, 2000);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        fancybox: {
            v: 3,
            css: false
        },
        hide: "#chromeModal,.modal-backdrop",
        category: "hcomic"
    }, {
        name: "色漫网",
        url: {
            h: "www.cartoon18.com",
            p: "/v/",
            e: ".title+div>a>i.fa-play"
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let url = fn.gu(".title+div>a");
            return fn.fetchDoc(url).then(dom => fn.ge("img[data-src]", dom) ? fn.gae("img[data-src]", dom) : fn.gae("#lightgallery a,.gallary a", dom));
        },
        button: [4],
        insertImg: ["//div[a[img]]", 2],
        insertImgAF: (parent) => {
            parent.className = "";
            let modalOpen = fn.ge(".modal-open");
            if (modalOpen) modalOpen.classList.remove("modal-open");
        },
        fancybox: {
            v: 3,
            css: false
        },
        hide: "#chromeModal,.modal-backdrop",
        category: "hcomic"
    }, {
        name: "色漫网",
        host: ["www.cartoon18.com"],
        reg: /^https?:\/\/www\.cartoon18\.com\/([\w-]+\/)?story\/\d+\/full/,
        imgs: () => fn.ge("img[data-src]") ? fn.gae("img[data-src]") : fn.gae("#lightgallery a,.gallary a"),
        button: [4],
        insertImg: ["#lightgallery,.gallary", 2],
        autoDownload: [0],
        next: "//a[text()='下一話']",
        prev: "//a[text()='上一話']",
        fancybox: {
            v: 3,
            css: false
        },
        category: "hcomic"
    }, {
        name: "开心看漫画 閱讀頁",
        host: ["kxmanhua.com"],
        url: {
            t: "开心看漫画",
            p: "/detail/"
        },
        imgs: ".blog__details__content img",
        button: [4],
        insertImg: [".blog__details__content", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='下一话'][@href]",
        prev: "//a[text()='上一话'][@href]",
        customTitle: () => fn.ge("meta[name='manga-name']").content + " - " + fn.ge("meta[name='chap-title']").content,
        hide: ".fixed-ads,.ad-banner,.blog__details__content~*",
        category: "hcomic"
    }, {
        name: "凹凸漫/X漫/肉漫天堂 目錄頁",
        url: {
            t: "开心看漫画",
            p: "/manga/"
        },
        init: () => fn.createImgBox(".anime__details__episodes", 2),
        imgs: () => {
            let links = fn.gau(".chapter_list a").reverse();
            return fn.getImgA(".blog__details__content img", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: ".anime__details__title>h3",
        hide: ".ad-banner",
        category: "hcomic"
    }, {
        name: "凹凸漫/X漫/肉漫天堂 閱讀頁",
        host: ["atm333.com", "xman5.com", "rmtt6.com"],
        url: {
            h: /atm|xman|rmtt/,
            p: "read/",
            e: [
                "center>h1",
                "center>h2"
            ]
        },
        init: () => fn.clearAllTimer(),
        imgs: "img.lazyload[data-original]",
        button: [4],
        insertImg: ["center:has(>div>img.lazyload[data-original])", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => fn.gt("center>h1") + " - " + fn.gt("center>h2"),
        category: "hcomic"
    }, {
        name: "凹凸漫/X漫/肉漫天堂 目錄頁",
        host: ["atm333.com", "xman5.com", "rmtt6.com"],
        url: {
            h: /atm|xman|rmtt/,
            p: "detail/",
            e: [
                ".hot_banner",
                ".playlist_full"
            ]
        },
        init: () => {
            fn.clearAllTimer();
            if ("showlist" in _unsafeWindow) {
                _unsafeWindow.showlist();
            }
            fn.createImgBox(".hot_banner", 2);
        },
        imgs: () => {
            let links = fn.gau(".playlist_full .content_playlist a");
            return fn.getImgA("img.lazyload[data-original]", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: "h1.title",
        category: "hcomic"
    }, {
        name: "韓漫射/绅士同人H漫",
        url: {
            h: ["h-webtoon.com", "h-doujinshi.xyz"]
        },
        init: "setTimeout(()=>{fn.gae('.g1-nav-single a').forEach(e=>{e.removeAttribute('target')})},2000)",
        imgs: ".g1-content-narrow p img",
        button: [4],
        insertImg: [".g1-content-narrow", 2],
        autoDownload: [0],
        next: "#content .g1-teaser-next",
        prev: "#content .g1-teaser-prev",
        customTitle: "h1.entry-title",
        hide: "#simple-banner,.touchy-wrapper,.touchy-wrapper~*:not([id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],[id^='pagetual'],[class^='pagetual'],#comicRead,#fab,*[class^=fancybox]),.code-block,#secondary",
        category: "hcomic"
    }, {
        name: "18H漫画",
        host: ["18hmanga.com", "18hmanga.cyou"],
        reg: /^https?:\/\/(18hmanga\.(com|cyou))\/[^\/]+\/$/,
        init: () => fn.remove(".code-block,#secondary,body>div[id][class][style]"),
        imgs: ".entry-content>img,.entry-content>p>img,.entry-content>div>img",
        button: [4],
        insertImg: [".entry-content", 2],
        autoDownload: [0],
        next: "#content .g1-teaser-prev",
        prev: "#content .g1-teaser-next",
        customTitle: ".entry-title",
        css: ".g1-column-2of3{width:100%!important}",
        category: "hcomic"
    }, {
        name: "18H漫画",
        url: {
            h: "18hmanga",
            e: "//a[contains(text(),'Read More')]"
        },
        init: () => fn.remove("body>div[id][class][style]"),
        imgs: () => {
            fn.showMsg(displayLanguage.str_01, 0);
            let fetchNum = 0;
            let resArr = fn.gau("//a[contains(text(),'Read More')]").map((url, i, arr) => {
                return fn.fetchDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${arr.length}`, 0);
                    return fn.gae(".entry-content>img,.entry-content>p>img,.entry-content>div>img", dom);
                });
            })
            return Promise.all(resArr).then(arr => arr.flat());
        },
        button: [4],
        insertImg: [
            ["#primary", 0], 2
        ],
        go: 1,
        customTitle: ".g1-breadcrumbs-item>span[itemprop=name]",
        category: "hcomic"
    }, {
        name: "老司機禁漫 目錄頁",
        host: ["laosiji6.com", "laosiji52.com"],
        url: {
            h: "laosiji",
            p: /^\/comic\/\d+$/i
        },
        init: () => fn.createImgBox(".detail", 2),
        imgs: () => {
            let links = fn.gau(".vol-item a").reverse();
            return fn.getImgA("img.lazy", links);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0], 3
        ],
        customTitle: ".detail h1",
        category: "hcomic"
    }, {
        name: "老司機禁漫 閱讀頁",
        host: ["laosiji6.com", "laosiji52.com"],
        url: {
            h: "laosiji",
            p: /^\/comic\/\d+\/\w+$/i
        },
        init: () => fn.createImgBox("img.lazy", 1),
        imgs: "img.lazy",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "img.lazy"], 2
        ],
        insertImgAF: () => {
            if (nextLink && !fn.ge("//a[text()='章節目錄']")) {
                fn.addUrlHtml(nextLink, ".container-fluid", 2);
                fn.css(".positionFooter{display:none!important;}");
            }
        },
        autoDownload: [0],
        next: () => {
            let chapterId = fn.lp.split("/").at(-1);
            let comicUrl = fn.gu(".breadcrumb-item:nth-child(2)>a");
            let nextXPath = `//div[div[div[label[span[a[contains(@href,'${chapterId}')]]]]]]/preceding-sibling::div[1]//a`;
            return fn.fetchDoc(comicUrl).then(dom => {
                let next = fn.ge(nextXPath, dom, dom);
                return next ? next.href : null;
            });
        },
        prev: 1,
        customTitle: () => fn.gt(".breadcrumb-item:nth-child(2) a").trim() + " - " + fn.gt(".breadcrumb-item.active").trim(),
        category: "hcomic"
    }, {
        name: "COMIC18",
        host: ["www.comic18.cc"],
        reg: /^https?:\/\/www\.comic18\.cc\/\w+\/\d+\.html$/,
        init: () => fn.waitEle(".article-body>img").then(e => fn.createImgBox(e, 1)),
        imgs: ".article-body>img",
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".article-body>img"], 2
        ],
        autoDownload: [0],
        next: "a.entry-page-prev[href$=html]",
        prev: "a.entry-page-next[href$=html]",
        customTitle: ".detail-title",
        category: "hcomic"
    }, {
        name: "18漫畫",
        host: ["18mh.org"],
        reg: [
            /^https?:\/\/badynews\.com\/[^\/]+$/i,
            /^https?:\/\/18mh\.org\/manga\/[\w-]+\/[\d-]+/
        ],
        init: async () => {
            await fn.waitEle(".touch-manipulation img");
            fn.remove(".flex.flex-row.space-x-2.px-2.py-4");
        },
        imgs: ".touch-manipulation img",
        button: [4],
        insertImg: [".touch-manipulation", 2],
        autoDownload: [0],
        next: "#nextChapterLink",
        prev: "#preChapterLink",
        customTitle: () => fn.gt("ol.inline-flex>li:nth-child(2) a").trim() + " - " + fn.gt("ol.inline-flex>li:nth-child(3) a").trim(),
        category: "hcomic"
    }, {
        name: "Hitomi.la",
        url: {
            h: "hitomi.la",
            p: "/reader/"
        },
        init: async () => {
            await fn.wait(() => document.title !== "| Hitomi.la");
            fn.run("setTimeout(()=>{$(document).unbind('keydown');$(document).unbind('click')},1000)");
        },
        imgs: async () => {
            await fn.waitEle("#mobileImages .lillie", 11);
            const {
                galleryinfo,
                url_from_url_from_hash,
                our_galleryinfo
            } = _unsafeWindow;
            fn.ge("#comicImages").setAttribute("class", "fitVertical");
            fn.ge("#mobileImages").setAttribute("class", "hidden");
            if (options.fancybox == 1) {
                fn.showMsg("Get Thumbnailsing...");
                let url = fn.gu("//a[text()='Gallery Info']");
                let dom = await fn.iframeDoc(url, ".gallery-preview img");
                thumbnailSrcArray = fn.gae(".gallery-preview img", dom).map(e => e.dataset.src ?? e.src);
            }
            return galleryinfo.files.map((e, i) => url_from_url_from_hash(galleryinfo.id, our_galleryinfo[i], "webp", undefined, "a"));
        },
        button: [4],
        insertImg: ["#comicImages", 2],
        endColor: "white",
        customTitle: () => fn.title("|", 1),
        css: "body{overflow:unset!important}",
        category: "hcomic"
    }, {
        name: "HO5HO",
        host: ["www.ho5ho.com"],
        reg: /^https?:\/\/www\.ho5ho\.com\/.+\/.+\/server.+\//,
        include: "//script[contains(text(),'chapter_preloaded_images')]",
        imgs: () => _unsafeWindow.chapter_preloaded_images,
        button: [4],
        insertImg: [".entry-content", 2],
        customTitle: ".breadcrumb>li:nth-child(2)",
        category: "hcomic"
    }, {
        name: "成人漫画 圖片清單頁",
        host: ["bad.news"],
        link: "https://bad.news/mh",
        reg: /^https?:\/\/bad\.news\/mh\/\w+\/id-\d+$/,
        imgs: () => {
            let link = [fn.gu("a.post-thumb")];
            return fn.getImgA("img.img-responsive", link);
        },
        thums: "img.img-responsive",
        button: [4],
        insertImg: [
            ["//div[div[article[div[div[a[img[@class='img-responsive']]]]]]]", 2], 2
        ],
        go: 1,
        category: "hcomic"
    }, {
        name: "成人漫画 閱讀頁",
        host: ["bad.news"],
        link: "https://bad.news/mh",
        reg: /^https?:\/\/bad\.news\/mh\/view\/id-\d+/,
        imgs: ".img-responsive",
        button: [4],
        insertImg: ["//div[img[@class='img-responsive']]", 2],
        category: "hcomic"
    }, {
        name: "H漫画",
        host: ["a.123548.xyz"],
        url: {
            e: "//div[@class='logo']/a[text()='H漫画']",
            p: "/e/action/ShowInfo.php"
        },
        imgs: ".entry img",
        button: [4],
        insertImg: [".entry", 1],
        autoDownload: [0],
        next: "//p[contains(text(),'上一')]/a",
        prev: "//p[contains(text(),'下一')]/a",
        customTitle: ".contitle",
        category: "hcomic"
    }, {
        name: "JComic",
        host: ["jcomic.net"],
        reg: /^https?:\/\/jcomic\.net\/page\/[^\/]+$/,
        imgs: ".comic-view,.comic-thumb",
        button: [4],
        insertImg: ["//div[img[@class='img-responsive comic-thumb']]", 2],
        customTitle: "//ol/li[2]/a",
        category: "hcomic"
    }, {
        name: "JComic",
        host: ["jcomic.net"],
        reg: /^https?:\/\/jcomic\.net\/page\/[^\/]+\/[0-9\.]+$/,
        imgs: ".comic-view,.comic-thumb",
        button: [4],
        insertImg: ["//div[img[@class='img-responsive comic-thumb']]", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//a[button[text()='下一章']]");
            return next && next.href != siteUrl ? next.href : null;
        },
        prev: 1,
        customTitle: () => fn.gt("//ol/li[2]/a") + " - " + fn.gt("//ol/li[3]"),
        category: "hcomic"
    }, {
        name: "一之涩漫画/哈塔兹漫画/布罗塔漫画/物二漫画",
        url: {
            h: [
                "1zse.com",
                "hatazi.com",
                "www.bulota.com",
                /52216\d\.xyz$/
            ],
            p: /^\/index\.php\/\d+\.html/
        },
        init: () => {
            fn.addMutationObserver(() => fn.remove("#eruda,.__chobitsu-hide__,#lightboxOverlay,#lightbox"));
            fn.clearAllTimer();
        },
        imgs: () => fn.getImg(".context img", fn.gt(".pages").match(/\d+/g)[1], 7),
        button: [4],
        insertImg: [".context", 2],
        autoDownload: [0],
        next: ".post-previous a",
        prev: ".post-next a",
        customTitle: () => fn.dt({
            s: "#content h1",
            d: /\[\d+P\]|〈|〉/gi
        }),
        hide: "body>*:not(#head,.container,#footer,#tbox,[id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],#comicRead,#fab,*[class^=fancybox])",
        category: "hcomic"
    }, {
        name: "那露漫画",
        host: ["naluhd.com"],
        reg: /^https?:\/\/naluhd\.com\/index\.php\/\d+\.html/,
        imgs: () => fn.getImgA(".article-content img", "a.post-page-numbers"),
        button: [4],
        insertImg: [".article-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇'] and not(starts-with(@href,'java'))]",
        prev: "//a[p[text()='下一篇'] and not(starts-with(@href,'java'))]",
        customTitle: ".article-title>a",
        category: "hcomic"
    }, {
        name: "色色漫画/最新韩漫网",
        host: ["www.sesemanhua.com", "www.manhuazuixin.com"],
        reg: [
            /^https:\/\/www\.sesemanhua\.com\/index\.php\/chapter\/\d+/,
            /^https?:\/\/www\.manhuazuixin\.com\/chapter_\d+\.html/
        ],
        include: ".rd-article-wr,.comic-list",
        imgs: ".rd-article-wr img,.comic-list img",
        button: [4],
        insertImg: [".rd-article-wr,.comic-list", 2],
        autoDownload: [0],
        next: ".j-rd-next,.next-btn",
        prev: ".j-rd-prev,.prev-btn",
        customTitle: ".comic-title>a,.comic-name,.mip-shell-header-title",
        category: "hcomic"
    }, {
        name: "韩国a漫 閱讀頁",
        host: ["www.hanguoaman.com"],
        reg: /^https?:\/\/www\.hanguoaman\.com\/read\/\d+\.html$/,
        imgs: ".container img",
        button: [4],
        insertImg: [".container", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/')]",
        customTitle: () => fn.dt({
            d: / - 韩国.+$/
        }),
        category: "hcomic"
    }, {
        name: "韩国a漫 目錄頁",
        host: ["www.hanguoaman.com"],
        reg: /^https?:\/\/www\.hanguoaman\.com\/aman\//,
        init: () => fn.createImgBox(".stui-pannel:last-of-type", 1),
        imgs: () => {
            let links = fn.gau(".stui-content__playlist a");
            return fn.getImgA(".container img", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: "h1.title",
        category: "hcomic"
    }, {
        name: "韩漫天下",
        host: ["manhuatianxia.com", "www.manhuatianxia.com"],
        reg: /^https?:\/\/(www\.)?manhuatianxia\.com\/index\.php\/chapter\/\d+$/,
        imgs: "#manga-imgs img,#BookText img",
        button: [4],
        insertImg: ["#manga-imgs,#BookText", 2],
        autoDownload: [0],
        next: "//a[text()='下一话' or text()='下一章'][starts-with(@href,'/')]",
        prev: "//a[text()='上一话' or text()='上一章'][starts-with(@href,'/')]",
        customTitle: () => fn.dt({
            d: "韩漫 "
        }),
        category: "hcomic"
    }, {
        name: "韩漫在线",
        host: ["hanmanzx.com", "www.hanmanzx.com"],
        reg: /^https?:\/\/(www\.)?hanmanzx\.com\/index\.php\/chapter-\d+\.html$/,
        imgs: ".content_read #content img,.chapter_content img",
        button: [4],
        insertImg: [".content_read #content,.chapter_content", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/')] | //a[div[span[contains(text(),'下一篇')]]][starts-with(@href,'/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/')] | //a[div[span[contains(text(),'上一篇')]]][starts-with(@href,'/')]",
        customTitle: () => fn.dt({
            d: "在线观看 "
        }),
        category: "hcomic"
    }, {
        name: "九妖漫画",
        host: ["lifantt.com", "9yaomh.cc"],
        url: {
            t: "九妖漫画网",
            p: "/chapter/"
        },
        imgs: ".rd-article-wr img,.comic-list img",
        button: [4],
        insertImg: [".rd-article-wr,.comic-list", 2],
        autoDownload: [0],
        next: ".j-rd-next,.next-btn",
        prev: ".j-rd-prev,.prev-btn",
        customTitle: () => fn.title(" - 九妖漫画网"),
        hide: "[class^=ad],.m-hm-ad1,p.result",
        category: "hcomic"
    }, {
        name: "韩漫库/欲漫涩/腐漫屋/快看禁漫",
        host: ["se8.us", "yumanse.com", "fumanwu.org", "kkcomic.vip"],
        url: {
            t: ["韩漫库", "欲漫涩", "腐漫屋", "快看禁漫"],
            p: "/chapter/"
        },
        imgs: ".rd-article-wr img,.comic-list img,.episode-detail img",
        button: [4],
        insertImg: [".rd-article-wr,.comic-list,.episode-detail", 1],
        autoDownload: [0],
        next: ".j-rd-next,.next-btn,a.next[href^='/']",
        prev: ".j-rd-prev,.prev-btn,a.prev[href^='/']",
        customTitle: async () => {
            if (fn.ge(".rd-article-wr")) {
                return fn.gt(".read__crumb").replace("首页  ", "").replace("  ", " - ");
            } else {
                try {
                    return _unsafeWindow.shareArr[0].match(/《([^》]+)/)[1] + " - " + fn.gt(".comic-name");
                } catch {
                    let url = fn.gu("//a[contains(text(),'全集')]");
                    let comicName = await fn.fetchDoc(url).then(dom => fn.gt("h1.title", 1, dom));
                    return comicName + " - " + fn.gt(".center-title");
                }
            }
        },
        hide: "body>ins,div[id^='show']",
        category: "hcomic"
    }, {
        name: "日漫之家",
        host: ["rimanzhijia.com"],
        reg: /^https?:\/\/rimanzhijia\.com\/index\.php\/chapter\/\d+/,
        imgs: "#comic_pic",
        button: [4],
        insertImg: [
            ["#comic_pic", 2, "#comic_pic"], 2
        ],
        autoDownload: [0],
        next: "//a[contains(text(),'下一章')][starts-with(@href,'/')]",
        prev: "//a[contains(text(),'上一章')][starts-with(@href,'/')]",
        customTitle: () => fn.gt(".bo_tit").replace(">", "-"),
        css: ".bo_nav{width:97%!important;padding:10px!important}",
        hide: "img[src*='/ad/']",
        category: "hcomic"
    }, {
        name: "最新韩漫网M",
        host: ["www.zuixinhanman.com", "www.xinhanman.com"],
        reg: /^https?:\/\/www\.(zui)?xinhanman\.com\/chapter_\d+\.html/,
        delay: 300,
        imgs: "#comic_pic",
        button: [4],
        insertImg: [
            [".bo_tit", 2, "#comic_pic"], 2,
        ],
        autoDownload: [0],
        next: "//a[contains(text(),'下一章')][contains(@href,'html')]",
        prev: "//a[contains(text(),'上一章')][contains(@href,'html')]",
        customTitle: ".mip-shell-header-title",
        fancybox: {
            blacklist: 1
        },
        category: "hcomic"
    }, {
        name: "韩漫100",
        host: ["hanman100.com"],
        reg: /^https?:\/\/hanman100\.com\/index\.php\/chapter-\d+\.html/,
        init: () => fn.createImgBox("#all", 2),
        imgs: "#img-content img,.comic-list img",
        button: [4, "24%", 4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#all"], 2
        ],
        autoDownload: [0],
        next: ".pnext.next+a[href$=html],.next-btn",
        prev: 1,
        customTitle: () => fn.dt({
            s: "h1.text-center,.comic-name",
            d: "漫画 "
        }),
        hide: "#left,#right",
        category: "hcomic"
    }, {
        name: "免费韩漫看",
        host: ["www.hanmanm.com"],
        reg: /^https?:\/\/www\.hanmanm(\w+)?\.com\/index\.php\/chapter\/\d+/,
        imgs: "#ChapterContent img,.readForm img",
        button: [4],
        insertImg: ["#ChapterContent,.readForm", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/')]",
        customTitle: () => fn.ge("#ChapterContent") ? fn.gt(".arthor") + " - " + fn.gt(".title") : fn.title("免费观看 "),
        category: "hcomic"
    }, {
        name: "韩漫推荐",
        host: ["www.hanmantop.com"],
        reg: /^https?:\/\/www\.hanman(\w+)?\.com\/index\.php\/chapter\/\d+/,
        include: "//div/div[@style]/img[@style]",
        imgs: "//div/div[@style]/img[@style]",
        button: [4],
        insertImg: ["//div[div[@style]/img[@style]]", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/')]",
        customTitle: "h1[style]",
        category: "hcomic"
    }, {
        name: "韩漫推荐M",
        host: ["www.hanmantop.com"],
        reg: /^https?:\/\/www\.hanman(\w+)?\.com\/index\.php\/chapter\/\d+/,
        imgs: ".chapterbox img",
        button: [4],
        insertImg: [
            [".chapterbox>*:first-child", 1, ".pic"], 2
        ],
        autoDownload: [0],
        next: "//a[text()='继续阅读下一章节']",
        prev: 1,
        customTitle: () => fn.title("韩漫 "),
        category: "hcomic"
    }, {
        name: "51漫画/爱漫画",
        host: ["51comic.org", "aicomic.org"],
        reg: [
            /^https?:\/\/aicomic\.org\/index\.php\/chapter\/\d+/,
            /^https?:\/\/51comic\.org\/chapter\/\d+/
        ],
        init: () => fn.addMutationObserver(() => fn.remove("//div[div[text()='x']]")),
        imgs: () => fn.ge(".rd-article-wr") ? fn.gae(".rd-article-wr img") : fn.gae(".comic-list img:not([src$='empty.png'])"),
        button: [4],
        insertImg: [".rd-article-wr,.comic-list", 1],
        autoDownload: [0],
        next: ".j-rd-next:not([style]):not(.hide),.next-btn",
        prev: ".j-rd-prev,.prev-btn",
        customTitle: () => fn.ge(".rd-article-wr") ? fn.gt(".j-comic-title") + " - " + fn.gt(".comic-title>a").replace(/\d+p/i, "") : _unsafeWindow.shareArr[0].match(/《([^》]+)/)[1] + " - " + fn.gt(".comic-name").replace(/\d+p/i, ""),
        hide: ".image-container",
        category: "hcomic"
    }, {
        name: "特漫网",
        host: ["www.44te.com"],
        reg: /^https?:\/\/www\.44te\.com\/chapter\/\d+$/,
        imgs: ".comicpage img:not([src*='/banner/']),#cp_img img:not([src*='/banner/'])",
        button: [4],
        insertImg: [".comicpage,#cp_img", 2],
        autoDownload: [0],
        next: "//a[@href and not(starts-with(@href,'java')) and text()='下一章']",
        prev: "//a[@href and not(starts-with(@href,'java')) and text()='上一章']",
        customTitle: () => fn.title(/无删减/, 1),
        hide: "body>div[style^=background],[id^=ad]",
        category: "hcomic"
    }, {
        name: "一耽女孩",
        host: ["yidan.in", "yidan.one", "yidan.app"],
        reg: /^https?:\/\/yidan\.(in|one|app)\/#\/pages\/read\/read\?no=\d+&id=\d+(&episodesId=\d+)?/,
        init: async () => {
            await fn.waitEle([".read-article img", "uni-view.last-bum"]);
            fn.ge("uni-view.last-bum").addEventListener("click", () => setTimeout(() => location.reload(), 300));
            fn.showMsg(displayLanguage.str_05, 0);
            let [, no, mhid] = fn.url.match(/no=(\d+)&id=(\d+)/);
            let api = `/prod-api/app-api/vv/mh-episodes/get?jiNo=${no}&mhid=${mhid}&id=`;
            let fetchJson = await fetch(api).then(res => res.json());
            debug("\n此頁JSON資料\n", fetchJson);
            siteJson = fetchJson;
        },
        imgs: () => siteJson.data.pics.split(",").map(e => fn.lo + e),
        button: [4],
        insertImg: [".read-article", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//a[text()='继续看下一话']");
            if (next) {
                let [, mhid] = fn.url.match(/&id=(\d+)/);
                let url = `https://${fn.lh}/#/pages/read/read?no=${siteJson.data.next}&id=${mhid}`;
                return url;
            }
            return null;
        },
        prev: 1,
        customTitle: () => fn.title(" - 一耽女孩_好看的一耽漫画官网").trim(),
        hide: ".page-pagination",
        category: "hcomic"
    }, {
        name: "91禁漫",
        host: ["www.91jinman.com"],
        reg: /^https?:\/\/www\.91jinman\.com\/\d+\.html/,
        imgs: ".wp-posts-content img",
        button: [4],
        insertImg: [".wp-posts-content", 2],
        autoDownload: [0],
        next: "//a[p[text()='上一篇']]",
        prev: "//a[p[text()='下一篇']]",
        customTitle: ".article-title",
        css: ".wp-posts-content{max-height:unset!important}",
        category: "hcomic"
    }, {
        name: "鸟鸟韩漫 閱讀頁",
        host: ["nnhanman6.com"],
        url: {
            h: "nnhanman",
            p: "chapter",
            e: ".BarTit>h1"
        },
        imgs: "img[data-original]",
        button: [4],
        insertImg: ["//td[img] | //div[@class='view-imgBox']", 2],
        autoDownload: [0],
        next: "#k_Pic_nextArr",
        prev: 1,
        customTitle: () => fn.gt(".BarTit>h1").replace(" - 第1章", ""),
        category: "hcomic"
    }, {
        name: "鸟鸟韩漫 目錄頁",
        host: ["nnhanman6.com"],
        url: {
            h: "nnhanman",
            p: "/comic/",
            e: ".Introduct_Sub"
        },
        init: () => fn.createImgBox(".txtDesc", 2),
        imgs: () => {
            let links = fn.gau("#list a").reverse();
            return fn.getImgA("img[data-original]", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: ".Introduct_Sub h1",
        category: "hcomic"
    }, {
        name: "松鼠韓漫 閱讀頁",
        host: ["www.songshuhanman.com"],
        url: {
            h: "songshuhanman",
            p: "/ch/"
        },
        imgs: ".more-box img",
        button: [4],
        insertImg: [".more-box", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/ch/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/ch/')]",
        customTitle: "h1",
        category: "hcomic"
    }, {
        name: "松鼠韓漫 目錄頁",
        host: ["www.songshuhanman.com"],
        url: {
            h: "songshuhanman",
            p: "/com/"
        },
        init: () => fn.createImgBox(".contpost2.gap", 2),
        imgs: () => {
            let links = fn.gau(".playlist a");
            return fn.getImgA(".more-box img", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: "article h1",
        category: "hcomic"
    }, {
        name: "野貓韓漫 閱讀頁",
        url: {
            e: ".logo img[alt^=野貓韓漫]",
            p: "/read/"
        },
        imgs: ".module img",
        button: [4],
        insertImg: [".module", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/read/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/read/')]",
        customTitle: () => {
            let text = fn.attr("meta[name=keywords]", "content");
            let textArr = text.split(",").map(t => t.trim());
            let [, comicName, chapterName] = textArr;
            return comicName + " - " + chapterName;
        },
        category: "hcomic"
    }, {
        name: "野貓韓漫 目錄頁",
        url: {
            e: ".logo img[alt^=野貓韓漫]",
            p: "/m/"
        },
        init: () => fn.createImgBox(".module-info", 2),
        imgs: () => {
            let links = fn.gau(".module-play-list a");
            return fn.getImgA(".module img", links);
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        customTitle: ".module-info-heading h1",
        category: "hcomic"
    }, {
        name: "肉漫画网",
        host: ["www.roumanhua.com", "m.roumanhua.com"],
        reg: /^https?:\/\/(www|m)\.roumanhua\.com\/(wap)?chapter\/\d+/,
        imgs: "img[data-original]",
        button: [4],
        insertImg: [
            ["img[data-original]", 2, "img[data-original]"], 2
        ],
        autoDownload: [0],
        next: "//a[text()='下一章节'] | //a[@class='s_page2']",
        prev: "//a[text()='上一章节'] | //a[@class='s_page1']",
        customTitle: () => fn.title("|韩国漫画网"),
        category: "hcomic"
    }, {
        name: "漫香阁",
        host: ["xn--wgv69rba1382b.com", "韩漫日漫.com"],
        url: {
            t: "漫香阁",
            p: /^\/content-[\w-]+\.html$/
        },
        imgs: "#contentimg img",
        button: [4],
        insertImg: ["#contentimg", 2],
        customTitle: ".services-desc",
        category: "hcomic"
    }, {
        name: "頂點漫畫",
        host: ["www.apexmh.com"],
        reg: /^https?:\/\/www\.apexmh\.com\/comic\/\d+\.html/,
        imgs: () => fn.getImg("#showimg img", fn.gt("//p[contains(text(),'图片数量') or contains(text(),'圖片數量')]").match(/\d+/)[0], 9),
        button: [4],
        insertImg: ["#showimg", 2],
        customTitle: "h1",
        category: "hcomic"
    }, {
        name: "亲亲漫画",
        host: ["m.qinqinmanhua.xyz"],
        reg: /^https?:\/\/m\.qinqinmanhua\.xyz\/view\/\d+\.html/,
        imgs: ".showimg img",
        autoDownload: [0],
        next: ".BtnBox>.next[href*=view]",
        prev: ".BtnBox>.prev[href*=view]",
        customTitle: () => document.title.match(/《(.+)》/)[1],
        category: "hcomic"
    }, {
        name: "狮城漫画",
        host: ["hdcomic.com"],
        reg: /^https?:\/\/hdcomic\.com\/chapter\/\d+/,
        init: () => fn.clearAllTimer(),
        imgs: ".comicpage img,#cp_img img",
        button: [4],
        insertImg: [".comiclist,#cp_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][@href]",
        prev: "//a[text()='上一章'][@href]",
        customTitle: () => fn.title(/免费阅读-狮城漫画|在线阅读-狮城漫画/).replace(/\s-\s\(\d+P\)-高清全集/i, ""),
        category: "hcomic"
    }, {
        name: "韩漫连连看",
        host: ["www.hmllk.com"],
        reg: /^https?:\/\/www\.hmllk\.com\/chapter\/\d+/,
        init: () => fn.clearAllTimer(),
        imgs: ".comicpage img,#cp_img img",
        button: [4],
        insertImg: [".comiclist,#cp_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][@href]",
        prev: "//a[text()='上一章'][@href]",
        customTitle: () => fn.title(/免费阅读-连连看.+|免费在线看.+/).replace(/\s-\s\(\d+P\)-高清全集/i, ""),
        category: "hcomic"
    }, {
        name: "漫画大全网",
        link: "https://www.kanman.buzz/",
        url: {
            t: "漫画大全网",
            p: "/chapter/"
        },
        imgs: "#reader-scroll img[width]",
        button: [4],
        insertImg: ["#reader-scroll", 2],
        endColor: "white",
        autoDownload: [0],
        next: () => {
            let code = fn.gst("#js_right");
            let next = code.match(/\/chapter\/\d+\/\d+\.html/g).at(-1);
            if (next === fn.lp) {
                return null;
            }
            return next;
        },
        prev: "#js_left",
        customTitle: () => fn.title(/全集免费.+$/),
        fancybox: {
            blacklist: 1
        },
        category: "hcomic"
    }, {
        name: "顶通漫画",
        link: "https://喜悅.toptooncn.club/學習.html",
        url: {
            h: "toptoon",
            p: /^\/\w+\/\d+\.html$/,
            e: ".place"
        },
        imgs: "#txtbox img",
        button: [4],
        insertImg: ["#txtbox", 2],
        autoDownload: [0],
        next: "a.nexturl.on",
        prev: "a.prevurl.on",
        customTitle: () => {
            let arr = fn.gt(".place").split(">").map(s => s.trim());
            return arr[2] + " - " + arr[3];
        },
        hide: ".ads_plugin,.ad-top-info",
        category: "hcomic"
    }, {
        name: "H肉番动漫",
        host: ["www.rhmanhua11.xyz", "www.rhmanhua12.xyz"],
        reg: /^https?:\/\/www\.rhmanhua(\d+)?\.xyz\/artshow-\d+\.html/,
        imgs: () => {
            thumbnailSrcArray = fn.getImgSrcArr(".margin-fix img");
            return thumbnailSrcArray.map(e => e.replace(/t(\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [".list-videos", 2],
        go: 1,
        customTitle: ".headline>h2",
        category: "hcomic"
    }, {
        name: "色漫集",
        host: ["semanji.com"],
        reg: /^https?:\/\/semanji\.com\/\w+\/[^\.]+\.html/,
        imgs: ".post-content a",
        button: [4],
        insertImg: [".post-content", 2],
        customTitle: () => fn.title(" - 色漫集"),
        fancybox: {
            v: 3,
            css: false
        },
        category: "hcomic"
    }, {
        name: "18H汉化漫画 介紹頁",
        host: ["manhua.sexbook.top", "18manga.top", "mt91.top", "kk4.top"],
        url: {
            e: "//ul[@class='nav-main']//a[text()='18H汉化漫画']",
            p: "/cont.php",
            s: "?id="
        },
        imgs: async () => {
            let max = fn.gt("#td-Act+#td-Series").match(/\d+/)[0];
            let [, imgDir, , ex] = fn.gu(".article-content a").match(/^(.+\/)(\d+)(\.\w+)$/);
            return fn.arr(max, (v, i) => imgDir + (i + 1) + ex);
        },
        button: [4],
        insertImg: [
            [".content", 0, ".article-content>a"], 2
        ],
        endColor: "white",
        go: 1,
        customTitle: () => fn.gt(".article-content>h3").split("|")[1],
        fancybox: {
            blacklist: 1
        },
        css: ".single .content{margin-right:0px!important;}",
        hide: ".sidebar,.modown-ad",
        category: "hcomic"
    }, {
        name: "18H汉化漫画 閱讀頁",
        host: ["manhua.sexbook.top", "18manga.top", "mt91.top", "kk4.top"],
        url: {
            e: "//ul[@class='nav-main']//a[text()='18H汉化漫画']",
            p: "/imgs.php",
            s: "?id="
        },
        imgs: async () => {
            let next = fn.ge("li.active+li");
            if (next) {
                let last = fn.ge("//a[contains(text(),'最大頁') or contains(text(),'最大页')]");
                let lastDoc = await fn.fetchDoc(last.href);
                let [lastFn] = fn.gst("decodeBinaryString", lastDoc).match(/decodeBinaryString\('[^;]+/g);
                let html = fn.run(lastFn);
                let tempDoc = fn.doc(html);
                let lastA = fn.gae("a", tempDoc).at(-1);
                let [, max] = lastA.href.match(/(\d+)\.\w+$/);
                let [, imgDir, , ex] = fn.gu("#imgs>a").match(/^(.+\/)(\d+)(\.\w+)$/);
                return fn.arr(max, (v, i) => imgDir + (i + 1) + ex);
            } else {
                return fn.gae("#imgs>a");
            }
        },
        button: [4],
        insertImg: ["#imgs", 2],
        endColor: "white",
        customTitle: ".article-content>h3",
        fancybox: {
            blacklist: 1
        },
        css: ".single .content{margin-right:0px!important;}",
        hide: ".sidebar,.modown-ad",
        category: "hcomic"
    }, {
        name: "hanime1",
        host: ["hanime1.biz", "ani02.xyz", "anime01.xyz"],
        url: {
            e: ["//a[contains(text(),'anime1')][@href='/home']", ".blog"],
            p: /^\/book\/\d+$/
        },
        init: async () => {
            fn.ge(".blog").scrollIntoView({
                block: "end"
            });
            await fn.delay(2000);
        },
        imgs: async () => {
            await fn.waitEle(".blog_section img[title]:not([src*=cover])");
            thumbnailSrcArray = fn.getImgSrcArr(".blog_section img[title]:not([src*=cover])");
            return thumbnailSrcArray.map(e => e.replace(/t(\d+\.\w+)$/, "$1"));
        },
        button: [4],
        insertImg: [
            [".m-1>.blog_section", 2], 2
        ],
        go: 1,
        customTitle: ".blog_section h1,.blog_section h3",
        hide: ".blog_section.max-w-7xl.mx-auto.rounded-sm.p-2.pb-3,.flex.flex-row.flex-wrap.items-center.text-center.justify-center",
        category: "hcomic"
    }, {
        name: "JavABC",
        host: ["javabc.club"],
        reg: /^https?:\/\/javabc\.club\/chapter\/\d+$/i,
        include: "#enc_img img",
        init: () => {
            fn.clearAllTimer();
            fn.remove("//div[@class='comicpage']/a[img] | //div[@class='comicpage']/div[script] | //div[@id='cp_img']/a[img] | //div[@id='cp_img']/div[script]");
        },
        imgs: async () => {
            await fn.getNP("#enc_img>div,#enc_img>img", "//a[text()='下一页'][@href]", null, ".fanye,.view-bottom-bar");
            return fn.gae("#enc_img img");
        },
        button: [4],
        insertImg: ["#enc_img", 2],
        customTitle: () => {
            if (fn.ge(".comic-name")) {
                return fn.gt(".comic-name");
            } else {
                let [, text] = fn.gst("bookInfo").match(/bookInfo[\s=]+([^;]+)/);
                let bookInfo = fn.run(text);
                return bookInfo.book_name;
            }
        },
        css: "img{opacity:1!important;}",
        category: "hcomic"
    }, {
        name: "桃心漫画",
        host: ["txcomic.com"],
        reg: /^https?:\/\/txcomic\.com\/chapter\/\d+$/i,
        include: "#enc_img img",
        init: () => fn.remove("//div[@class='comicpage']/a[img] | //div[@class='comicpage']/div[script] | //div[@id='cp_img']/a[img] | //div[@id='cp_img']/div[script]"),
        imgs: "#enc_img img",
        button: [4],
        insertImg: ["#enc_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][@href]",
        prev: "//a[text()='上一章'][@href]",
        customTitle: () => {
            if (fn.ge(".title")) {
                return fn.gt(".title");
            } else {
                let [, text] = fn.gst("bookInfo").match(/bookInfo[\s=]+([^;]+)/);
                let bookInfo = fn.run(text);
                return bookInfo.book_name + " - " + bookInfo.chapter_name;
            }
        },
        hide: "#pubcdnModal",
        category: "hcomic"
    }, {
        name: "有色漫画网",
        host: ["yousemanhua.com"],
        reg: /^https?:\/\/yousemanhua\.com\/index\.php\/chapter\/\d+$/i,
        imgs: "img[data-original]:not([data-original*='empty.png'])",
        button: [4],
        insertImg: [".rd-article-wr,.chapter_content", 2],
        autoDownload: [0],
        next: "//a[contains(@class,'j-rd-next')][@_href] | //a[div[span[contains(text(),'下一篇')]]]",
        prev: "//a[contains(@class,'j-rd-prev')][@_href] | //a[div[span[contains(text(),'上一篇')]]]",
        customTitle: async () => {
            if (fn.ge(".read__crumb")) {
                let arr = fn.gt(".read__crumb").split("  ");
                return arr[1] + " - " + arr[2];
            } else {
                let dom = await fn.fetchDoc(fn.gu(".nav_left>a"));
                return fn.title(" - 有色漫画", 0, dom) + " - " + fn.title(" - 有色漫画");
            }
        },
        category: "hcomic"
    }, {
        name: "漫画御殿",
        host: ["eromangabigdata.com"],
        reg: /^https?:\/\/eromangabigdata\.com\/\w+\/\d+\/\w\/[\w-_]+$/i,
        imgs: () => fn.gae("#imgwrap img").map(e => e.dataset.width ?? e.src),
        button: [4],
        insertImg: ["#imgwrap", 2],
        go: 1,
        customTitle: "#pan span.pan",
        hide: "#chip",
        category: "hcomic"
    }, {
        name: "LXMANGA",
        host: ["lxmanga.life"],
        reg: /^https?:\/\/lxmanga\.life\/[\w-]+\/[\w-]+\/[\w-]+/i,
        include: "//nav[li[span[starts-with(text(),'Danh')]]]",
        imgs: "img.lazy.max-w-full",
        button: [4],
        insertImg: [".text-center:has(img.lazy.max-w-full)", 2],
        autoDownload: [0],
        next: "//a[button[span[text()='Chương sau']]][not(starts-with(@href,'javascript'))]",
        prev: "//a[button[span[text()='Chương trước']]][not(starts-with(@href,'javascript'))]",
        customTitle: () => fn.title(" - ", 3),
        category: "hcomic"
    }, {
        name: "污污漫畫",
        host: ["www.55comic.com", "www.comicbox.xyz", "www.wuwucomic.xyz"],
        reg: /^https?:\/\/(www\.55comic\.com|www\.comicbox\.xyz|www\.wuwucomic\.xyz)\/chapter\/\d+$/i,
        include: ".comiclist",
        init: () => fn.remove("//div[div[@class='CarouselView center']]"),
        imgs: async () => {
            let arr = [];
            await fn.aotoScrollEles(".comiclist div[data-src]", (ele) => {
                let canvas = fn.ge("canvas", ele);
                if (canvas) {
                    arr.push(canvas.toDataURL("image/jpeg"));
                    return true;
                }
                return false;
            });
            return arr.map(e => fn.dataURLtoBlobURL(e));
        },
        button: [4],
        insertImg: [".comicpage", 0],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: ".title",
        fetch: 1,
        category: "hcomic"
    }, {
        name: "污污漫畫M",
        host: ["www.55comic.com", "www.comicbox.xyz"],
        reg: /^https?:\/\/(www\.55comic\.com|www\.comicbox\.xyz)\/chapter\/\d+$/i,
        include: "#cp_img",
        imgs: async () => {
            let arr = [];
            await fn.aotoScrollEles(".cropped[data-src]", (ele) => {
                let canvas = fn.ge("canvas", ele);
                if (canvas) {
                    arr.push(canvas.toDataURL("image/jpeg"));
                    return true;
                }
                return false;
            });
            _unsafeWindow.scrollTo({
                top: 0
            });
            return arr.map(e => fn.dataURLtoBlobURL(e));
        },
        button: [4],
        insertImg: ["#cp_img", 0],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => fn.title(" - 污污漫畫"),
        fetch: 1,
        category: "hcomic"
    }, {
        name: "污漫天堂",
        host: ["wumtt.com"],
        url: {
            e: ".logo>a[title='污漫天堂']",
            p: "/mangaread/"
        },
        imgs: ".content>center>div>img",
        button: [4],
        insertImg: [".content>center>div:has(>img)", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => fn.dt({
            s: ".content h1",
            d: [
                "《",
                "》"
            ]
        }) + " - " + fn.gt(".content h2"),
        category: "hcomic"
    }, {
        name: "污污漫书/55漫書",
        url: {
            h: ["www.55comics.com", "www.55manshu.com"],
            p: /\/\d+\.html$/,
            e: ".scramble-page img"
        },
        imgs: async () => {
            if (fn.ge(".pagination li.active")) {
                let max = fn.gt("//li[a[text()='下一页»' or text()='下一頁»' or text()='Next»']]", 2);
                let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url + "?p=" + (i + 1));
                return fn.getImgA(".scramble-page img", links);
            } else {
                await fn.getNP(".scramble-page", "//li/a[text()='下一页»' or text()='下一頁»' or text()='Next»']", null, ".pagination");
                return fn.gae(".scramble-page img");
            }
        },
        button: [4],
        insertImg: [
            [".scramble-page", 2, ".scramble-page"], 2
        ],
        insertImgAF: () => {
            let arr = ["//div[div[@class='ads']]", "//div[ul[ul[@class='pagination']]]"];
            fn.remove(arr);
        },
        autoDownload: [0],
        next: "//a[text()='下一话»' or text()='下一話»']",
        prev: "//a[text()='上一话»' or text()='上一話»']",
        customTitle: () => {
            let str = fn.gt(".chapter-left h1");
            let strArr = str.split(">");
            strArr = strArr.map(str => str.trim());
            return strArr[2] + " - " + strArr[3];
        },
        observerClick: "#chk_cover",
        hide: ".row:has(>.ads)",
        category: "hcomic"
    }, {
        name: "污污漫书/55漫書",
        url: {
            h: ["www.55comics.com", "www.55manshu.com"]
        },
        observerClick: "#chk_cover",
        hide: ".row:has(>.ads)",
        category: "ad"
    }, {
        name: "日韩漫画/歪歪漫画",
        host: ["www.diyihm.com", "www.lltoon.com", "www.rrtoon.com", "wwtoon.com", "www.zztoon.com", "www.vvtoon.com", "www.fftoon.com", "www.wwtoon.com", "www.niumh.com"],
        link: "https://www.niumh.com/view/9922/524220",
        url: {
            t: ["第一漫画", "歪歪漫画", "第一韩漫", "太极漫画网"],
            p: /^\/view\/\d+\/\d+$/,
            e: "//script[contains(text(),'$(document).ready')]",
            d: "m"
        },
        init: () => {
            try {
                let code = fn.gt("//script[contains(text(),'$(document).ready')]");
                let objStr = code.match(/window\.\w+\s?=\s?([^;]+)/)[1];
                let json = JSON.parse(objStr);
                debug("\n此頁JSON資料\n", json);
                siteJson = json;
            } catch {}
        },
        imgs: async () => {
            if (isArray(siteJson?.volume?.pages) && siteJson?.volume?.pages?.length > 0) {
                return siteJson.volume.pages;
            } else if (fn.ge("//a[text()='本章已分页']")) {
                fn.showMsg(displayLanguage.str_01, 0);
                let arr = [];
                let src;
                let page = 1;
                let loop = true;
                const getData = () => fn.fetchDoc(location.href + "/" + page).then(dom => {
                    fn.showMsg(`${displayLanguage.str_02}${page}/???`, 0);
                    const srcs = fn.getImgSrcArr(".charpetBox img", dom);
                    for (src of srcs) {
                        if (arr.includes(src)) {
                            loop = false;
                            return;
                        } else {
                            arr.push(src);
                        }
                    }
                });
                while (loop) {
                    await getData();
                    page++;
                }
                return arr;
            } else {
                return fn.gae(".charpetBox img");
            }
        },
        button: [4, "24%", 3],
        insertImg: [".charpetBox", 2],
        autoDownload: [0],
        next: "#loadNextChapter",
        prev: "#loadPrevChapter",
        customTitle: () => {
            if (siteJson?.volume?.title) {
                return siteJson.comic.title + " - " + siteJson.volume.title;
            } else {
                return fn.gt(".BarTit");
            }
        },
        hide: "body>div[class][style]:first-of-type,.letchepter[style*='20px'],#FullPictureLoadGoToLastImage~*:not([id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],#comicRead,#fab,*[class^=fancybox])",
        category: "hcomic"
    }, {
        name: "Manhuascan.us",
        url: {
            h: "manhuascan.us",
            p: "/manga/"
        },
        imgs: "#readerarea img",
        button: [4],
        insertImg: ["#readerarea", 2],
        next: ".section_button a:has(>.fa-angle-right)",
        prev: ".section_button a:has(>.fa-angle-left)",
        customTitle: () => fn.title(" - Manhuascan.us"),
        category: "comic"
    }, {
        name: "Mangago",
        host: ["mangago.me", "mangago.zone", "youhim.me"],
        url: {
            h: /mangago|youhim/,
            p: /^\/read-manga\/|^\/chapter\//,
            e: "#pic_container",
            d: "pc"
        },
        init: async () => {
            fn.clearAllTimer();
            fn.createImgBox("#pic_container", 1, 1000);
            fn.remove("#pic_container");
            await fn.getEleF("#pagenavigation a", "#pic_container img", ["#FullPictureLoadMainImgBox", 0]);
        },
        imgs: () => fn.gae("#FullPictureLoadMainImgBox img"),
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 0],
        endColor: "white",
        next: () => {
            if (fn.lp.includes("/chapter/")) {
                let cid = fn.lp.split("/").at(-2);
                let selector = `.chapter li:has(a[href*='${cid}'])+li>a`;
                return fn.gu(selector);
            } else {
                return fn.gu("//p[contains(text(),'Next Chapter:')]/a");
            }
        },
        prev: 1,
        customTitle: () => {
            let url = fn.gu(".widepage a");
            return fn.fetchDoc(url).then(dom => fn.ge(".rating_wrap a", dom)?.title.replace("Peole who read ", "") + " - " + fn.gt("#dropdown-chapter-page"));
        },
        css: "#FullPictureLoadMainImgBox img[id^=page]{width:auto;height:auto;max-width:100%}",
        hide: "div:has(>img[onclick])",
        category: "comic"
    }, {
        name: "MangaDex",
        url: {
            h: "mangadex.org",
            e: "link[title=MangaDex]",
            d: "pc"
        },
        SPA: () => new URL(document.URL).pathname.startsWith("/chapter/"),
        observerURL: true,
        init: () => fn.wait((d) => d.title != "" && !d.title.includes("Loading")),
        imgs: () => {
            if (_this.SPA()) {
                fn.showMsg(displayLanguage.str_05, 0);
                const chapter_id = new URL(document.URL).pathname.split("/").at(2);
                return fetch(`https://api.mangadex.org/at-home/server/${chapter_id}?forcePort443=false`).then(res => res.json()).then(json => {
                    fn.hideMsg();
                    const {
                        baseUrl,
                        chapter: {
                            data,
                            hash
                        }
                    } = json;
                    return data.map(e => baseUrl + "/data/" + hash + "/" + e);
                });
            } else {
                return [];
            }
        },
        next: async () => {
            if (_this.SPA()) {
                await fn.waitEle("#chapter-selector li[data-value]");
                let id = location.pathname.split("/").at(-1);
                let chapters = [...document.querySelectorAll("#chapter-selector li[data-value]")];
                let nextUrl = null;
                chapters.some((e, i, a) => {
                    if (e.dataset.value == id) {
                        if (a[i - 1] === undefined) {
                            nextUrl = null;
                        } else {
                            nextUrl = "https://mangadex.org/chapter/" + a[i - 1].dataset.value;
                        }
                        return true;
                    } else {
                        return false;
                    }
                });
                return nextUrl;
            } else {
                return null;
            }
        },
        customTitle: async () => {
            await _this.init();
            let text = fn.dt({
                d: [
                    /^[\d\s\|]+/,
                    " - MangaDex"
                ]
            });
            let textArr = text.split(" - ");
            return textArr[1] + " - " + textArr[0];
        },
        category: "comic"
    }, {
        name: "NamiComi",
        url: {
            h: "namicomi.com",
            e: "meta[content=NamiComi]",
            d: "pc"
        },
        SPA: () => new URL(document.URL).pathname.includes("/chapter/"),
        observerURL: true,
        imgs: () => {
            if (_this.SPA()) {
                fn.showMsg(displayLanguage.str_05, 0);
                const chapter_id = new URL(document.URL).pathname.split("/").at(3);
                return fetch(`https://api.namicomi.com/images/chapter/${chapter_id}?newQualities=true`).then(res => res.json()).then(json => {
                    fn.hideMsg();
                    const {
                        data: {
                            baseUrl,
                            hash,
                        }
                    } = json;
                    let data;
                    let quality;
                    let keys = ["source", "high", "medium", "low"];
                    for (let k of keys) {
                        if (Array.isArray(json.data[k])) {
                            data = json.data[k];
                            quality = k;
                            break;
                        }
                    }
                    return data.map(e => baseUrl + "/chapter/" + chapter_id + "/" + hash + `/${quality}/` + e.filename);
                });
            } else {
                return [];
            }
        },
        next: async () => {
            if (_this.SPA()) {
                let id = location.pathname.split("/").at(-1);
                await fn.waitEle(`select.relative option[value=${id}]`);
                let chapters = [...document.querySelectorAll("select.relative option")];
                let nextUrl = null;
                chapters.some((e, i, a) => {
                    if (e.value == id) {
                        if (a[i - 1] === undefined) {
                            nextUrl = null;
                        } else {
                            nextUrl = "https://namicomi.com/en/chapter/" + a[i - 1].value;
                        }
                        return true;
                    } else {
                        return false;
                    }
                });
                return nextUrl;
            } else {
                return null;
            }

        },
        customTitle: () => {
            let text = fn.dt({
                d: [
                    / - NamiComi.+$/
                ]
            });
            let textArr = text.split(" - ");
            return textArr[1] + " - " + textArr[0];
        },
        category: "comic"
    }, {
        name: "BATOTO",
        url: {
            h: "bato.to",
            p: "/chapter/"
        },
        imgs: () => {
            let code = fn.gst("imgHttps");
            let [, text] = code.match(/imgHttps[\s\=]+([^;]+)/);
            return JSON.parse(text);
        },
        button: [4],
        insertImg: ["#viewer", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[span[contains(text(),'Next Chapter')]]",
        prev: 1,
        customTitle: () => {
            let id = fn.lp.split("/").at(-1);
            let chapters = fn.gae("optgroup[label=Chapters] option");
            let chapterName = chapters.find(e => e.value == id).innerText;
            let magaName = fn.gt(".nav-title>a");
            return magaName + " - " + chapterName.replaceAll("\n", "").replace(/\s{2,10}/, "");
        },
        category: "comic"
    }, {
        name: "Dynasty Reader",
        url: {
            h: "dynasty-scans.com",
            p: "/chapters/",
            e: "#reader"
        },
        imgs: () => _unsafeWindow.pages.map(e => fn.lo + e.image),
        button: [4],
        insertImg: ["#reader", 2],
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 4);
            }
        },
        autoDownload: [0],
        next: "#next_link",
        prev: 1,
        customTitle: () => fn.title("Dynasty Reader » "),
        category: "comic"
    }, {
        name: "Hiperdex/MangaRead",
        url: {
            h: ["hiperdex.com", "www.mangaread.org"],
            p: /^\/manga\/[\w-]+\/chapter/
        },
        imgs: ".wp-manga-chapter-img",
        button: [4],
        insertImg: [".reading-content", 2],
        autoDownload: [0],
        next: "a.next_page",
        prev: "a.prev_page",
        customTitle: "#chapter-heading",
        category: "comic"
    }, {
        name: "MangaSee/MangaLife",
        url: {
            h: ["mangasee123.com", "manga4life.com"],
            p: "/read-online/"
        },
        init: async () => {
            await fn.waitEle("#TopPage img[ng-src^=http]");
            fn.createImgBox("#TopPage", 1);
        },
        imgs: () => {
            let srcArr = [];
            let ngSrc = fn.attr("#TopPage img", "ng-src");
            let ps = fn.gae("#TopPage div[ng-repeat]").length;
            return fn.arr(ps, (v, i) => ngSrc.replace(/^(.+\/\d+-)(\d+)(\.\w+)$/, `$1${String(i + 1).padStart(3, "0")}$3`));
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#TopPage"], 2
        ],
        endColor: "white",
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 3);
            }
        },
        autoDownload: [0],
        next: () => {
            let nextIndex = null;
            let buttons = fn.gae("#ChapterModal [ng-repeat]>button");
            if (fn.lp.includes("-index-")) {
                let [, s] = fn.lp.match(/-index-(\d)/);
                buttons = buttons.filter(e => e.innerText.startsWith("S" + s));
            }
            if (buttons.some(e => e.innerText.startsWith("S1 ")) && !fn.lp.includes("-index-")) {
                buttons = buttons.filter(e => e.innerText.startsWith("S1 "));
            }
            let buttonTexts = buttons.map(b => b.innerText);
            let chapterIndexs = buttonTexts.map(t => t.match(/[\d\.]+$/)[0]).reverse();
            let [, cNum] = fn.lp.match(/-chapter-(\d+)/);
            for (let [i, v] of chapterIndexs.entries()) {
                if (cNum == v) {
                    if (chapterIndexs[i + 1] !== undefined) {
                        nextIndex = chapterIndexs[i + 1];
                    }
                    break;
                }
            }
            if (nextIndex !== null) {
                return fn.lp.replace(/(-chapter-)(\d+)/, `$1${nextIndex}`);
            }
            return nextIndex;
        },
        prev: 1,
        customTitle: () => fn.title(" Page 1"),
        category: "comic"
    }, {
        name: "MangaPark",
        host: ["mangapark.net", "mangapark.com", "mangapark.to", "parkmanga.com"],
        url: {
            t: "Share Any Manga on MangaPark",
            p: ["chapter", "/title/"]
        },
        init: () => fn.waitEle(["[data-name='image-item'] img", "//script[contains(text(),'pageName') and contains(text(),'image_server')]"]),
        imgs: () => JSON.parse(fn.gst("image_server")).objs.filter(e => {
            try {
                return e.startsWith("http") && /\.(jpe?g|png|webp|gif)$/i.test(e) && !["/thumb/", "/ampi/", "/mpim/", "/mpav/"].some(t => e.includes(t));
            } catch {
                return false;
            }
        }),
        button: [4],
        insertImg: [".items-center:has(>div[data-name='image-item'])", 2],
        autoDownload: [0],
        next: "//a[span[text()='Next Chapter']]",
        prev: "//a[span[text()='Prev Chapter']]",
        customTitle: () => fn.title(" - Share Any Manga on MangaPark"),
        category: "comic"
    }, {
        name: "Mangakakalot",
        host: ["ww8.mangakakalot.tv"],
        url: {
            h: "mangakakalot",
            p: "/chapter/"
        },
        imgs: "#vungdoc img",
        button: [4],
        insertImg: ["#vungdoc", 2],
        autoDownload: [0],
        next: "//a[starts-with(text(),'NEXT')]",
        prev: "//a[starts-with(text(),'PREV')]",
        customTitle: ".info-top-chapter>h2",
        category: "comic"
    }, {
        name: "MangaHere/Manga Fox 分頁模式",
        url: {
            h: ["www.mangahere.cc", "fanfox.net"],
            p: "/manga/",
            e: ".cp-pager-list span",
        },
        imgs: () => {
            const {
                imagecount,
                croot,
                chapterid
            } = _unsafeWindow;
            let fetchNum = 0;
            let keyE = fn.ge("#dm5_key");
            let key = keyE.value;
            let resArr = fn.arr(imagecount, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: chapterid,
                    page: i + 1,
                    key: key
                });
                let api = `${croot}chapterfun.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(res => {
                    fn.showMsg(`${displayLanguage.str_06}(${fetchNum+=1}/${imagecount})`, 0);
                    let text = fn.run(res.slice(4));
                    let [, pix] = text.match(/pix="([^"]+)/);
                    let [, pvalue] = text.match(/pvalue=([^;]+)/);
                    pvalue = JSON.parse(pvalue);
                    return pix + pvalue[0];
                });
            });
            return Promise.all(resArr);
        },
        button: [4],
        insertImg: [".reader-main", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='Next Chapter']",
        prev: "//a[text()='Pre chapter']",
        customTitle: () => fn.ge("meta[name='og:title']")?.content?.split(" - ")[1]?.replace(/Read | Online/g, ""),
        hide: ".ad-reader,.pager-list-left>span",
        category: "comic"
    }, {
        name: "MangaHere/Manga Fox 條漫模式",
        url: {
            h: ["www.mangahere.cc", "fanfox.net"],
            p: "/manga/",
            e: ".cp-pager-list",
        },
        imgs: ".reader-main img",
        button: [4],
        insertImg: [".reader-main", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='Next Chapter']",
        prev: "//a[text()='Pre chapter']",
        customTitle: () => fn.ge("meta[name='og:title']")?.content?.split(" - ")[1]?.replace(/Read | Online/g, ""),
        hide: ".ad-reader",
        category: "comic"
    }, {
        name: "MangaHere/Manga Fox M",
        url: {
            h: ["m.mangahere.cc", "m.fanfox.net"],
            p: ["/manga/", "/roll_manga/"],
            e: "#viewer"
        },
        init: () => {
            let url = fn.url.replace("/manga/", "/roll_manga/");
            return fn.fetchDoc(url).then(dom => {
                siteJson.srcs = fn.getImgSrcArr("#viewer img", dom);
                let btn = fn.ge(".roll-pagebtn", dom);
                if (btn) {
                    tempEles.push(btn);
                    let next = fn.ge("//a[text()='Next Chapter']", btn);
                    if (next) {
                        tempNextLink = next.href;
                    }
                }
            });
        },
        imgs: () => siteJson.srcs,
        button: [4, "24%", 1],
        insertImg: ["#viewer", 2],
        endColor: "white",
        insertImgAF: (parent) => {
            if (tempEles.length > 0 && !fn.ge(".roll-pagebtn")) {
                for (let e of tempEles) {
                    insertAfter(parent, e);
                }
            }
            fn.remove(".pager,.mangaread-page");
        },
        next: () => tempNextLink,
        prev: 1,
        customTitle: () => {
            if (fn.lh.includes("fanfox")) {
                return document.title + fn.gt(".mangaread-title");
            } else {
                let [text] = fn.gst("addHistory").match(/{"href[^}]+}/);
                let obj = JSON.parse(text);
                let ch = fn.gt(".return-title");
                return obj.name + " - " + ch;
            }
        },
        category: "comic"
    }, {
        name: "MangaHere/Manga Fox M",
        url: {
            h: ["newm.mangahere.cc", "newm.fanfox.net"],
            p: "/manga/",
            e: ".read-bottom-bar"
        },
        imgs: () => {
            if (fn.ge(".read-bottom-bar-block.control-right")) {
                const {
                    imagecount,
                    croot,
                    chapterid
                } = _unsafeWindow;
                let fetchNum = 0;
                let resArr = fn.arr(imagecount, (v, i) => {
                    let searchParams = new URLSearchParams({
                        cid: chapterid,
                        page: i + 1,
                        key: ""
                    });
                    let api = `${croot}chapterfun.ashx?${searchParams}`;
                    return fetch(api).then(res => res.text()).then(res => {
                        fn.showMsg(`${displayLanguage.str_06}(${fetchNum+=1}/${imagecount})`, 0);
                        let text = fn.run(res.slice(4));
                        let [, pix] = text.match(/pix="([^"]+)/);
                        let [, pvalue] = text.match(/pvalue=([^;]+)/);
                        pvalue = JSON.parse(pvalue);
                        return pix + pvalue[0];
                    });
                });
                return Promise.all(resArr);
            } else {
                return fn.gae(".read-img-bar img");
            }
        },
        button: [4, "24%"],
        insertImg: [".read-img-bar", 2],
        insertImgAF: (parent) => {
            fn.run("jQuery('.read-img-bar').off();")
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 5);
            }
        },
        next: "//a[div[p[text()='Next Chapter']]][not(starts-with(@href,'java'))]",
        prev: "//a[div[p[text()='Last Chapter' or text()='Prev Chapter']]][not(starts-with(@href,'java'))]",
        customTitle: () => fn.ge("meta[name='og:title']")?.content?.split(" - ")[1]?.replace(/Read | Online/g, ""),
        css: "#FullPictureLoadOptionsButtonParentDiv{margin-top:50px;}",
        hide: "div:has(>[id^=mc])",
        category: "comic"
    }, {
        name: "Komikcast",
        host: ["komikcast.cz"],
        url: {
            h: "komikcast",
            p: "/chapter/"
        },
        imgs: ".main-reading-area img",
        button: [4],
        insertImg: [".main-reading-area", 2],
        endColor: "white",
        autoDownload: [0],
        next: ".nextprev>a[rel=next]",
        prev: ".nextprev>a[rel=prev]",
        customTitle: ".chapter_headpost>h1",
        hide: "center:has(>div):has(a)",
        category: "comic"
    }, {
        name: "Sen Manga",
        url: {
            h: "raw.senmanga.com",
            p: /^\/[\w-]+\/\d+$/
        },
        imgs: () => {
            let links = [fn.url];
            let [pl] = fn.gae(".page-list");
            let ps = fn.gae(".page-list option", pl).length;
            if (ps > 1) {
                links = fn.arr(ps, (v, i) => i == 0 ? fn.url : fn.url + "/" + (i + 1));
            }
            return fn.getImgA(".picture", links);
        },
        button: [4],
        insertImg: [".reader", 2],
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 4);
            }
            fn.remove(".pager>.viewer,.nav-page");
        },
        autoDownload: [0],
        next: () => {
            let next = fn.ge(".custom-select option[selected]")?.previousElementSibling;
            if (next) {
                return fn.url.replace(/\d+$/, next.value);
            } else {
                return null;
            }
        },
        prev: 1,
        customTitle: () => fn.title(" - Page 1 / Raw | Sen Manga"),
        hide: "h2:has(>br)",
        category: "comic"
    }, {
        name: "ReadComicOnline",
        host: ["readcomiconline.li"],
        url: {
            h: "readcomiconline.li",
            p: /^\/Comic\/[\w-]+\/(Issue|Full|Vol)/i,
            d: "pc"
        },
        init: async () => {
            await fn.waitEle(["//script[contains(text(),'SetImage')]", "#divImage img"]);
            fn.clearAllTimer();
            fn.createImgBox("#divImage", 1);
        },
        imgs: () => {
            let code = fn.gst("currImage");
            let [keyText] = code.match(/\w+\(_\w+\[currImage\]\)/i);
            let [fnKey] = keyText.match(/^\w+/i);
            let [, arrKey] = keyText.match(/\((\w+)/i);
            let srcArr = _unsafeWindow[arrKey].map(e => _unsafeWindow[fnKey](e));
            return srcArr;
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#divImage,#divMsg,div:has(>div>iframe)"], 2
        ],
        endColor: "white",
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 1);
            }
        },
        autoDownload: [0],
        next: () => {
            let id = new URLSearchParams(document.location.search).get("id");
            let cOption = fn.gae("#selectEpisode>option").find(e => e.value.endsWith(id));
            let next = cOption?.nextElementSibling;
            if (next) {
                let arr = fn.url.split("/");
                arr[arr.length - 1] = next.value;
                return arr.join("/");
            } else {
                return null;
            }
        },
        prev: 1,
        customTitle: () => fn.title(/ - Read.+$/),
        fancybox: {
            blacklist: 1
        },
        gallery: 1,
        category: "comic"
    }, {
        name: "ReadComicOnline M",
        host: ["readcomiconline.li"],
        url: {
            h: "readcomiconline.li",
            p: /^\/Comic\/[\w-]+\/(Issue|Full|Vol)/i,
            d: "m"
        },
        init: async () => {
            await fn.waitEle("#divImage img");
            fn.clearAllTimer();
            fn.createImgBox("#divImage", 1);
        },
        imgs: () => {
            let code = fn.gst("currImage");
            let [, arrKey] = code.match(/(\w+)\[currImage\]/);
            return _unsafeWindow[arrKey];
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#divImage,#imgLoader"], 2
        ],
        endColor: "white",
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 1);
            }
        },
        autoDownload: [0],
        next: () => {
            let id = new URLSearchParams(document.location.search).get("id");
            let cOption = fn.gae(".selectEpisode>option").find(e => e.value.endsWith(id));
            let next = cOption?.nextElementSibling;
            if (next) {
                let arr = fn.url.split("/");
                arr[arr.length - 1] = next.value;
                return arr.join("/");
            } else {
                return null;
            }
        },
        prev: 1,
        customTitle: () => fn.title(/ - Read.+$/),
        fancybox: {
            blacklist: 1
        },
        category: "comic"
    }, {
        name: "TCB Scans",
        url: {
            h: "tcbscans.me",
            p: "/chapters/"
        },
        imgs: ".items-center>picture>img",
        button: [4],
        insertImg: [".items-center:has(>picture)", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[contains(text(),'Next')]",
        prev: "//a[contains(text(),'Prev')]",
        customTitle: ".container h1",
        category: "comic"
    }, {
        name: "NiAdd",
        url: {
            e: ["//script[contains(text(),'NiaddChpPageCtrl')]"],
            p: "/statuses/"
        },
        imgs: () => _unsafeWindow.NiaddChpPageCtrl.options.all_imgs_url,
        button: [4],
        insertImg: ["#viewer", 2],
        endColor: "white",
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 5);
            }
        },
        autoDownload: [0],
        next: () => {
            let url = _unsafeWindow.NiaddChpPageCtrl.options.next_chp_url;
            if (url === "https://www.niadd.com/") {
                return null;
            } else {
                return url;
            }
        },
        prev: 1,
        customTitle: () => fn.gt(".title>a:last-child") + " - " + fn.gt(".title>a"),
        hide: ".ads_margin,center:has(>script),.mangaread-pagenav>select~*,.site-content>footer",
        category: "comic"
    }, {
        name: "NiAdd",
        link: "https://niadd.com/original/10070490/chapters.html",
        url: {
            h: "niadd.com",
            p: "/chapter/",
            e: ["#viewer", ".pic_box", ".tool", "img[id^='manga_pic']", ".manga-name"]
        },
        imgs: () => {
            let max = fn.gt(".tool>a").match(/\d+/g).at(-1);
            let links = fn.arr(max, (v, i) => i == 0 ? fn.url : fn.url.replace(/\/$/, "") + `-${i + 1}.html`);
            return fn.getImgA("img[id^='manga_pic']", links);
        },
        button: [4],
        insertImg: [".pic_box", 2],
        insertImgAF: (parent) => {
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 5);
            }
        },
        endColor: "white",
        autoDownload: [0],
        next: () => {
            let select = document.querySelector(".mangaread-pagenav>select");
            let chapters = [...select.querySelectorAll("option")];
            let nextUrl = null;
            chapters.some((e, i, a) => {
                if (e.value == fn.url) {
                    if (a[i - 1] === undefined) {
                        nextUrl = null;
                    } else {
                        nextUrl = a[i - 1].value;
                    }
                    return true;
                } else {
                    return false;
                }
            });
            return nextUrl;
        },
        prev: 1,
        customTitle: () => fn.dt({
            s: ".manga-name",
            d: [
                /[\s\/]$/,
                "(mitaku.net) "
            ]
        }),
        hide: ".option-item~*",
        category: "comic"
    }, {
        name: "MangaHasu",
        url: {
            h: "mangahasu.me",
            e: "#loadchapter"
        },
        imgs: ".img-chapter .img img",
        button: [4],
        insertImg: [".img-chapter .img", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='Next']",
        prec: "//a[text()='Prev']",
        customTitle: ".div-title-chapter h1",
        category: "comic"
    }, {
        name: "MangaFire",
        url: {
            h: "mangafire.to",
            p: "/read/",
            d: "pc"
        },
        init: () => (siteJson = JSON.parse(document.querySelector('#syncData').innerText)),
        imgs: () => {
            let [, comic_id, chapter_number] = new URL(document.URL).pathname.match(/(\w+)\/\w+\/chapter-(.+)$/i);
            let headers = new Headers({
                "Accept": "application/json, text/javascript, */*; q=0.01",
                "X-Requested-With": "XMLHttpRequest",
            });
            return fetch(`/ajax/read/${comic_id}/chapter/en`, {
                headers
            }).then(res => res.json()).then(json => {
                let tempDom = new DOMParser().parseFromString(json.result.html, "text/html");
                let chapter_id = [...tempDom.querySelectorAll("li a")].find(a => a.dataset.number == chapter_number).dataset.id;
                return fetch(`/ajax/read/chapter/${chapter_id}`, {
                    headers
                }).then(res => res.json()).then(json => json.result.images.map(arr => arr.find(e => e.startsWith("http"))));
            });
        },
        capture: () => _this.imgs(),
        autoDownload: [0],
        next: () => !!siteJson.next_chapter_url ? new URL(siteJson.next_chapter_url).pathname : null,
        customTitle: () => fn.title(/ - Read Manga Online| \| Read Online on MangaFire|Manga, /g),
        category: "comic"
    }, {
        name: "Top Manhua",
        url: {
            h: ["manhuatop.org", "topmanhua.fan"],
            p: "/chapter"
        },
        imgs: ".reading-content img",
        button: [4],
        insertImg: [".reading-content", 2],
        endColor: "white",
        autoDownload: [0],
        next: "a.next_page",
        prev: "a.prev_page",
        customTitle: "#chapter-heading",
        category: "comic"
    }, {
        name: "嗨皮漫畫閱讀",
        enable: 0,
        url: {
            h: "m.happymh.com",
            p: "/mangaread/"
        },
        exclude: ".captcha-area",
        fetchJson: (url = siteUrl) => {
            let [, , mangaCode, id] = new URL(url).pathname.split("/");
            let api = `/v2.0/apis/manga/reading?code=${mangaCode}&cid=${id}&v=v3.1613134`;
            return fetch(api, {
                "headers": {
                    "accept": "application/json, text/plain, */*",
                    "x-requested-id": new Date().getTime(),
                    "x-requested-with": "XMLHttpRequest"
                }
            }).then(res => res.json());
        },
        init: async () => {
            let json = await _this.fetchJson();
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
            fn.picPreload(json.data.scans.map(e => e.url), json.data.manga_name + " - " + json.data.chapter_name);
            if (await fn.waitEle("#page-area")) {
                new IntersectionObserver((entries, observer) => {
                    if (entries[0].isIntersecting) {
                        observer.unobserve(entries[0].target);
                        let f = ge("footer>article");
                        let item = ge("footer>article>div:nth-child(2)");
                        item.querySelectorAll("a").forEach(a => a.classList.add("MuiButton-containedPrimary"));
                        let p = gx("//a[span[text()='上一话' or text()='上一話'] and contains(@href,'/mangaread/')]");
                        if (p) p.classList.add("MuiButton-containedPrimary");
                        let n = gx("//a[span[text()='下一话' or text()='下一話'] and contains(@href,'/readMore/')]");
                        if (n) {
                            n.classList.remove("MuiButton-containedPrimary");
                            n.firstChild.innerText = "^_^感谢您的阅读~已经没有下一话了哦~";
                        }
                    }
                }).observe(ge('#page-area'));
            }
            await fn.waitEle("footer a[href^='/mangaread/'],footer a[href^='/readMore/']");
        },
        imgs: () => siteJson.status == 0 ? siteJson.data.scans.map(e => e.url) : [],
        referrerpolicy: "origin",
        button: [4],
        insertImg: ["//article[div[contains(@id,'imageLoader')]]", 3],
        autoDownload: [0],
        next: "//a[span[text()='下一話' or text()='下一话']][contains(@href,'/mangaread/')]",
        prev: "//a[span[text()='上一話' or text()='上一话']]",
        customTitle: () => siteJson.data.manga_name + " - " + siteJson.data.chapter_name,
        preloadNext: async (nextDoc, obj) => {
            let json = await obj.fetchJson(nextLink);
            json.status == 0 ? fn.picPreload(json.data.scans.map(e => e.url), json.data.manga_name + " - " + json.data.chapter_name, "next") : debug("預讀下一頁失敗");
        },
        css: "footer>article>div{padding: 0.5rem 0 !important}",
        category: "comic"
    }, {
        name: "嗨皮漫畫展開目錄",
        reg: /^https?:\/\/m\.happymh\.com\/manga\//,
        enable: 0,
        icon: 0,
        key: 0,
        init: () => {
            window.addEventListener("load", async () => {
                await delay(1000);
                if (fn.ge("//div[contains(text(),'给本王显示全部章节')]")) {
                    EClick("#expandButton");
                }
            });
        },
        category: "comic"
    }, {
        name: "嗨皮漫畫,連結新分頁開啟",
        reg: /^https?:\/\/m\.happymh\.com\//,
        enable: 0,
        icon: 0,
        key: 0,
        openInNewTab: ".home-banner a:not([target=_blank]),.manga-rank a:not([target=_blank]),.manga-cover a:not([target=_blank])",
        category: "comic"
    }, {
        name: "COLAMANHUA", //方向鍵上一章下一章、反反偵錯,下載需先手動觸發全部載入圖片,圖址如為blob函式會使用到canvas需要繪製過程會有點卡。
        enable: 1,
        url: {
            h: "www.colamanga.com",
            p: /^\/manga-.+\.html$/
        },
        init: () => {
            fn.clearAllTimer(1);
            if (autoScrollAllElement === 1) _this.scrollEle();
        },
        imgs: () => fn.ge(".mh_comicpic img[src^=blob]") ? fn.imgBlobUrlArr(".mh_comicpic img[src^=blob]") : fn.gae(".mh_comicpic img[src]"),
        //scrollEle: [".mh_comicpic img", 600],
        scrollEle: () => fn.aotoScrollEles(".mh_comicpic", (ele) => isEle(fn.ge("img[src]", ele)), 10000),
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => fn.title(" COLAMANGA", 1),
        css: ".mh_wrap{width:100%!important;min-width:100%!important}",
        category: "comic"
    }, {
        name: "COLAMANHUA 目錄連結新分頁開啟",
        reg: /^https?:\/\/www\.colamanga\.com\/manga-\w+\/$/,
        openInNewTab: ".all_data_list a:not([target=_blank])",
        category: "none"
    }, {
        name: "8Comic無限動漫",
        host: ["www.8comic.com"],
        enable: 1,
        url: {
            t: "無限動漫",
            p: "/online/",
            i: 0
        },
        frameCode: `
if ("xx" in window) {
    const {
        su,
        ti,
        nn,
        mm,
        xx
    } = window;
    const getSrc = (code) => {
        const a = code.substring(15);
        const b = window[code.substring(0, 5)];
        const c = window[code.substring(5, 10)];
        const d = window[code.substring(10, 15)];
        const src = "https://img" + su(b, 0, 1) + ".8comic.com/" + su(b, 1, 1) + "/" + ti + "/" + c + "/" + nn(a) + "_" + su(d, mm(a), 3) + ".jpg";
        return src;
    };
    const html = decodeURIComponent(xx);
    const codes = html.matchAll(/\\ss="([^"]+)"/g);
    const srcs = [...codes].map(([, code]) => {
        if (code.startsWith("//")) {
            return window.location.protocol + code;
        } else if (code.length >= 16 && code.length <= 18 && /\\d{1,3}/.test(code.substring(15))) {
            return getSrc(code);
        } else {
            return null;
        }
    });
    window.newImgs = srcs;
    const url = reurl("ch", ni);
    if (url == document.URL) {
        window.nextLink = null;
    } else {
        window.nextLink = url;
    }
}
        `,
        init: async () => {
            await fn.waitVar(["xx", "su", "ti", "nn", "mm"]);
            await fn.waitEle("#comics-pics img");
            fn.script(_this.frameCode, 0, 1);
            fn.createImgBox(".pinch-zoom-container", 2);
        },
        imgs: () => _unsafeWindow.newImgs,
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".pinch-zoom-container"], 2
        ],
        autoDownload: [0],
        next: () => _unsafeWindow.nextLink,
        prev: "#prevvol",
        customTitle: () => fn.dt({
            s: "#pt"
        }),
        preloadNext: () => {
            if (!!_unsafeWindow.nextLink) {
                fn.iframe(_unsafeWindow.nextLink, {
                    waitVar: ["xx", "su", "ti", "nn", "mm"],
                    cb: async (dom, frame) => {
                        fn.script(_this.frameCode, 0, 1, dom);
                        fn.picPreload(frame.newImgs, fn.dt({
                            t: fn.gt("#pt", 1, dom)
                        }), "next");
                    }
                });
            }
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "8Comic無限動漫 自動翻頁",
        url: {
            t: "無限動漫",
            p: "/online/",
            i: 1
        },
        frameCode: `
if ("xx" in window) {
    const {
        su,
        ti,
        nn,
        mm,
        xx
    } = window;
    const getSrc = (code) => {
        const a = code.substring(15);
        const b = window[code.substring(0, 5)];
        const c = window[code.substring(5, 10)];
        const d = window[code.substring(10, 15)];
        const src = "https://img" + su(b, 0, 1) + ".8comic.com/" + su(b, 1, 1) + "/" + ti + "/" + c + "/" + nn(a) + "_" + su(d, mm(a), 3) + ".jpg";
        return src;
    };
    const html = decodeURIComponent(xx);
    const codes = html.matchAll(/\\ss="([^"]+)"/g);
    const srcs = [...codes].map(([, code]) => {
        if (code.startsWith("//")) {
            return window.location.protocol + code;
        } else if (code.length >= 16 && code.length <= 18 && /\\d{1,3}/.test(code.substring(15))) {
            return getSrc(code);
        } else {
            return null;
        }
    });
    window.newImgs = srcs;
    const url = reurl("ch", ni);
    if (url == document.URL) {
        window.nextLink = null;
    } else {
        window.nextLink = url;
    }
}
        `,
        init: async () => {
            //console.log("window.xx",window.xx);
            await fn.waitVar(["xx", "su", "ti", "nn", "mm"]);
            await fn.waitEle("#comics-pics img");
            fn.script(_this.frameCode, 0, 1);
            let tE = fn.createImgBox(".pinch-zoom-container", 2);
            fn.remove(".pinch-zoom-container");
            let imgs = fn.createImgArray(frameWindow.newImgs);
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            mode: 1,
            waitEle: "#comics-pics img",
            ele: () => fn.createImgArray(frameWindow.newImgs),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: () => frameWindow.nextLink,
            title: (dom, frame) => {
                if (hasTouchEvent) {
                    return "第" + frame.ch + "集";
                } else {
                    return fn.dt({
                        t: fn.gt("#pt", 1, dom)
                    });
                }
            },
            re: "#pt",
            aF: () => (_unsafeWindow.ch = frameWindow.ch),
            preloadNextPage: () => {
                if (!!frameWindow.nextLink) {
                    fn.iframe(frameWindow.nextLink, {
                        waitVar: ["xx", "su", "ti", "nn", "mm"],
                        cb: async (dom, frame) => {
                            fn.script(_this.frameCode, 0, 1, dom);
                            fn.picPreload(frame.newImgs, _this.autoPager.title(dom, frame), "next");
                        }
                    });
                }
            }
        },
        category: "comic autoPager"
    }, {
        name: "Mangabz",
        enable: 1,
        url: {
            h: "mangabz.com",
            p: "/m",
            e: ".container",
            i: 0
        },
        init: () => fn.MangabzUI(),
        imgs: (msg = 1) => {
            if (msg == 1) fn.showMsg(displayLanguage.str_05, 0);
            const {
                MANGABZ_IMAGE_COUNT,
                MANGABZ_CURL,
                MANGABZ_CID,
                MANGABZ_MID,
                MANGABZ_VIEWSIGN_DT,
                MANGABZ_VIEWSIGN
            } = _unsafeWindow;
            let fetchNum = 0;
            let resArr = fn.arr(MANGABZ_IMAGE_COUNT, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: MANGABZ_CID,
                    page: i + 1,
                    key: "",
                    _cid: MANGABZ_CID,
                    _mid: MANGABZ_MID,
                    _dt: MANGABZ_VIEWSIGN_DT,
                    _sign: MANGABZ_VIEWSIGN
                });
                let apiUrl = `${MANGABZ_CURL}chapterimage.ashx?${searchParams}`;
                return fetch(apiUrl).then(res => res.text()).then(res => {
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_06}(${fetchNum+=1}/${MANGABZ_IMAGE_COUNT})`, 0);
                    return fn.run(res)[0];
                });
            });
            return Promise.all(resArr).then(arr => {
                if (msg == 1) fn.hideMsg();
                return arr;
            });
        },
        button: [4],
        insertImg: ["#cp_img", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[img[contains(@src,'xiayizhang')]][starts-with(@href,'/m')]",
        prev: "//a[img[contains(@src,'shangyizhang')]][starts-with(@href,'/m')]",
        customTitle: (dom = document) => fn.title("_", 2, dom).replace("漫畫", ""),
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("MANGABZ_IMAGE_COUNT", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(0), obj.customTitle(nextDoc), "next");
        },
        css: "body{overflow:unset!important}",
        hide: "a[href^='j']",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Mangabz 自動翻頁",
        url: {
            h: "mangabz.com",
            p: "/m",
            e: ".container",
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("MANGABZ_IMAGE_COUNT", dom);
            let [, imagesNum] = code.match(/MANGABZ_IMAGE_COUNT[\s\=]+(\d+)/);
            let [, chapterURL] = code.match(/MANGABZ_CURL[\s\="]+([^"]+)/);
            let [, cid] = code.match(/MANGABZ_CID[\s\=]+(\d+)/);
            let [, mid] = code.match(/MANGABZ_MID[\s\=]+(\d+)/);
            let dt = encodeURIComponent(code.match(/MANGABZ_VIEWSIGN_DT[\s\="]+([^"]+)/)[1]);
            let [, sing] = code.match(/MANGABZ_VIEWSIGN[\s\="]+([^"]+)/);
            let resArr = fn.arr(imagesNum, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: cid,
                    page: i + 1,
                    key: "",
                    _cid: cid,
                    _mid: mid,
                    _dt: dt,
                    _sign: sing
                });
                let api = `${chapterURL}chapterimage.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(text => {
                    let srcArr = fn.run(text);
                    return srcArr[0];
                });
            });
            return Promise.all(resArr);
        },
        getImgs: async (dom = document) => {
            let srcs = await _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.MangabzUI();
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getImgs().then(async imgs => {
                let tE = fn.ge("#cp_img");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#cp_img", 0],
            observer: "#cp_img>img",
            next: "//a[img[contains(@src,'xiayizhang')]][starts-with(@href,'/m')]",
            re: ".container",
            title: (dom) => {
                let code = fn.gst("MANGABZ_CTITLE", dom);
                let [, title] = code.match(/MANGABZ_CTITLE[\s\="]+([^"]+)/);
                return title;
            },
            preloadNextPage: 1
        },
        css: "body{overflow:unset!important}",
        hide: "a[href^='j']",
        category: "comic autoPager"
    }, {
        name: "Xmanhua",
        enable: 1,
        url: {
            h: "xmanhua.com",
            p: "/m",
            e: ".reader-bottom-page-list",
            i: 0
        },
        init: () => fn.XmanhuaUI(),
        imgs: (msg = 1) => {
            if (msg == 1) fn.showMsg(displayLanguage.str_05, 0);
            const {
                XMANHUA_IMAGE_COUNT,
                XMANHUA_CURL,
                XMANHUA_CID,
                XMANHUA_MID,
                XMANHUA_VIEWSIGN_DT,
                XMANHUA_VIEWSIGN
            } = _unsafeWindow;
            let fetchnUm = 0;
            let resArr = fn.arr(XMANHUA_IMAGE_COUNT, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: XMANHUA_CID,
                    page: i + 1,
                    key: "",
                    _cid: XMANHUA_CID,
                    _mid: XMANHUA_MID,
                    _dt: XMANHUA_VIEWSIGN_DT,
                    _sign: XMANHUA_VIEWSIGN
                });
                let apiUrl = `${XMANHUA_CURL}chapterimage.ashx?${searchParams}`;
                return fetch(apiUrl).then(res => res.text()).then(res => {
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_06}(${fetchnUm+=1}/${XMANHUA_IMAGE_COUNT})`, 0);
                    return fn.run(res)[0];
                });
            });
            return Promise.all(resArr).then(arr => {
                if (msg == 1) fn.hideMsg();
                return arr;
            });
        },
        button: [4],
        insertImg: ["#cp_img", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[img[contains(@src,'reader-bottom-right-2')]][starts-with(@href,'/m')]",
        prev: "//a[img[contains(@src,'reader-bottom-right-1')]][starts-with(@href,'/m')]",
        customTitle: (dom = document) => fn.title("_", 2, dom).replace("漫畫", ""),
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("XMANHUA_IMAGE_COUNT", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(0), obj.customTitle(nextDoc), "next");
        },
        css: ".reader-img-con{padding:64px 0 50px !important;}",
        hide: ".relative>a",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Xmanhua 自動翻頁",
        url: {
            h: "xmanhua.com",
            p: "/m",
            e: ".reader-bottom-page-list",
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("XMANHUA_IMAGE_COUNT", dom);
            let [, imagesNum] = code.match(/XMANHUA_IMAGE_COUNT[\s\=]+(\d+)/);
            let [, chapterURL] = code.match(/XMANHUA_CURL[\s\="]+([^"]+)/);
            let [, cid] = code.match(/XMANHUA_CID[\s\=]+(\d+)/);
            let [, mid] = code.match(/XMANHUA_MID[\s\=]+(\d+)/);
            let dt = encodeURIComponent(code.match(/XMANHUA_VIEWSIGN_DT[\s\="]+([^"]+)/)[1]);
            let [, sing] = code.match(/XMANHUA_VIEWSIGN[\s\="]+([^"]+)/);
            let resArr = fn.arr(imagesNum, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: cid,
                    page: i + 1,
                    key: "",
                    _cid: cid,
                    _mid: mid,
                    _dt: dt,
                    _sign: sing
                });
                let api = `${chapterURL}chapterimage.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(text => {
                    let srcArr = fn.run(text);
                    return srcArr[0];
                });
            });
            return Promise.all(resArr);
        },
        getImgs: async (dom = document) => {
            let srcs = await _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.XmanhuaUI();
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getImgs().then(async imgs => {
                let tE = fn.ge("#cp_img");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#cp_img", 0],
            observer: "#cp_img>img",
            next: "//a[img[contains(@src,'reader-bottom-right-2')]][starts-with(@href,'/m')]",
            re: ".container",
            title: (dom) => {
                let code = fn.gst("XMANHUA_CTITLE", dom);
                let [, title] = code.match(/XMANHUA_CTITLE[\s\="]+([^"]+)/);
                return title;
            },
            preloadNextPage: 1
        },
        css: ".reader-img-con{padding:64px 0 50px !important;}",
        hide: ".relative>a",
        category: "comic autoPager"
    }, {
        name: "DM5/極速 分頁模式",
        host: ["www.dm5.com", "m.dm5.com", "www.dm5.cn", "m.dm5.cn", "en.dm5.com", "cnc.dm5.com", "hk.dm5.com", "www.1kkk.com", "m.1kkk.com", "tel.1kkk.com", "en.1kkk.com", "cnc.1kkk.com", "hk.1kkk.com"],
        enable: 1,
        url: {
            h: [/dm5/, /1kkk/],
            p: /^\/(m|ch|vol|other)/,
            e: "#chapterpager",
            i: 0
        },
        imgs: (msg = 1) => {
            if (msg == 1) fn.showMsg(displayLanguage.str_05, 0);
            const {
                DM5_IMAGE_COUNT,
                DM5_CURL,
                DM5_CID,
                DM5_MID,
                DM5_VIEWSIGN_DT,
                DM5_VIEWSIGN
            } = _unsafeWindow;
            let fetchNum = 0;
            let keyE = fn.ge("#dm5_key");
            let key = keyE.value;
            let resArr = fn.arr(DM5_IMAGE_COUNT, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: DM5_CID,
                    page: i + 1,
                    key: key,
                    language: 1,
                    gtk: 6,
                    _cid: DM5_CID,
                    _mid: DM5_MID,
                    _dt: DM5_VIEWSIGN_DT,
                    _sign: DM5_VIEWSIGN
                });
                let api = `${DM5_CURL}chapterfun.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(res => {
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_06}(${fetchNum+=1}/${DM5_IMAGE_COUNT})`, 0);
                    return fn.run(res)[0];
                });
            });
            return Promise.all(resArr).then(arr => {
                if (msg == 1) fn.hideMsg();
                return arr;
            });
        },
        button: [4],
        insertImg: ["#cp_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.title("_", 2, dom),
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("DM5_IMAGE_COUNT", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(0), obj.customTitle(nextDoc), "next");
        },
        topButton: true,
        css: "body{overflow:unset!important}",
        hide: ".view-ad,.view-mask",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "DM5/極速 分頁模式 自動翻頁",
        url: {
            h: [/dm5/, /1kkk/],
            p: /^\/(m|ch|vol|other)/,
            e: "#chapterpager",
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("DM5_IMAGE_COUNT", dom);
            let [, imagesNum] = code.match(/DM5_IMAGE_COUNT[\s\=]+(\d+)/);
            let [, chapterURL] = code.match(/DM5_CURL[\s\="]+([^"]+)/);
            let [, cid] = code.match(/DM5_CID[\s\=]+(\d+)/);
            let [, mid] = code.match(/DM5_MID[\s\=]+(\d+)/);
            let [, dt] = code.match(/DM5_VIEWSIGN_DT[\s\="]+([^"]+)/);
            let [, sing] = code.match(/DM5_VIEWSIGN[\s\="]+([^"]+)/);
            let keyE = fn.ge("#dm5_key");
            let key = keyE.value;
            let resArr = fn.arr(imagesNum, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: cid,
                    page: i + 1,
                    key: key,
                    language: 1,
                    gtk: 6,
                    _cid: cid,
                    _mid: mid,
                    _dt: dt,
                    _sign: sing
                });
                let api = `${chapterURL}chapterfun.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(text => {
                    let srcArr = fn.run(text);
                    return srcArr[0];
                });
            });
            return Promise.all(resArr)
        },
        getImgs: async (dom = document) => {
            let srcs = await _this.getSrcs(dom);
            return fn.createImgArray(srcs)
        },
        init: async () => {
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getImgs().then(async imgs => {
                let tE = fn.ge("#cp_img");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#cp_img", 0],
            observer: "#cp_img>img",
            next: "//a[text()='下一章']",
            re: ".active.right-arrow,.view-paging",
            title: (dom) => fn.gt(".title", 1, dom).replace("首页 ", "").replace(/\s+/g, " ").trim(),
            hide: ".view-comment",
            preloadNextPage: 1
        },
        css: "body{overflow:unset!important}",
        hide: "a[href^='javascript:Show'],.chapterpager,.view-ad,.view-mask",
        category: "comic autoPager"
    }, {
        name: "DM5/極速 條漫模式",
        enable: 1,
        url: {
            h: [/dm5/, /1kkk/],
            p: /^\/(m|ch|vol|other)/,
            i: 0
        },
        imgs: "#barChapter>img",
        button: [4],
        insertImg: ["#barChapter", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.title("_", 2, dom),
        preloadNext: (nextDoc, obj) => fn.picPreload(fn.getImgSrcArr(obj.imgs, nextDoc), obj.customTitle(nextDoc), "next"),
        css: "body{overflow:unset!important}",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "DM5/極速 條漫模式 自動翻頁",
        url: {
            h: [/dm5/, /1kkk/],
            p: /^\/(m|ch|vol|other)/,
            e: "#barChapter",
            i: 1
        },
        getSrcs: (dom) => fn.gae("img.load-src[data-src]", dom).map(e => e.dataset.src),
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge("#barChapter");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#barChapter", 0],
            observer: "#barChapter>img",
            next: "//a[text()='下一章']",
            re: ".view-paging",
            title: (dom) => fn.gt(".title", 1, dom).replace("首页 ", "").replace(/\s+/, " ").trim(),
            hide: ".view-comment",
            preloadNextPage: 1
        },
        css: "body{overflow:unset!important}",
        category: "comic autoPager"
    }, {
        name: "YYMANGA",
        enable: 1,
        url: {
            h: "yymanhua.com",
            p: "/m",
            e: ".reader-bottom-page-list",
            i: 0
        },
        init: () => fn.XmanhuaUI(),
        imgs: (msg = 1) => {
            if (msg == 1) fn.showMsg(displayLanguage.str_05, 0);
            const {
                YYMANHUA_IMAGE_COUNT,
                YYMANHUA_CURL,
                YYMANHUA_CID,
                YYMANHUA_MID,
                YYMANHUA_VIEWSIGN_DT,
                YYMANHUA_VIEWSIGN
            } = _unsafeWindow;
            let fetchnUm = 0;
            let resArr = fn.arr(YYMANHUA_IMAGE_COUNT, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: YYMANHUA_CID,
                    page: i + 1,
                    key: "",
                    _cid: YYMANHUA_CID,
                    _mid: YYMANHUA_MID,
                    _dt: YYMANHUA_VIEWSIGN_DT,
                    _sign: YYMANHUA_VIEWSIGN
                });
                let apiUrl = `${YYMANHUA_CURL}chapterimage.ashx?${searchParams}`;
                return fetch(apiUrl).then(res => res.text()).then(res => {
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_06}(${fetchnUm+=1}/${YYMANHUA_IMAGE_COUNT})`, 0);
                    return fn.run(res)[0];
                });
            });
            return Promise.all(resArr).then(arr => {
                if (msg == 1) fn.hideMsg();
                return arr;
            });
        },
        button: [4],
        insertImg: ["#cp_img", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[img[contains(@src,'reader-bottom-right-2')]][starts-with(@href,'/m')]",
        prev: "//a[img[contains(@src,'reader-bottom-right-1')]][starts-with(@href,'/m')]",
        customTitle: (dom = document) => fn.title("_", 2, dom).replace("漫畫", ""),
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("YYMANHUA_IMAGE_COUNT", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(0), obj.customTitle(nextDoc), "next");
        },
        css: ".reader-img-con{padding:64px 0 50px !important;}",
        hide: ".relative>a",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "YYMANGA 自動翻頁",
        url: {
            h: "yymanhua.com",
            p: "/m",
            e: ".reader-bottom-page-list",
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("YYMANHUA_IMAGE_COUNT", dom);
            let [, imagesNum] = code.match(/YYMANHUA_IMAGE_COUNT[\s\=]+(\d+)/);
            let [, chapterURL] = code.match(/YYMANHUA_CURL[\s\="]+([^"]+)/);
            let [, cid] = code.match(/YYMANHUA_CID[\s\=]+(\d+)/);
            let [, mid] = code.match(/YYMANHUA_MID[\s\=]+(\d+)/);
            let dt = encodeURIComponent(code.match(/YYMANHUA_VIEWSIGN_DT[\s\="]+([^"]+)/)[1]);
            let [, sing] = code.match(/YYMANHUA_VIEWSIGN[\s\="]+([^"]+)/);
            let resArr = fn.arr(imagesNum, (v, i) => {
                let searchParams = new URLSearchParams({
                    cid: cid,
                    page: i + 1,
                    key: "",
                    _cid: cid,
                    _mid: mid,
                    _dt: dt,
                    _sign: sing
                });
                let api = `${chapterURL}chapterimage.ashx?${searchParams}`;
                return fetch(api).then(res => res.text()).then(text => {
                    let srcArr = fn.run(text);
                    return srcArr[0];
                });
            });
            return Promise.all(resArr);
        },
        getImgs: async (dom = document) => {
            let srcs = await _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.XmanhuaUI();
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getImgs().then(async imgs => {
                let tE = fn.ge("#cp_img");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#cp_img", 0],
            observer: "#cp_img>img",
            next: "//a[img[contains(@src,'reader-bottom-right-2')]][starts-with(@href,'/m')]",
            re: ".container",
            title: (dom) => {
                let code = fn.gst("YYMANHUA_CTITLE", dom);
                let [, title] = code.match(/YYMANHUA_CTITLE[\s\="]+([^"]+)/);
                return title;
            },
            preloadNextPage: 1
        },
        css: ".reader-img-con{padding:64px 0 50px !important;}",
        hide: ".relative>a",
        category: "comic autoPager"
    }, {
        name: "DM5/極速/Mangabz/Xmanhua/yymanhua/漫画人/漫本 手機版",
        host: ["www.dm5.com", "m.dm5.com", "www.dm5.cn", "m.dm5.cn", "en.dm5.com", "cnc.dm5.com", "hk.dm5.com", "www.1kkk.com", "m.1kkk.com", "tel.1kkk.com", "en.1kkk.com", "cnc.1kkk.com", "hk.1kkk.com", "www.mangabz.com", "mangabz.com", "www.xmanhua.com", "xmanhua.com", "www.yymanhua.com", "yymanhua.com", "www.manben.com", "www.manhuaren.com"],
        enable: 1,
        url: {
            h: /dm5|1kkk|mangabz|xmanhua|yymanhua|manhuaren|manben/,
            p: /^\/(m|ch|vol|other)?[-_0-9]+\//,
            e: "//script[contains(text(),'newImgs')]",
            i: 0
        },
        delay: 300,
        init: () => {
            if (fn.gae(".view-bottom-bar>li").length == 4) {
                fn.css(".view-bottom-bar>li:nth-child(n+2):nth-child(-n+3){display:none!important}.view-bottom-bar li{width:50%!important}");
            }
            let b = fn.ge("body.viewbody");
            if (fn.lh.includes("mangabz") && b) {
                b.innerHTML = b.innerHTML.replace("<!--", "").replace("-->", "");
                fn.ge(".top-bar-tool").removeAttribute("style");
                fn.ge(".bottom-bar").removeAttribute("style");
                const showtoolbar = () => document.body.classList.toggle("toolbar");
                document.addEventListener('click', showtoolbar);
            }
        },
        imgs: () => _unsafeWindow.newImgs,
        button: [4],
        insertImg: ["#cp_img,.main_img,#comicContain,.comic-list", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//a[text()='下一章'] | //a[img[@alt='下一章']]");
            if (next) return /pushHistory/.test(next.href) ? location.origin + next.href.split("'")[1] : next.href;
            return null;
        },
        prev: "//a[text()='上一章'] | //a[img[@alt='上一章']]",
        customTitle: (dom = document) => {
            let host = fn.lh;
            if (/dm5|manhuaren|1kkk|mangabz|xmanhua|yymanhua/.test(host) && !/sixmanhua/.test(host)) {
                return fn.title("_", 2, dom);
            } else if (/sixmanhua/.test(host)) {
                return fn.title("_", 3, dom);
            } else if (/manben/.test(host)) {
                if (fn.ge("#comicTitle")) {
                    return fn.gt("#chapter", 1, dom) + " " + fn.gt(".title-comicHeading", 1, dom);
                } else {
                    return fn.title(" ", 2, dom);
                }
            }
        },
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("newImgs", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "DM5/極速/Mangabz/Xmanhua/yymanhua/漫画人/漫本 手機版 自動翻頁",
        url: {
            h: /dm5|1kkk|mangabz|xmanhua|yymanhua|manhuaren|manben/,
            p: /^\/(m|ch|vol|other)?[-_0-9]+\//,
            e: "//script[contains(text(),'newImgs')]",
            i: 1
        },
        delay: 300,
        getSrcs: (dom) => {
            let code = fn.gst("newImgs", dom);
            code = code.replace("eval", "");
            let text = fn.run(code);
            let arrText = text.replace(/var newImgs=|;$/g, "");
            let srcs = fn.run(arrText);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge("#cp_img");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            if (fn.gae(".view-bottom-bar>li").length == 4) {
                fn.css(".view-bottom-bar>li:nth-child(n+2):nth-child(-n+3){display:none!important}.view-bottom-bar li{width:50%!important}");
            }
            let b = fn.ge("body.viewbody");
            if (fn.lh.includes("mangabz") && b) {
                b.innerHTML = b.innerHTML.replace("<!--", "").replace("-->", "");
                fn.ge(".top-bar-tool").removeAttribute("style");
                fn.ge(".bottom-bar").removeAttribute("style");
                const showtoolbar = () => document.body.classList.toggle("toolbar");
                document.addEventListener('click', showtoolbar);
            }
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#cp_img", 0],
            observer: "#cp_img>img",
            next: (dom) => {
                let next = fn.ge("//a[text()='下一章'] | //a[img[@alt='下一章']]", dom, dom);
                if (next) {
                    let url = /pushHistory/.test(next.href) ? fn.lo + next.href.split("'")[1] : next.href;
                    if (!/-end/.test(url)) {
                        return url;
                    }
                }
                return null;
            },
            re: ".view-fix-top-bar-title,.top-title,.view-bottom-bar,.view-fix-bottom-bar,.bottom-bar-tool",
            title: (dom) => {
                let tt = fn.gt(".top-title", 1, dom);
                if (fn.lh.includes("xmanhua") && tt) {
                    return tt.replaceAll("?", "-").replace("XManhua-", "");
                } else if (fn.lh.includes("mangabz") && tt) {
                    return tt.replaceAll("?", "-").replace("Mangabz-", "");
                } else if (fn.lh.includes("yymanhua") && tt) {
                    return tt.replaceAll("?", "-").replace("YYManhua-", "");
                }
                return dom.title.replace(/,?_在线漫画.+/, "").replace("漫画", "").replace(/^[^_]+_/, "");
            },
            bF: (dom) => {
                let b = fn.ge("body.viewbody", dom);
                if (fn.lh.includes("mangabz") && b) {
                    b.innerHTML = b.innerHTML.replace("<!--", "").replace("-->", "");
                }
            },
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "再漫画",
        url: {
            h: "manhua.zaimanhua.com"
        },
        SPA: () => document.URL.includes("/view/"),
        observerURL: true,
        getData: async () => {
            await fn.wait((dom, win) => win?.__NUXT__?.data?.getChapters && win?.__NUXT__?.data?.getCationDetails);
            let {
                chapter_order,
                title: chapterName,
                page_url: srcs
            } = _unsafeWindow.__NUXT__.data.getChapters.data.chapterInfo;
            let {
                title: comicName,
                chapterList
            } = _unsafeWindow.__NUXT__.data.getCationDetails.data.comicInfo;
            siteJson = {
                srcs,
                chapter_order,
                comicName,
                chapterName,
                chapterList: chapterList[0].data.sort((a, b) => a.chapter_order - b.chapter_order)
            }
            debug("\n此頁JSON資料\n", siteJson);
        },
        init: async () => {
            if (_this.SPA()) await _this.getData();
            fn.addMutationObserver(() => {
                if (!_this.SPA() || isOpenOptionsUI || isOpenGallery || isOpenFancybox || isOpenFilter || isDownloading) return;
                setTimeout(async () => {
                    await _this.getData();
                    nextLink = _this.next();
                    customTitle = siteJson.comicName + " - " + siteJson.chapterName;
                }, 200);
            });
        },
        imgs: () => siteJson.srcs,
        autoDownload: [0],
        next: () => {
            if (!_this.SPA()) return null;
            let next = null;
            siteJson.chapterList.some((c, i, a) => {
                if (c.chapter_order == siteJson.chapter_order) {
                    if (a[i + 1] !== undefined) {
                        next = document.URL.replace(/\d+$/, "") + a[i + 1].chapter_id;
                    }
                    return true;
                }
            });
            return next;
        },
        prev: 1,
        customTitle: () => siteJson.comicName + " - " + siteJson.chapterName,
        category: "comic"
    }, {
        name: "动漫之家",
        url: {
            h: "www.idmzj.com"
        },
        SPA: () => document.URL.includes("/view/"),
        observerURL: true,
        getData: async () => {
            await fn.wait((dom, win) => win?.__NUXT__?.data?.getchapters && win?.__NUXT__?.data?.getcationDeatils);
            let {
                chapter_order,
                title: chapterName,
                page_url: srcs
            } = _unsafeWindow.__NUXT__.data.getchapters.data.chapterInfo;
            let {
                title: comicName,
                chapterList
            } = _unsafeWindow.__NUXT__.data.getcationDeatils.comicInfo;
            siteJson = {
                srcs,
                chapter_order,
                comicName,
                chapterName,
                chapterList: chapterList[0].data.sort((a, b) => a.chapter_order - b.chapter_order)
            }
            debug("\n此頁JSON資料\n", siteJson);
        },
        init: async () => {
            if (_this.SPA()) await _this.getData();
            fn.addMutationObserver(() => {
                if (!_this.SPA() || isOpenOptionsUI || isOpenGallery || isOpenFancybox || isOpenFilter || isDownloading) return;
                setTimeout(async () => {
                    await _this.getData();
                    customTitle = siteJson.comicName + " - " + siteJson.chapterName;
                }, 200);
            });
        },
        imgs: () => siteJson.srcs,
        customTitle: () => siteJson.comicName + " - " + siteJson.chapterName,
        observerClick: [".login_tip", "#floatCode>.close_code"],
        focus: ".btmBtnBox",
        category: "comic"
    }, {
        name: "动漫之家M",
        host: ["m.idmzj.com"],
        enable: 0,
        //reg: () => /m\.i?dmzj\.com\/view\/\d+\/\d+\.html/.test(fn.url) && comicInfiniteScrollMode != 1,
        url: {
            h: /m\.i?dmzj\.com/,
            p: "/view/"
        },
        init: "$('body').unbind('keydown');",
        imgs: () => {
            let code = fn.gst("initData");
            return fn.run(code.match(/page_url.+(\[.+\])/)[1]);
        },
        button: [4, "24%", 3],
        insertImg: ["#commicBox", 2],
        autoDownload: [0],
        next: ".afterChapter",
        prev: ".beforeChapter",
        customTitle: () => fn.title("-", 1),
        hide: "#khdDown,.appTil,#m_r_bottom,#m_r_panelbox,.control_panel.alpha",
        //infiniteScroll: true,
        category: "comic"
    }, {
        name: "动漫之家M 自動翻頁",
        enable: 0,
        //reg: () => /^https?:\/\/m\.i?dmzj\.com\/view\/\d+\/\d+\.html/.test(fn.url) && comicInfiniteScrollMode == 1,
        url: {
            h: /m\.i?dmzj\.com/,
            p: "/view/",
            i: 1
        },
        getImgs: (dom = document) => {
            let code = fn.gst("initData", dom);
            let srcs = fn.run(code.match(/page_url.+(\[.+\])/)[1]);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.run("$('body').unbind('keydown');");
            let imgs = _this.getImgs();
            let tE = fn.ge("#commicBox");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            observer: "#commicBox>img",
            pos: ["#commicBox", 0],
            next: (dom) => {
                let code = fn.gst("comic_id", dom).replaceAll('\"', '');
                let next_chap = code.search(/next_chap/);
                if (next_chap > -1) {
                    let [, cm] = code.match(/comic_id:(\d+)/);
                    let [, nm] = code.match(/next_chap_id:(\d+)/);
                    return fn.lo + "/view/" + cm + "/" + nm + ".html";
                } else {
                    return null;
                }
            },
            stop: async (dom) => {
                if (!fn.ge("//script[contains(text(),'page_url')]", dom)) {
                    let yes = await confirm(`Full Picture Load\n可能遇到 "请登录后观看!" 的情況。\n下一頁連結:\n${nextLink}\n是否前往下一頁?`);
                    if (yes) {
                        setTimeout(() => {
                            location.href = nextLink;
                        }, 1000);
                    }
                    return true;
                }
                return false;
            },
            re: "a.BarTit,.botNav .tc",
            title: (dom) => fn.gt(".BarTit", 1, dom),
            aF: (dom) => {
                let code = [...dom.scripts].find(s => s.innerHTML.includes("initData")).innerHTML;
                [code] = code.match(/mReader[^;]+;/);
                fn.script(code, 0, 1);
            }
        },
        hide: "#khdDown,.appTil,#m_r_bottom,#m_r_panelbox,.control_panel.alpha",
        category: "comic autoPager"
    }, {
        name: "漫畫狗",
        enable: 1,
        url: {
            h: "dogemanga.com",
            p: "/p/",
            e: ".site-reader"
        },
        init: () => {
            fn.ge(".site-reader").setAttribute("class", "imgBox");
            fn.addUrlHtml(location.origin, ".imgBox", 1, "首頁");
            _this.next() ? fn.addUrlHtml(_this.next(), ".imgBox", 1) : null;
        },
        imgs: () => fn.gae(".site-reader__image").map(e => e.dataset.pageImageUrl),
        button: [4, "24%", 1],
        insertImg: [".imgBox", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//select[@data-kind='publication']/option[@selected]/preceding-sibling::option[1]");
            return next ? next.value : null;
        },
        prev: 1,
        customTitle: () => fn.title(" - 漫畫狗"),
        css: ".imgBox{height:auto!important}",
        hide: ".fixed-bottom",
        category: "comic"
    }, {
        name: "明日方舟泰拉记事社",
        host: ["terra-historicus.hypergryph.com"],
        enable: 1,
        url: {
            h: "terra-historicus.hypergryph.com"
        },
        SPA: () => document.URL.includes("/episode/"),
        observerURL: true,
        imgs: () => {
            if (!_this.SPA()) return [];
            let max = fn.gt(".HG_COMIC_READER_indicator>div:last-child");
            let fetchNum = 0;
            return fn.arr(max, (v, i) => fetch(`/api${fn.lp}/page?pageNum=${(i + 1)}`).then(res => res.json()).then(json => {
                fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${max}`, 0);
                return json.data.url;
            }));
        },
        capture: () => _this.imgs(),
        autoDownload: [0],
        next: () => {
            if (!_this.SPA()) return null;
            return fn.waitEle("//a[text()='下一话'] | //a[text()='下一张']").then(next => next ? next.href : null);
        },
        prev: 1,
        customTitle: () => {
            if (!_this.SPA()) return null;
            return fn.waitEle(".HG_COMIC_READER_episodeTitle").then(e => fn.gt(".HG_COMIC_READER_comicTitle") + " - " + e.innerText);
        },
        category: "comic"
    }, {
        name: "Manhuagui看漫画M",
        enable: 1,
        url: {
            h: "m.manhuagui.com",
            p: /^\/comic\/\d+\/\d+.html/,
            i: 0
        },
        json: (dom = document) => {
            let code = fn.gst("x6c", dom).trim().slice(26);
            return JSON.parse(fn.run(code).slice(11, -12));
        },
        init: async () => {
            await fn.waitEle("#manga img[src*=hamreus]");
            siteJson = _this.json();
        },
        imgs: (json = siteJson) => json.images.map(e => `https://i.hamreus.com${e}?e=${json.sl.e}&m=${json.sl.m}`),
        button: [4],
        insertImg: ["#manga", 2],
        autoDownload: [0],
        next: () => siteJson.nextId == 0 ? null : fn.ge("#mangaTitle a").href + siteJson.nextId + ".html",
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.gt("#mangaTitle", 1, dom),
        preloadNext: (nextDoc, obj) => {
            let json = obj.json(nextDoc);
            let arr = obj.imgs(json);
            fn.picPreload(arr, obj.customTitle(nextDoc), "next");
        },
        css: ".action-list li{width:50% !important}",
        hide: "#action>ul>li:nth-child(n+2):nth-child(-n+3),.manga-page,.clickforceads",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Manhuagui看漫画M 自動翻頁",
        url: {
            h: "m.manhuagui.com",
            p: /^\/comic\/\d+\/\d+.html/,
            i: 1
        },
        json: (dom = document) => {
            let code = fn.gst("x6c", dom).trim().slice(26);
            let json = JSON.parse(fn.run(code).slice(11, -12));
            return json;
        },
        getSrcs: (dom) => {
            let json = _this.json(dom);
            let srcs = json.images.map(e => `https://i.hamreus.com${e}?e=${json.sl.e}&m=${json.sl.m}`);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            await fn.waitEle("#manga img[src*=hamreus]");
            let imgs = _this.getImgs();
            let tE = fn.ge("#manga");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#manga", 0],
            observer: "#manga>img",
            next: (dom, r = 1) => {
                let json = _this.json(dom);
                if (json.nextId == 0) {
                    if (r === 1) {
                        let e = fn.ge("a[data-action='chapter.next']");
                        e.href = fn.ge("#mangaTitle a").href;
                        e.innerText = "返回目录";
                    }
                    return null;
                } else {
                    return fn.gu("#mangaTitle a") + json.nextId + ".html";
                }
            },
            re: "#mangaTitle",
            title: (dom) => fn.ge("#mangaTitle>a", dom)?.nextSibling?.data?.replace(/\s+/g, " ")?.trim(),
            aF: (dom) => {
                let json = _this.json(dom);
                let cUrl = fn.gu("#mangaTitle a");
                let ne = fn.ge("a[data-action='chapter.next']");
                ne.href = cUrl + json.nextId + ".html";
                let pe = fn.ge("a[data-action='chapter.prev']");
                pe.href = cUrl + json.prevId + ".html";
            },
            preloadNextPage: 1
        },
        css: ".action-list li{width:50% !important}",
        hide: "#action>ul>li:nth-child(n+2):nth-child(-n+3),.manga-page,.clickforceads",
        category: "comic autoPager"
    }, {
        name: "Manhuagui看漫画M 点击查看下20条记录",
        url: {
            h: "m.manhuagui.com",
            p: /^\/(update|list|rank|user)\//
        },
        loadMore: "#more:not([style*=none])>.more-go",
        openInNewTab: "#detail a:not([target=_blank])",
        category: "autoPager"
    }, {
        name: "Manhuagui看漫画",
        host: ["www.manhuagui.com", "tw.manhuagui.com", "www.mhgui.com"],
        enable: 1,
        url: {
            h: /manhuagui|mhgui/,
            p: /^\/comic\/\d+\/\d+.html/,
            i: 0
        },
        init: "$(document).unbind('keydown');",
        imgs: (dom = document) => {
            let code = fn.gst("x6c", dom).slice(26, -1);
            let json = fn.run(fn.run(code).slice(11, -11));
            let domain = "https://i.hamreus.com";
            return json.files.map(e => `${domain+json.path+e}?e=${json.sl.e}&m=${json.sl.m}`);
        },
        button: [4],
        insertImg: ["#tbBox", 2],
        autoDownload: [0],
        next: () => {
            const {
                cInfo
            } = _unsafeWindow;
            return cInfo.nextId == 0 ? null : location.origin + "/comic/" + cInfo.bid + "/" + cInfo.nextId + ".html";
        },
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.gt("h1>a", 1, dom) + " - " + fn.gt("h2", 1, dom),
        preloadNext: true,
        css: ".tbCenter{max-width:1400px!important;width:auto!important;height:auto!important}",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Manhuagui看漫画 自動翻頁",
        url: {
            h: /manhuagui|mhgui/,
            p: /^\/comic\/\d+\/\d+.html/,
            i: 1
        },
        json: (dom = document) => {
            let code = fn.gst("x6c", dom).slice(26, -1);
            let json = fn.run(fn.run(code).slice(11, -11));
            return json;
        },
        getSrcs: (dom) => {
            let json = _this.json(dom);
            let domain = "https://i.hamreus.com";
            let srcs = json.files.map(e => `${domain+json.path+e}?e=${json.sl.e}&m=${json.sl.m}`);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge("#tbBox");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            fn.run("$(document).unbind('keydown');");
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#tbBox", 0],
            observer: "#tbBox img",
            next: (dom, r = 1) => {
                let json = _this.json(dom);
                let n = json.nextId;
                if (n == 0) {
                    if (r === 1) {
                        fn.ge("#pagination").outerHTML = fn.ge(".main-btn").outerHTML;
                    }
                    return null;
                } else {
                    return fn.url.replace(/\d+\.html$/, "") + n + ".html";
                }
            },
            re: ".title h2",
            title: (dom) => _this.json(dom).cname,
            preloadNextPage: 1
        },
        css: ".tbCenter{max-width:1400px!important;width:auto!important;height:auto!important}",
        hide: "#prev,#pageSelect,#next,.pager>*:not([onclick])",
        category: "comic autoPager"
    }, {
        name: "包子漫画 閱讀",
        host: ["cn.baozimh.com", "cn.webmota.com", "tw.baozimh.com", "tw.webmota.com", "www.baozimh.com", "www.webmota.com", "cn.kukuc.co", "tw.kukuc.co", "www.kukuc.co", "tw.czmanga.com", "cn.czmanga.com", "www.czmanga.com", "tw.dzmanga.com", "cn.dzmanga.com", "www.dzmanga.com", "tw.dociy.net", "cn.dociy.net", "www.dociy.net", "tw.twmanga.com", "cn.twmanga.com", "www.twmanga.com"],
        enable: 1,
        url: {
            t: "包子",
            p: /^\/comic\/chapter\/[^/]+\/\w+\.html/i,
            i: 0
        },
        init: async () => {
            fn.addMutationObserver(() => fn.remove("div[id*='ads'],div[id='interstitial_fade'],iframe"));
            fn.run("document['onkeydown']=null;");
            await fn.getNP(".comic-contain>div:not(.mobadsq)", "//a[contains(text(),'下一頁') or contains(text(),'下一页')]", null, ".comic-chapter>.next_chapter,.bottom-bar-tool");
        },
        imgs: (dom = document) => [...new Set(fn.gae(".comic-contain amp-img", dom).map(e => e.dataset.src ?? e.getAttribute("src")))],
        button: [4],
        insertImg: [".comic-contain", 2],
        autoDownload: [0],
        next: "//div[@class='next_chapter']/a[contains(text(),'下一話') or contains(text(),'下一话')]",
        prev: 1,
        customTitle: (dom = document) => fn.title(" - ", 3, dom).replace(/\(\d+\/\d+\)/, ""),
        preloadNext: true,
        hide: "div[id*='ads'],div[id='interstitial_fade'],iframe,.chapter-main.scroll-mode~*:not(.next_chapter):not(.bottom-bar)",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "包子漫画 閱讀 自動翻頁",
        url: {
            t: "包子",
            p: /^\/comic\/chapter\/[^/]+\/\w+\.html/i,
            i: 1
        },
        getSrcs: (dom) => fn.gae(".comic-contain amp-img", dom).map(e => e.dataset.src ?? e.getAttribute("src")),
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            if (fn.ge(".FullPictureLoadImage")) {
                let currentLastSrc = fn.gae(".FullPictureLoadImage").at(-1).dataset.src;
                let nextFirstNum = Number(srcs[0].match(/(\d)\.\w+$/)[1]);
                if (/\/(50|100|150|200|250|300)\.[a-z]{3,5}$/i.test(currentLastSrc) && nextFirstNum == 7 && nextFirstNum != 1) {
                    srcs = srcs.slice(4);
                }
            }
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.addMutationObserver(() => fn.remove("div[id*='ads'],div[id='interstitial_fade'],iframe"));
            fn.run("document['onkeydown']=null;");
            let imgs = _this.getImgs();
            let tE = fn.ge(".comic-contain");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: [".comic-contain", 0],
            observer: ".comic-contain img",
            next: (dom) => {
                let next = fn.ge("a#next-chapter", dom);
                return next ? next.pathname : null;
            },
            re: "//div[@class='text']/span[@class='title'] | //div[@class='comic-chapter']/div[@class='next_chapter'] | //div[@class='bottom-bar-tool']",
            title: (dom) => {
                let titleText = fn.gt("span.title", 1, dom).replace(/\(\d\/\d+\)/, "");
                return {
                    ok: /\/\d+_\d+\.html$/.test(nextLink),
                    text: titleText
                }
            },
            hide: ".comic-chapter>.l-content",
            preloadNextPage: 1
        },
        css: ".comic-contain{width: 100%;margin: 0 auto;max-width:970px;}",
        hide: "div[id*='ads'],div[id='interstitial_fade'],iframe,.chapter-main.scroll-mode~*:not(.next_chapter,.bottom-bar,.l-content),.mobadsq",
        category: "comic autoPager"
    }, {
        name: "包子漫画 展開目錄",
        icon: 0,
        key: 0,
        url: {
            t: "包子",
            p: /^\/comic\/[-\w]+$/i
        },
        autoClick: ["#button_show_all_chatper", 1000],
        category: "comic"
    }, {
        name: "包子漫画,連結新分頁開啟",
        icon: 0,
        key: 0,
        url: {
            t: "包子",
            e: ".comics-card,.bookshelf-items"
        },
        openInNewTab: ".comics-card a:not([target=_blank]),.bookshelf-items a:not(.remove-img):not([target=_blank])",
        category: "comic"
    }, {
        name: "Komiic",
        enable: 0,
        url: {
            h: "komiic.com"
        },
        SPA: () => document.URL.includes("/chapter/"),
        observerURL: true,
        imgs: async (url = document.URL) => {
            if (!_this.SPA()) return [];
            fn.showMsg(displayLanguage.str_05, 0);
            let [, chapterId] = url.match(/chapter\/(\d+)\/images/);
            let body = {
                operationName: "imagesByChapterId",
                variables: {
                    chapterId: `${chapterId}`
                },
                query: "query imagesByChapterId($chapterId: ID!) {\n  imagesByChapterId(chapterId: $chapterId) {\n    id\n    kid\n    height\n    width\n    __typename\n  }\n}\n"
            };
            let json = await fetch("/api/query", {
                "headers": {
                    "content-type": "application/json"
                },
                "body": JSON.stringify(body),
                "method": "POST"
            }).then(res => res.json());
            debug("\nimages JSON\n", json);
            return json.data.imagesByChapterId.map(e => "https://komiic.com/api/image/" + e.kid);
        },
        capture: () => _this.imgs(),
        next: async (url = document.URL) => {
            if (!_this.SPA()) return null;
            let [, mhId] = url.match(/comic\/(\d+)/);
            let body = {
                operationName: "chapterByComicId",
                variables: {
                    comicId: `${mhId}`
                },
                query: "query chapterByComicId($comicId: ID!) {\n  chaptersByComicId(comicId: $comicId) {\n    id\n    serial\n    type\n    dateCreated\n    dateUpdated\n    size\n    __typename\n  }\n}\n"
            };
            let json = await fetch("/api/query", {
                "headers": {
                    "content-type": "application/json"
                },
                "body": JSON.stringify(body),
                "method": "POST"
            }).then(res => res.json());
            debug("\nchapter JSON\n", json);
            let [, chapterId] = url.match(/chapter\/(\d+)\/images/);
            let chapters = json.data.chaptersByComicId;
            let nextUrl;
            for (let [i, chapter] of chapters.entries()) {
                if (new RegExp(chapterId).test(chapter.id)) {
                    if (chapters[i + 1] !== undefined) {
                        let nextId = chapters[i + 1].id;
                        nextUrl = siteUrl.replace(new RegExp(`/${chapterId}/`), `/${nextId}/`).replace(/\?page=\d+/, "");
                    } else {
                        nextUrl = null;
                    }
                    break;
                }
            }
            return nextUrl;
        },
        prev: 1,
        customTitle: async () => {
            if (!_this.SPA()) return null;
            await fn.waitEle(".v-breadcrumbs");
            let textArr = fn.gt(".v-breadcrumbs").split("\n");
            return textArr[1] + " - " + textArr[2];
        },
        fetch: 1,
        referer: "url",
        category: "comic"
    }, {
        name: "LINE WEBTOON / 咚漫",
        host: ["www.webtoons.com", "www.dongmanmanhua.cn"],
        enable: 0,
        url: {
            h: /webtoons|dongmanmanhua/,
            p: /^\/[^&]+&episode/
        },
        imgs: "._images[data-url]",
        autoDownload: [0],
        next: "//div[@class='episode_cont']//li[a[starts-with(@class,'on')]]/following-sibling::li[1]/a",
        prev: "//div[@class='episode_cont']//li[a[starts-with(@class,'on')]]/preceding-sibling::li[1]/a",
        customTitle: () => fn.title("|", 3).replace(/ - \d+/, "").replace("|", " - "),
        category: "comic"
    }, {
        name: "LINE WEBTOON 目錄聚集所有章節",
        enable: 0,
        icon: 0,
        key: 0,
        url: {
            h: "www.webtoons.com",
            p: "/list"
        },
        init: "fn.getNP('._episodeItem',\"//div[@class='paginate']/a[span[@class='on']]/following-sibling::a[1]\",null,'.paginate',0,null,0);",
        category: "comic"
    }, {
        name: "動漫狂",
        host: ["www.cartoonmad.com", "cc.fun8.us"],
        enable: 1,
        url: {
            h: "cc.fun8.us",
            p: "/post/",
            i: 0
        },
        exclude: "#info table[align]",
        init: () => fn.cartoonmadUI(),
        imgs: (dom = document) => {
            let [imgDir] = fn.ge("img[onload],img[oncontextmenu]", dom).src.match(/.+\//);
            let max = fn.ge(".onpage", dom).parentNode.lastElementChild.previousElementSibling.innerText;
            fn.remove("//tr[td[a[@class='onpage']]]");
            return fn.arr(max, (v, i) => imgDir + String((i + 1)).padStart(3, "0") + ".jpg");
        },
        button: [4],
        insertImg: ["//td[a[img[@oncontextmenu]]] | //td[a[img[@oncontextmenu]]]", 2],
        autoDownload: [0],
        next: "//td[@width='150' and a[img[@src='/image/rad.gif']]]/a | //a[b]",
        prev: "//td[@width='150' and a[img[@src='/image/rad1.gif']]]/a",
        customTitle: async (dom = document) => {
            let src = fn.ge("img[onload],img[oncontextmenu]", dom).src;
            let comicId = new URL(src).pathname.split("/")[3];
            let comicIdData = JSON.parse(localStorage.getItem("comicIdData")) ?? {};
            if (comicIdData[comicId] === null || comicIdData[comicId] === undefined) {
                if (/TW|HK/.test(language)) {
                    fn.showMsg("首次取得漫畫名稱", 0);
                } else if (/zh/.test(language)) {
                    fn.showMsg("首次取得漫画名称", 0);
                } else {
                    fn.showMsg("First time Get ComicName", 0);
                }
                let comicName = await fn.xhrDoc(`https://www.cartoonmad.com/comic/${comicId}.html`, {
                    headers: {
                        "User-Agent": PC_UA
                    }
                }).then(comicDoc => fn.ge("meta[name=Keywords]", comicDoc).content.split(",")[0]);
                comicIdData[comicId] = comicName;
                localStorage.setItem("comicIdData", JSON.stringify(comicIdData));
                return comicName + " - " + dom.title;
            } else {
                let comicName = comicIdData[comicId];
                return comicName + " - " + dom.title;
            }
        },
        preloadNext: true,
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "動漫狂 自動翻頁",
        url: {
            h: "cc.fun8.us",
            p: "/post/",
            i: 1
        },
        exclude: "#info table[align]",
        getSrcs: (dom) => {
            let [imgDir] = fn.ge("img[onload],img[oncontextmenu]", dom).src.match(/.+\//);
            let max = fn.ge(".onpage", dom).parentNode.lastElementChild.previousElementSibling.innerText;
            let srcs = fn.arr(max, (v, i) => imgDir + String((i + 1)).padStart(3, "0") + ".jpg");
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.cartoonmadUI();
            let imgs = _this.getImgs();
            let tE = fn.ge("//td[a[img[@oncontextmenu]]] | //td[a[img[@oncontextmenu]]]");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            fn.remove("//tr[td[a[@class='onpage']]]");
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["//td[img]", 0],
            observer: "//td[img]/img",
            next: "//td[@width='150' and a[img[@src='/image/rad.gif']]]/a | //a[b]",
            aF: (dom) => {
                fn.gae("//tr[td[@bgcolor='#EAEAEA']] | //tr[td[@bgcolor='#EBEBEB']]").forEach(e => (e.innerHTML = fn.ge("//tr[td[@bgcolor='#EAEAEA']] | //tr[td[@bgcolor='#EBEBEB']]", dom, dom).innerHTML));
                fn.remove("//td[div[@id='sidebar-follow']] | //td[ins[@class='adsbygoogle']] | //tr[td[script]] | //select");
            },
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "動漫啦",
        enable: 0,
        url: {
            h: "www.dongman.la",
            p: "/chapter/"
        },
        imgs: (link = siteUrl, msg = 1, request = 0) => {
            let links = [link.replace("all.html", "") + "all.html"];
            return fn.getImgA(".imgListBox img", links, 0, null, msg, request);
        },
        button: [4],
        insertImg: [".imgListBox", 2],
        autoDownload: [0],
        next: "//a[label[text()='下一章']][contains(@href,'chapter')]",
        prev: "//a[label[text()='上一章']][contains(@href,'chapter')]",
        customTitle: (dom = document) => fn.attr("meta[name='description']", "content", dom),
        preloadNext: async (nextDoc, obj) => fn.picPreload(await obj.imgs(nextLink, 0, 1), obj.customTitle(nextDoc), "next"),
        css: ".mdui-col-xs-4{width:50%!important}",
        hide: ".mdui-container .mdui-col-xs-4:nth-child(2)",
        category: "comic"
    }, {
        name: "動漫啦M",
        enable: 0,
        url: {
            h: "m.dongman.la",
            p: "/chapter/",
        },
        imgs: ".chapter-images img",
        button: [4],
        insertImg: [".chapter-images", 2],
        autoDownload: [0],
        next: "//a[label[text()='下一章']][contains(@href,'chapter')]",
        prev: "//a[label[text()='上一章']][contains(@href,'chapter')]",
        customTitle: (dom = document) => dom.title,
        preloadNext: true,
        category: "comic"
    }, {
        name: "動漫戲說",
        enable: 0,
        url: {
            h: "comic.acgn.cc",
            p: "/view"
        },
        imgs: (dom = document) => fn.gae(".pic[_src][id]", dom).map(e => e.getAttribute("_src")),
        button: [4],
        insertImg: ["#pic_list", 2],
        autoDownload: [0],
        next: ".display_right>a",
        prev: ".display_left>a",
        customTitle: (dom = document) => fn.gt(".hotrmtexth1>a", 1, dom),
        preloadNext: true,
        hide: ".btn_wrap",
        category: "comic"
    }, {
        name: "国漫吧",
        host: ["www.guoman8.cc", "m.guoman8.cc"],
        enable: 1,
        url: {
            h: ".guoman8.",
            p: /^\/\d+\/\d+\.html$/,
            i: 0
        },
        init: () => setTimeout(() => fn.run("$(document).off();"), 5000),
        imgs: () => {
            const {
                cInfo,
                pageConfig
            } = _unsafeWindow;
            return cInfo.fs.map(e => /^http/.test(e) ? e : location.protocol + "//" + pageConfig.host.auto[0] + e);
        },
        button: [4],
        insertImg: ["//td[img[@id='manga']]", 2],
        autoDownload: [0],
        next: "a.nextC:not([href^=java])",
        prev: ".prevC",
        customTitle: () => {
            const {
                cInfo
            } = _unsafeWindow;
            return cInfo.btitle + " - " + cInfo.ctitle;
        },
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("cInfo", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(), "next");
        },
        css: ".action-list li{width:50%!important}",
        hide: "#action>ul>li:nth-child(n+2):nth-child(-n+3),.bd_960_90,body>section,#action~*:not(#pageNo),footer~*",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "国漫吧 自動翻頁",
        url: {
            h: ".guoman8.",
            p: /^\/\d+\/\d+\.html$/,
            i: 1
        },
        json: (dom) => {
            let code = fn.gst("eval", dom);
            let codeText = code.match(/eval(\(.+\)\))/)[0].slice(4);
            let objText = fn.run(codeText);
            objText = objText.replace(/var\scInfo\s?=|;/g, "");
            let json = fn.run(objText);
            return json;
        },
        getSrcs: (dom) => {
            let json = _this.json(dom);
            const {
                pageConfig
            } = _unsafeWindow;
            let srcs = json.fs.map(e => /^http/.test(e) ? e : "//" + pageConfig.host.auto[0] + e);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge("//td[img[@id='manga']]");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            setTimeout(() => fn.run("$(document).off();"), 5000);
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["//td[img]", 0],
            observer: "//td[img]/img",
            next: (dom, r = 1) => {
                let nextE = fn.ge("a.nextC:not([href^=java])", dom);
                if (nextE) {
                    return nextE.href;
                } else {
                    if (r === 1) {
                        let curl = fn.lp.replace(/\d+\/$|\d+\.html$/, "");
                        let mn = fn.ge("a.nextC");
                        if (mn) {
                            mn.href = curl;
                            mn.innerText = "返回目录";
                        }
                        if (fn.lh === "www.guoman8.cc") {
                            mn.remove();
                            let pn = fn.ge("//a[text()='下一章']");
                            pn.setAttribute("onclick", "");
                            pn.href = fn.ge("//a[text()='返回目录']").pathname;
                            pn.innerText = "返回目录";
                        }
                    }
                    return null;
                }
            },
            re: ".title h2,.main-btn,#mangaTitle,#action",
            title: (dom) => _this.json(dom).ctitle,
            preloadNextPage: 1
        },
        css: ".action-list li{width:50%!important}",
        hide: "#imgLoading,#manga,.action,#action>ul>li:nth-child(n+2):nth-child(-n+3),.bd_960_90,body>section,#action~*:not(#pageNo,#FullPictureLoadMsg),footer~*:not(#FullPictureLoadMsg),#prev,#pageSelect,#next,#pager>*:not([onclick]),#pager>*[onclick*='next()'],.backToTop~div[style*='overflow']",
        category: "comic autoPager"
    }, {
        name: "古风漫画网",
        host: ["www.gufengmh.com", "m.gufengmh.com", "www.gufengmh9.com", "m.gufengmh9.com"],
        enable: 1,
        url: {
            h: "gufengmh",
            p: /^\/manhua\/\w+\/\d+\.html/,
            i: 0
        },
        init: () => {
            fn.run("$(document).off();$('#images').off();");
            fn.remove("#skin");
            fn.createImgBox("#images", 2);
        },
        imgs: () => {
            const {
                chapterImages,
                SinConf,
                chapterPath
            } = _unsafeWindow;
            return chapterImages.map(e => SinConf.resHost[0].domain + "/" + chapterPath + e);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#images"], 2
        ],
        autoDownload: [0],
        next: () => {
            const {
                nextChapterData,
                comicUrl
            } = _unsafeWindow;
            return nextChapterData?.id > 0 ? comicUrl + nextChapterData.id + ".html" : null;
        },
        prev: "//a[contains(text(),'上一章')]",
        customTitle: (dom = document) => {
            if (/^https?:\/\/www/.test(siteUrl)) {
                let arr = fn.gt(".title", 1, dom).split(" / ");
                return arr[0] + " - " + arr[1];
            } else {
                let code = fn.gst("SinMH.initChapter", dom);
                let arr = code.match(/SinMH.initChapter\(([^\)]+)\)/)[1].replaceAll('"', "").split(",");
                return arr[3] + " - " + arr[1];
            }
        },
        preloadNext: async (nextDoc, obj) => {
            let title;
            /^https?:\/\/www/.test(siteUrl) ? title = nextDoc.title.split("在线")[0] : title = obj.customTitle(nextDoc);
            let code = fn.gst("chapterImages", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), title, "next");
        },
        css: "#action li{width:50%!important}",
        hide: ".nav-pagination,.pageSelect,.nav-pagination,.img_land_prev,.img_land_next,#action li:nth-child(2),#action li:nth-child(3),.control_bottom~*,.chapter-view~*:not(.footer,[id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],[id^='pagetual'],[class^='pagetual'],#comicRead,#fab[class^=fancybox]),.img_info",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "古风漫画网 自動翻頁",
        url: {
            h: "gufengmh",
            p: /^\/manhua\/\w+\/\d+\.html/,
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("chapterImages", dom);
            let [, imagesArrText] = code.match(/chapterImages[\s=]+([^;]+)/);
            let cImages = fn.run(imagesArrText);
            let [, cPath] = code.match(/chapterPath[\s="]+([^"]+)/);
            let [, domain] = code.match(/pageImage[\s="]+(https?:\/\/\w+\.\w+\.\w+\/)/);
            let srcs = cImages.map(e => domain + cPath + e);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.run("$(document).off();$('#images').off();");
            fn.remove("#skin");
            let tE = fn.createImgBox("#images", 2);
            fn.remove("#images");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            script: "//script[contains(text(),'chapterImages')]",
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: (dom, r = 1) => {
                let code = fn.gst("nextChapterData", dom);
                let [, nextText] = code.match(/nextChapterData[\s=]+([^;]+)/);
                let [, cUrlText] = code.match(/comicUrl[\s="]+([^"]+)/);
                let nextrData = JSON.parse(nextText);
                if (nextrData?.id > 0) {
                    return cUrlText + nextrData.id + ".html";
                } else {
                    if (/^m\./.test(fn.lh) && r === 1) {
                        let n = fn.ge("//a[text()='下一章']");
                        n.href = fn.lp.replace(/\d+\.html$/, "");
                        n.innerText = "返回目录";
                    }
                    return null;
                }
            },
            re: ".title,.BarTit",
            title: (dom) => {
                if (/^https?:\/\/www/.test(siteUrl)) {
                    return fn.gt(".title>h1>a", 1, dom) + " - " + fn.gt(".title>h2", 1, dom);
                } else {
                    let code = fn.gst("SinMH.initChapter", dom);
                    let arr = code.match(/SinMH.initChapter\(([^\)]+)\)/)[1].replaceAll('"', "").split(",");
                    return arr[1];
                }
            },
            hide: ".comic-comment,.chapter-content+.imgBox",
            preloadNextPage: 1
        },
        css: "#action li{width:50%!important}",
        hide: ".nav-pagination,.pageSelect,.nav-pagination,.img_land_prev,.img_land_next,#action li:nth-child(2),#action li:nth-child(3),.control_bottom~*,.chapter-view~*:not(.footer,[id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],[id^='pagetual'],[class^='pagetual'],#comicRead,#fab,[class^=fancybox]),.img_info",
        category: "comic autoPager"
    }, {
        name: "漫画456",
        enable: 0,
        url: {
            h: "www.manhua456.com",
            p: /^\/manhua\/\w+\/\d+\.html/
        },
        init: async () => {
            await fn.waitVar("SinConf");
            fn.run("setTimeout(()=>{$(document).unbind('keyup');$(document).unbind('keydown')},4000)");
        },
        imgs: (frame = _unsafeWindow) => {
            const {
                SinConf,
                chapterImages,
                chapterPath
            } = frame;
            let host = SinConf.resHost1 ?? SinConf.resHost[0].domain;
            return chapterImages.map(e => /^http/.test(e) ? e : host + "/" + chapterPath + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: () => {
            const {
                nextChapterData,
                comicUrl
            } = _unsafeWindow;
            if (nextChapterData?.id > 0) {
                let url = new URL(nextChapterData.url);
                return url.protocol != location.protocol ? url.href.replace(url.protocol, location.protocol) : url;
            }
            return null;
        },
        prev: "//a[text()='上一章']",
        customTitle: (dom) => fn.title(" - ", 3, dom),
        preloadNext: () => {
            fn.iframe(nextLink, {
                waitVar: "SinConf",
                cb: async (dom, frame) => {
                    let srcs = _this.imgs(frame);
                    let text = _this.customTitle(dom);
                    fn.picPreload(srcs, text, "next");
                }
            });
        },
        hide: ".img_land_prev,.img_land_next",
        category: "comic"
    }, {
        name: "漫画456M",
        enable: 0,
        url: {
            h: "m.manhua456.com",
            p: /^\/manhua\/\w+\/\d+\.html/
        },
        init: async () => {
            await fn.waitVar(["pageTitle", "jQuery", "SinConf"]);
            await fn.waitEle("#images img");
            fn.run("jQuery('#images').unbind('click');");
        },
        imgs: (frame = _unsafeWindow) => {
            const {
                chapterImages,
                SinConf,
                chapterPath
            } = frame;
            let host = SinConf.resHost1 ?? SinConf.resHost[0].domain;
            return chapterImages.map(e => /^http/.test(e) ? e : host + "/" + chapterPath + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        next: () => {
            const {
                nextChapterData,
                comicUrl
            } = _unsafeWindow;
            if (nextChapterData?.id > 0) {
                let url = new URL(nextChapterData.url);
                return url.protocol != location.protocol ? url.href.replace(url.protocol, location.protocol) : url;
            }
            return null;
        },
        prev: "//a[text()='上一章']",
        customTitle: (frame = _unsafeWindow) => {
            const {
                pageTitle
            } = frame;
            let s = pageTitle.split(" - ");
            return s[1] + " - " + s[0];
        },
        preloadNext: () => {
            fn.iframe(nextLink, {
                waitVar: "SinConf",
                cb: async (dom, frame) => {
                    let srcs = _this.imgs(frame);
                    let text = _this.customTitle(frame);
                    fn.picPreload(srcs, text, "next");
                }
            });
        },
        css: ".action-list li{width:50% !important}",
        hide: "#action>ul>li:nth-child(n+2):nth-child(-n+3),.img_land_prev,.img_land_next,body>div[id]:has(>div[class][style]>div[style])",
        category: "comic"
    }, {
        name: "漫画1234",
        host: ["www.gmh1234.com", "m.gmh1234.com"],
        enable: 0,
        url: {
            h: "mh1234.com",
            p: /^\/comic\/\d+\/\d+\.html/
        },
        init: async () => {
            await fn.waitVar("chapterImages", 600);
            fn.run("$(document).unbind('keydown');$(document).unbind('keyup');$('#images').unbind('click');");
        },
        imgs: () => {
            const {
                chapterImages,
                SinConf,
                chapterPath
            } = _unsafeWindow;
            return chapterImages.map(e => /^http/.test(e) ? e : SinConf.resHost[0].domain + "/" + chapterPath + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        insertImgAF: (parent) => {
            if (fn.lh == "m.gmh1234.com") fn.run("$('#images').off()");
            if (nextLink) {
                fn.addUrlHtml(nextLink, parent, 1, displayLanguage.str_143, 3);
            }
        },
        next: () => fn.fetchDoc(_unsafeWindow.comicUrl).then(dom => {
            let nextUrl = null;
            fn.gau('ul[id^=chapter-list] a', dom).reverse().some((url, i, a) => {
                if (url.includes(location.pathname.match(/\d+/g).at(-1))) {
                    if (a[i - 1] === undefined) {
                        nextUrl = null;
                    } else {
                        nextUrl = a[i - 1];
                    }
                    return true;
                } else {
                    return false;
                }
            });
            return nextUrl;
        }),
        customTitle: (dom = document) => {
            let s = fn.gst("initChapter", dom).match(/SinTheme\.initChapter\(([^\)]+)\);/)[1].replaceAll('"', "").split(",");
            return s[3] + " - " + s[1];
        },
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("chapterImages", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        css: ".action-list li{width:50% !important}",
        hide: ".globalPadding,.img_info,#imgLoading,#loading,#action>ul>li:nth-child(n+2):nth-child(-n+3)",
        category: "comic"
    }, {
        name: "92漫画",
        enable: 0,
        url: {
            h: "www.92mh.com",
            p: /^\/manhua\/\d+\/\d+\.html/
        },
        init: "$(document).unbind('keydown');$(document).unbind('keyup');$('#images').unbind('click');",
        imgs: () => {
            const {
                chapterImages,
                SinConf
            } = _unsafeWindow;
            return chapterImages.map(e => /^http/.test(e) ? e : SinConf.resHost[0].domain + "/" + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: () => {
            const {
                nextChapterData
            } = _unsafeWindow;
            return nextChapterData.id > 0 ? nextChapterData.url : null;
        },
        prev: 1,
        customTitle: (dom = document) => {
            let s = fn.gst("initChapter", dom).match(/SinTheme\.initChapter\(([^\)]+)\);/)[1].replaceAll('"', "").split(",");
            return s[3] + " - " + s[1];
        },
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("chapterImages", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        hide: ".img_land_prev,.img_land_next",
        category: "comic"
    }, {
        name: "92漫画M",
        enable: 0,
        url: {
            h: "m.92mh.com",
            p: /^\/manhua\/\d+\/\d+\.html/
        },
        imgs: (url = siteUrl, dom = document, msg = 1, request = 0) => {
            let [, max] = fn.gt(".image-content p", 1, dom).match(/\/(\d+)/);
            return fn.getImg("#manga-image", max, 5, null, 20, url, msg, request);
        },
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: () => {
            let next = fn.ge("//a[text()='下一章'][contains(@href,'html')]");
            return next ? next.href : null;
        },
        prev: 1,
        customTitle: (dom = document) => fn.title("在线", 1, dom),
        preloadNext: async (nextDoc, obj) => fn.picPreload(await obj.imgs(nextLink, nextDoc, 0, 1), obj.customTitle(nextDoc), "next"),
        css: "body{padding:0!important}.action-list li{width:50% !important}",
        hide: "div[style*='text-align: left;'],.UnderPage~*:not([id^='Full'],[class^='Full'],[id^='pv-'],[class^='pv-'],[id^='pagetual'],[class^='pagetual'],#comicRead,#fab,[class^=fancybox]),.action-list>ul>li:nth-child(n+2):nth-child(-n+3)",
        category: "comic"
    }, {
        name: "优酷漫画",
        host: ["www.ykmh.net"],
        enable: 0,
        url: {
            h: ".ykmh.",
            p: /^\/manhua\/\w+\/\d+\.html$/,
            d: "pc"
        },
        init: "$(document).unbind('keydown');$(document).unbind('keyup');",
        imgs: () => {
            const {
                chapterImages,
                SinConf
            } = _unsafeWindow;
            return chapterImages.map(e => SinConf.resHost[0].domain + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: ".next>a",
        prev: ".pre>a",
        customTitle: (dom = document) => fn.title(" - ", 3, dom),
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("chapterImages", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        hide: ".img_land_prev,.img_land_next",
        category: "comic"
    }, {
        name: "优酷漫画M",
        host: ["m.ykmh.net"],
        enable: 0,
        url: {
            h: ".ykmh.",
            p: /^\/manhua\/\w+\/\d+\.html$/,
            d: "m"
        },
        init: "$('#images').unbind('click');",
        imgs: () => {
            const {
                chapterImages,
                SinConf
            } = _unsafeWindow;
            return chapterImages.map(e => SinConf.resHost[0].domain + e);
        },
        button: [4],
        insertImg: ["#images", 2],
        autoDownload: [0],
        next: () => {
            const {
                nextChapterData,
                comicUrl
            } = _unsafeWindow;
            return nextChapterData?.id > 0 ? nextChapterData.url : null;
        },
        prev: "//a[text()='上一章']",
        customTitle: () => {
            const {
                pageTitle
            } = _unsafeWindow;
            let s = pageTitle.split(" - ");
            return s[1] + " - " + s[0];
        },
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("chapterImages", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(), "next");
        },
        hide: ".letchepter>div,.letchepter>section,#FullPictureLoad~*",
        category: "comic"
    }, {
        name: "来漫画",
        host: ["www.laimanhua8.com", "www.laimanhua88.com", "www.comemh.com", "www.comemh8.com"],
        enable: 1,
        url: {
            h: [/^www\.(laimanhua|comemh)/],
            p: "/kanmanhua/",
            d: "pc",
            i: 0
        },
        init: () => {
            fn.clearAllTimer();
            fn.createImgBox("#pic-list", 2);
        },
        imgs: () => {
            const {
                base64_decode,
                picTree,
                getpicdamin
            } = _unsafeWindow;
            return base64_decode(picTree).split("$qingtiandy$").map(e => getpicdamin() + e);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#pic-list"], 2
        ],
        endColor: "white",
        autoDownload: [0],
        next: () => {
            const {
                nextUrlid
            } = _unsafeWindow;
            return nextUrlid == "" ? null : fn.gu("a#cartoon_url") + nextUrlid + ".html";
        },
        prev: ".btn-prev",
        customTitle: (dom = document) => fn.title(",", 1, dom).replace("漫画", "").trim(),
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("picTree", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        hide: "#loading,#pre-loading,.img_info,.blank20,#udbsdk_login",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "来漫画 自動翻頁",
        url: {
            h: /^www\.(laimanhua|comemh)/,
            p: "/kanmanhua/",
            d: "pc",
            i: 1
        },
        getSrcs: (dom) => {
            const {
                base64_decode,
                getpicdamin
            } = _unsafeWindow;
            let code = fn.gst("picTree", dom);
            let base64Text = code.match(/picTree[\s\=]+([^;]+)/)[1].replaceAll('"', "").replaceAll("'", "");
            let srcs = base64_decode(base64Text).split("$qingtiandy$").map(e => getpicdamin() + e);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.clearAllTimer();
            let tE = fn.createImgBox("#pic-list", 2);
            fn.remove("#pic-list");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            script: "//script[contains(text(),'picTree')]",
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: (dom) => {
                let code = fn.gst("nextUrlid", dom);
                let comicURL = fn.gu("#position a");
                let [, cidText] = code.match(/nextUrlid[\s\=]+([^,;]+)/);
                if (/\d+/.test(cidText)) {
                    let [cid] = cidText.match(/\d+/);
                    return comicURL + cid + ".html";
                } else {
                    return null;
                }
            },
            re: "#bottom_chapter",
            title: (dom) => fn.gt("#position", 1, dom).replaceAll("\n", "").replaceAll(">", "").replace("漫画", "").trim(),
            preloadNextPage: 1
        },
        css: ".subNav{margin: 4px auto!important;float:unset!important}",
        hide: "#loading,#pre-loading,.img_info,.blank20,#udbsdk_login",
        category: "comic autoPager"
    }, {
        name: "来漫画M",
        host: ["m.laimanhua8.com", "m.laimanhua88.com", "m.comemh.com", "m.comemh8.com"],
        enable: 1,
        url: {
            h: [/^m\.(laimanhua|comemh)/],
            p: "/kanmanhua/",
            e: "#manga",
            d: "m",
            i: 0
        },
        init: () => fn.clearAllTimer(),
        imgs: () => {
            const {
                mhInfo,
                realurl
            } = _unsafeWindow;
            return mhInfo.images.map(e => realurl + mhInfo.path + e);
        },
        button: [4],
        insertImg: ["#manga", 2],
        autoDownload: [0],
        next: () => {
            const {
                mhInfo
            } = _unsafeWindow;
            return mhInfo.nextUrlid == "" ? null : fn.gu("#mangaTitle>a") + mhInfo.nextUrlid + ".html";
        },
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.gt("#mangaTitle", 1, dom).replace(/\n/g, "").trim(),
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("mhInfo", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        css: ".action-list li{width:50% !important}",
        hide: "#jusha1,#action>ul>li:nth-child(n+2):nth-child(-n+3)",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "来漫画M 自動翻頁",
        url: {
            h: [/^m\.(laimanhua|comemh)/],
            p: "/kanmanhua/",
            e: "#manga",
            d: "m",
            i: 1
        },
        json: (dom) => {
            let code = fn.gst("mhInfo", dom);
            let [, objText] = code.match(/mhInfo[\s=]+([^;]+)/);
            let json = JSON.parse(objText);
            return json;
        },
        getSrcs: (dom) => {
            let json = _this.json(dom);
            let srcs = json.images.map(e => _unsafeWindow.realurl + json.path + e);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.clearAllTimer();
            let imgs = _this.getImgs();
            let tE = fn.ge("#manga");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            script: "//script[contains(text(),'mhInfo')]",
            ele: (dom) => _this.getImgs(dom),
            pos: ["#manga", 0],
            observer: "#manga>img",
            next: (dom, r = 1) => {
                let json = _this.json(dom);
                let cUrl = fn.gu("#mangaTitle>a");
                if (json.nextUrlid == "") {
                    if (r === 1) {
                        fn.remove("//li[a[text()='下一章']]");
                        let html = `<li><a href="${cUrl}">返回目录</a></li>`;
                        fn.ge("#action>ul").insertAdjacentHTML("beforeend", html);
                    }
                    return null;
                } else {
                    return cUrl + json.nextUrlid + ".html";
                }
            },
            title: (dom) => _this.json(dom).chapterTitle,
            hide: "#slider",
            preloadNextPage: 1
        },
        css: ".action-list li{width:50% !important}",
        hide: "#jusha1,#action>ul>li:nth-child(n+2):nth-child(-n+3)",
        category: "comic autoPager"
    }, {
        name: "来漫画",
        url: {
            h: "www.laimanhua.org",
            p: "/chapter/",
            d: "pc"
        },
        imgs: ".imgbox img",
        button: [4],
        insertImg: [".imgbox", 2],
        autoDownload: [0],
        next: "//a[text()='下一话']",
        prev: "//a[text()='上一话']",
        customTitle: () => fn.gt(".breadcrumb_crumbItem:nth-child(3)") + " - " + fn.gt(".breadcrumb_crumbItem:nth-child(4)"),
        category: "comic"
    }, {
        name: "来漫画M",
        url: {
            h: "m.laimanhua.org",
            p: "/chapter/",
            d: "m"
        },
        imgs: ".imgbox img",
        button: [4],
        insertImg: [".imgbox", 2],
        autoDownload: [0],
        next: "//a[text()='下一话']",
        prev: "//a[text()='上一话']",
        customTitle: () => {
            let text = fn.ge("meta[name=keywords]").content;
            text = text.replace(/^[^,]+,/, "");
            text = text.replace("漫画", " - ");
            return fn.dt({
                t: text,
                d: "在线观看 - 来漫画"
            })
        },
        category: "comic"
    }, {
        name: "漫客栈",
        enable: 0,
        url: {
            h: "www.mkzhan.com",
            p: /^\/\d+\/\d+\.html/
        },
        fetchJson: async (lp = new URL(siteUrl).pathname) => {
            let lps = lp.split("/");
            let comic_id = lps[1];
            let [chapter_id] = lps[2].match(/\d+/);
            let apiUrl = `https://comic.mkzcdn.com/chapter/content/v1/?chapter_id=${chapter_id}&comic_id=${comic_id}&format=1&quality=1&type=1`;
            return fetch(apiUrl).then(res => res.json());
        },
        init: async () => {
            let json = await _this.fetchJson();
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: (json = siteJson) => json.code == 302 ? [] : json.data.page.map(e => e.image),
        insertImg: ["#pages-tpl", 2],
        autoDownload: [0],
        next: ".rd-aside a.j-rd-next",
        prev: ".rd-aside a.j-rd-prev",
        autoClick: "//div[@class='rd-aside__item j-rd-mod'][span[text()='卷轴']]",
        customTitle: (dom = document) => fn.title(" - ", 1, dom),
        preloadNext: async (nextDoc, obj) => {
            let json = await obj.fetchJson(new URL(nextLink).pathname);
            fn.picPreload(obj.imgs(json), obj.customTitle(nextDoc), "next");
        },
        category: "comic"
    }, {
        name: "好国漫",
        host: ["www.haoguoman.net", "m.haoguoman.net"],
        enable: 1,
        url: {
            h: "haoguoman.net",
            p: /^\/\d+\/\d+\.html$/,
            i: 0
        },
        init: async () => {
            await fn.wait(() => !!_unsafeWindow?.layui?.jecms?.base64?.decode);
            fn.createImgBox("#pic-list", 2);
            let code = fn.gst("params");
            let [, dataBase64] = code.match(/params[\s='"]+([^'"]+)/);
            dataBase64 = dataBase64.replace(_unsafeWindow.layui.jecms.base64.decode("WXhVcHFHcnM1JDN3WWc="), "");
            let dataJson = JSON.parse(_unsafeWindow.layui.jecms.base64.decode(dataBase64));
            siteJson = dataJson;
        },
        imgs: () => siteJson.chapter_images.split("###").map(url => {
            if (!(/^http(s)?:\/\/.+/.test(url)) || url.startsWith("//")) {
                url = siteJson.cdnurl + (url.startsWith("/") ? "" : "/") + url;
            }
            return url;
        }),
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 2],
        autoDownload: [0],
        next: "a.j-next,a.j-next_btn",
        prev: "a.j-rd-prev,a.j-prev_btn",
        customTitle: () => siteJson.comic_name + " - " + siteJson.chapter_title,
        hide: "#pic-list,#loading,ins",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "好国漫 自動翻頁",
        enable: 1,
        url: {
            h: "haoguoman.net",
            p: /^\/\d+\/\d+\.html$/,
            i: 1
        },
        json: (dom = document) => {
            let code = fn.gst("params", dom);
            let [, dataBase64] = code.match(/params[\s='"]+([^'"]+)/);
            dataBase64 = dataBase64.replace(_unsafeWindow.layui.jecms.base64.decode("WXhVcHFHcnM1JDN3WWc="), "");
            let dataJson = JSON.parse(_unsafeWindow.layui.jecms.base64.decode(dataBase64));
            siteJson = dataJson;
            return dataJson;
        },
        getSrcs: (dom) => {
            let json = _this.json(dom);
            let srcs = json.chapter_images.split("###").map(url => {
                if (!(/^http(s)?:\/\/.+/.test(url)) || url.startsWith("//")) {
                    url = json.cdnurl + (url.startsWith("/") ? "" : "/") + url;
                }
                return url;
            });
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            await fn.wait(() => !!_unsafeWindow?.layui?.jecms?.base64?.decode);
            let tE = fn.createImgBox("#pic-list", 2);
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: "a.j-next,a.j-next_btn",
            re: ".breadcrumb,#floatbtn>a.j-rd-prev,#floatbtn>a.j-next",
            title: () => siteJson.chapter_title,
            preloadNextPage: 1
        },
        hide: "#pic-list,#loading,ins",
        category: "comic autoPager"
    }, {
        name: "漫画屋格式",
        host: ["www.mhua5.com", "www.mhw1.com", "www.cmh5.com", "www.umh5.com", "www.obq8.com", "www.wujinmh.com", "comics.veryim.com"],
        enable: 0,
        reg: [
            /^https?:\/\/(www\.mhua5\.com|www\.mhw\d?\.com|www\.cmh5\.com|www\.umh5\.com)\/index\.php\/chapter\/\d+/i,
            /^https?:\/\/www\.manshiduo\.net\/chapter_\d+\.html$/i,
            /^https?:\/\/www\.obq8\.com\/index\.php\/chapter-\d+.html$/i,
            /^https?:\/\/www\.wujinmh\.com\/\d+-\d+\.html$/i,
            /^https?:\/\/comics\.veryim\.com\/\w+\/\d+\/\d+\.html$/
        ],
        include: ".rd-article-wr",
        init: "document.onkeydown=null;",
        imgs: (dom = document) => fn.getImgSrcArr("img[data-original]:not([data-original*='/template/pc/default/']),.lazy-read:not([data-original*='/template/pc/default/']),img[data-src]", dom),
        button: [4],
        insertImg: [".rd-article-wr", 2],
        endColor: "white",
        autoDownload: [0],
        //next: ".btn--next-chapter,.rd-aside a.j-rd-next",
        next: () => {
            let next1 = fn.ge("a.j-rd-next[_href]:not([style])");
            let next2 = fn.ge("a.j-rd-next[href]:not([href^=java])");
            if (next1) {
                let href = fn.attr("a.j-rd-next[_href]", "_href");
                return href == "" ? null : location.origin + href;
            } else if (next2) {
                return next2.href;
            }
            return null;
        },
        prev: ".rd-aside a.j-rd-prev",
        autoClick: "//div[@class='rd-aside__item j-rd-mod'][span[text()='卷轴']]",
        customTitle: (dom = document) => {
            if (/www\.mhua5\.com|www\.mhw\d\.com/.test(fn.lh)) {
                return fn.title(" - 漫画屋", 0, dom).replace("-", " - ");
            } else if (/www\.cmh5\.com/.test(fn.lh)) {
                return fn.attr("meta[name=description]", "content", dom).split(" - 漫画屋")[0].replace("当前阅读的是", "").replace("的", " - ");
            } else if (/www\.umh5\.com|www\.biqug\.org/.test(fn.lh)) {
                return fn.gt(".j-comic-title", 1, dom) + " - " + fn.gt(".last-crumb", 1, dom);
            } else {
                return fn.title(/下拉|在线/, 1, dom).replace("-", " - ").replace(/漫画|\[\d+P\]/i, "");
            }
        },
        preloadNext: true,
        category: "comic"
    }, {
        name: "漫画屋M格式",
        host: ["m.mkzhan.com", "www.mhua5.com", "www.mhw1.com", "www.cmh5.com", "www.umh5.com", "www.biqug.org", "m.wujinmh.com", "wap.veryim.com"],
        enable: 0,
        reg: [
            /^https?:\/\/m\.mkzhan\.com\/\d+\/\d+\.html$/i,
            /^https?:\/\/(www\.mhua5\.com|www\.mhw\d?\.com|www\.cmh5\.com|www\.umh5\.com)\/index\.php\/chapter\/\d+/i,
            /^https?:\/\/www\.biqug\.org\/index\.php\/chapter-\d+.html$/i,
            /^https?:\/\/m\.wujinmh\.com\/\d+-\d+\.html$/i,
            /^https?:\/\/wap\.veryim\.com\/\w+\/\d+\/\d+\.html$/i,
            /^https?:\/\/www\.51manhua\.buzz\/chapter\/\d+$/i
        ],
        imgs: (dom = document) => fn.getImgSrcArr(".comic-page img,img[data-src],img[data-original]", dom),
        autoDownload: [0],
        next: async () => {
            if (/www\.mhua5\.com|www\.cmh5\.com|www\.umh5\.com|www\.mhw\d\.com|www\.biqug\.org|www\.cmh5\.com|(www\.)?51manhua\.buzz/.test(fn.lh)) {
                let next = fn.attr(".next-chapter", "_href");
                return next !== "" ? location.origin + next : null;
            } else if (/m\.mkzhan\.com/.test(fn.lh)) {
                await fn.waitEle(".next-chapter[data-href]", 10)
                let next = fn.ge(".next-chapter").dataset.href;
                return next !== "" || next != 0 ? location.origin + next : null;
            } else {
                let next = fn.ge("//a[text()='下一章']");
                return next ? next.href : null;
            }
        },
        prev: 1,
        customTitle: (dom = document) => {
            if (/www\.mhua5\.com|www\.cmh5\.com/.test(fn.lh)) {
                return fn.title(" - 漫画屋", 0, dom).replace("-", " - ");
            } else if (/m\.mkzhan\.com/.test(fn.lh)) {
                return fn.title(" - 漫客栈", 0, dom).trim();
            } else if (/www\.umh5\.com|www\.mhw\d\.com|www\.biqug\.org|m\.cuiman\.com|(www\.)?51manhua\.buzz/.test(fn.lh)) {
                return _unsafeWindow.shareArr[0].match(/《([^》]+)/)[1] + " - " + fn.gt(".comic-name", 1, dom);
            } else {
                return fn.title(/下拉|在线/, 1, dom).trim().replace("-", " - ");
            }
        },
        preloadNext: (nextDoc, obj) => fn.iframeDoc(nextLink, ".comic-page img,img[data-src],img[data-original],canvas[data-src]", 30000).then(nextIframeDoc => fn.picPreload(obj.imgs(nextIframeDoc), obj.customTitle(nextIframeDoc), "next")),
        hide: "body>ins,#mainView>.read,.chapter-end .read,#chapter1,#chapter3,.cnt-4,.comic-list a,.chapter-end>a,div[style^=height],body>div[id][style]:has(>div[style]),.comic-list>div[id][style]:has(>div[style]),#mainView>div[id][style]:has(>div[style]),.chapter-end>div[id][style]:has(>div[style])",
        category: "comic"
    }, {
        name: "新新漫画",
        host: ["www.77mh.nl", "m.77mh.nl", "www.77mh.xyz", "m.77mh.xyz", "www.77mh.me", "m.77mh.me"],
        enable: 0,
        url: {
            h: ".77mh.",
            p: /^\/\d+\/\d+\.html/
        },
        init: async () => await fn.waitVar("msg"),
        imgs: async () => {
            let status;
            if (fn.ge(".FullPictureLoadImage")) {
                status = 200;
            } else {
                let src = fn.attr("#comicImg img,.mg-co img", "src");
                status = await fn.xhrHEAD(src).then(res => res.status);
            }
            return status === 200 ? _unsafeWindow.msg.split("|").map(e => fn.lh.includes("m.77mh") ? _unsafeWindow.ImgSvrList + e : _unsafeWindow.img_qianz + e) : [];
        },
        button: [4],
        insertImg: ["#comicImg,.mg-co", 2],
        insertImgAF: () => {
            if (fn.lh.includes("m.77mh")) {
                let p = fn.ge(".page_num");
                let m = fn.ge(".mg-co");
                p ? insertAfter(m, p.cloneNode(true)) : null;
                let selectors = [".pagelist", "//div[div[@style and a[img[@width]]]]"];
                fn.remove(selectors);
            } else {
                let str = "try{$(document).unbind('keydown');$(document).unbind('keyup')}catch(e){}";
                new Function(str)();
                let p = fn.ge("#pnpage");
                let m = fn.ge("#main");
                p ? insertAfter(m, p.cloneNode(true)) : null;
                let selectors = [".qrcode_div", "#bdcotopnew", "#main>*:not(#comicImg)"];
                fn.remove(selectors);
            }
        },
        autoDownload: [0],
        next: () => {
            const {
                nextLink_b
            } = _unsafeWindow;
            return nextLink_b == "" ? null : location.origin + nextLink_b;
        },
        prev: "//a[contains(text(),'上一章')]",
        customTitle: (dom = document) => fn.title(" - ", 3, dom),
        preloadNext: async (nextDoc, obj) => {
            let code = fn.gst("eval", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(await obj.imgs(), obj.customTitle(nextDoc), "next");
        },
        category: "comic"
    }, {
        name: "漫漫聚/KuKu动漫",
        enable: 1,
        url: {
            h: [
                "www.manmanju.cc",
                "a.manmanju.cc",
                "b.manmanju.cc",
                "manhua.dididm.cc",
                "a.ikukudm.cc",
                "b.ikukudm.cc"
            ],
            p: /^\/comiclist\/\d+\/\d+\/1\.htm$/,
            i: 0
        },
        include: "td img",
        comicListUrl: () => `/comiclist/${siteUrl.split("/")[4]}/index.htm`,
        imgs: () => fn.getKukudmSrc(),
        button: [4],
        insertImg: ["//td[input]", 2],
        insertImgAF: async () => {
            let cUrl = _this.comicListUrl();
            let nextUrl = await _this.next();
            if (nextUrl) {
                fn.addUrlHtml(nextUrl, "body", 2);
                fn.addUrlHtml(cUrl, "body", 2, "目錄");
            } else {
                fn.addUrlHtml(cUrl, "body", 2, "目錄");
                fn.addUrlHtml(location.origin, "body", 2, "首頁");
            }
        },
        autoDownload: [0],
        next: () => {
            let chapterId = siteUrl.split("/")[5];
            let host = 1;
            if (/^a\./.test(fn.lh)) {
                host = 2;
            } else if (/^b\./.test(fn.lh)) {
                host = 3;
            }
            let nextXPath = `//dd[a[contains(@href,'${chapterId}')]]/following-sibling::dd[1]/a[${host}]`;
            return fn.xhrDoc(_this.comicListUrl()).then(dom => {
                let next = fn.ge(nextXPath, dom, dom);
                return next ? next.href : null;
            })
        },
        prev: 1,
        preloadNext: async (nextDoc, obj) => fn.picPreload(await fn.getKukudmSrc(nextLink, nextDoc, 0), nextDoc.title, "next"),
        css: "body{background-image:unset}body>table:nth-child(2),body>table:nth-child(2)>tbody>tr>td{width:100%!important;}body{scrollbar-width:none;-ms-overflow-style:none;overflow-x:hidden;overflow-y:auto}",
        hide: "body>table:nth-child(1),body>table:nth-child(3)",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "漫漫聚/KuKu动漫 自動翻頁",
        url: {
            h: [
                "www.manmanju.cc",
                "a.manmanju.cc",
                "b.manmanju.cc",
                "manhua.dididm.cc",
                "a.ikukudm.cc",
                "b.ikukudm.cc"
            ],
            p: /^\/comiclist\/\d+\/\d+\/1\.htm$/,
            i: 1
        },
        include: "td img",
        comicListUrl: () => `/comiclist/${siteUrl.split("/")[4]}/index.htm`,
        init: async () => {
            fn.showMsg(displayLanguage.str_135, 0);
            await fn.getKukudmSrc(siteUrl, document, 0).then(srcs => fn.createImgArray(srcs)).then(async imgs => {
                let tE = fn.ge("//td[input]");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
            let cUrl = _this.comicListUrl();
            fn.addUrlHtml(cUrl, "body", 2, "目錄");
            fn.addUrlHtml(location.origin, "body", 2, "首頁");
        },
        autoPager: {
            ele: (dom) => fn.getKukudmSrc(nextLink, dom, 0).then(srcs => fn.createImgArray(srcs)),
            pos: ["//td[img]", 0],
            observer: "//td[img]/img",
            next: () => {
                let chapterId = (nextLink ?? siteUrl).split("/")[5];
                let host = 1;
                if (/^a\./.test(fn.lh)) {
                    host = 2;
                } else if (/^b\./.test(fn.lh)) {
                    host = 3;
                }
                let nextXPath = `//dd[a[contains(@href,'${chapterId}')]]/following-sibling::dd[1]/a[${host}]`;
                return fn.xhrDoc(_this.comicListUrl()).then(dom => {
                    let next = fn.ge(nextXPath, dom, dom);
                    return next ? next.href : null;
                })
            },
            stop: (dom) => !fn.ge("//td[input]//img", dom),
            preloadNextPage: async (dom) => {
                let next = await _this.autoPager.next();
                if (!!next) {
                    fn.xhrDoc(next).then(async nextDoc => {
                        let srcs = await fn.getKukudmSrc(next, nextDoc, 0);
                        fn.picPreload(srcs, nextDoc.title, "next");
                    });
                }
            }
        },
        css: "body{background-image:unset}body>table:nth-child(2),body>table:nth-child(2)>tbody>tr>td{width:100%!important;}body{scrollbar-width:none;-ms-overflow-style:none;overflow-x:hidden;overflow-y:auto}",
        hide: "body>table:nth-child(1),body>table:nth-child(3)",
        category: "comic autoPager"
    }, {
        name: "漫漫聚M/KuKu动漫M",
        enable: 1,
        url: {
            h: [
                "m.manmanju.cc",
                "s1.m.manmanju.cc",
                "s2.m.manmanju.cc",
                "s3.m.manmanju.cc",
                "m.dididm.cc",
                "wap.dididm.cc",
                "s1.wap.ikukudm.cc",
                "s2.wap.ikukudm.cc",
                "s3.wap.ikukudm.cc"
            ],
            p: /^\/comiclist\/\d+\/\d+\/1\.htm$/,
            i: 0
        },
        include: ".classBox img,.imgBox",
        init: () => fn.remove("//center[iframe]"),
        imgs: () => {
            fn.remove("//a[img] | //ul[center[li]]");
            return fn.getKukudmSrc();
        },
        button: [4],
        insertImg: [".imgBox", 2],
        insertImgAF: async () => {
            fn.remove(".bottom .subNav~div[style*=height],.bottom .pageLine,.bottom .subNav");
            let nav = fn.ge("ul.subNav").cloneNode(true);
            let tE = fn.ge("div.bottom");
            insertBefore(tE, nav);
            await fn.remove("meta[name=viewport]");
            const meta = document.createElement("meta");
            meta.name = "viewport";
            meta.content = "width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=2.0,user-scalable=no";
            document.head.append(meta);
            let url = await _this.next();
            if (url) fn.addUrlHtml(url, ".bottom", 0);
        },
        autoDownload: [0],
        next: () => {
            let comicListUrl = fn.gu(".subNav a");
            let chapterId = siteUrl.split("/")[5];
            let nextXPath = `//li[a[contains(@href,'${chapterId}')]]/preceding-sibling::li[1]/a`;
            return fn.xhrDoc(comicListUrl).then(dom => {
                let next = fn.ge(nextXPath, dom, dom);
                return next ? next.href : null;
            })
        },
        prev: 1,
        customTitle: () => fn.title("在线", 1),
        preloadNext: async (nextDoc, obj) => fn.picPreload(await fn.getKukudmSrc(nextLink, nextDoc, 0), nextDoc.title.split("在线")[0], "next"),
        css: ".imgBox{margin-bottom:0px!important}.subNav{border-top:1px solid #dcdcde}body{scrollbar-width:none;overflow-x:hidden;overflow-y:auto}",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "漫漫聚/KuKu动漫M 404",
        enable: 1,
        url: {
            h: [
                "m.manmanju.cc",
                "s1.m.manmanju.cc",
                "s2.m.manmanju.cc",
                "s3.m.manmanju.cc",
                "m.dididm.cc",
                "wap.dididm.cc",
                "s1.wap.ikukudm.cc",
                "s2.wap.ikukudm.cc",
                "s3.wap.ikukudm.cc"
            ],
            p: /^\/comiclist\/\d+\/\d+\/1\.htm$/,
            e: [
                "td img",
                "iframe[src='/top.htm']"
            ],
            i: 0
        },
        comicListUrl: () => `/comiclist/${siteUrl.split("/")[4]}/index.htm`,
        imgs: () => fn.getKukudmSrc(),
        button: [4],
        insertImg: ["//td[input]", 2],
        insertImgAF: async () => {
            let cUrl = _this.comicListUrl();
            let nextUrl = await _this.next();
            if (nextUrl) {
                fn.addUrlHtml(nextUrl, "body", 2);
                fn.addUrlHtml(cUrl, "body", 2, "目錄");
            } else {
                fn.addUrlHtml(cUrl, "body", 2, "目錄");
                fn.addUrlHtml(location.origin, "body", 2, "首頁");
            }
        },
        autoDownload: [0],
        next: () => {
            let chapterId = siteUrl.split("/")[5];
            let nextXPath = `//li[a[contains(@href,'${chapterId}')]]/preceding-sibling::li[1]/a`;
            return fn.xhrDoc(_this.comicListUrl()).then(dom => {
                let next = fn.ge(nextXPath, dom, dom);
                return next ? next.href : null;
            })
        },
        prev: 1,
        preloadNext: async (nextDoc, obj) => fn.picPreload(await fn.getKukudmSrc(nextLink, nextDoc, 0), nextDoc.title.split("在线")[0], "next"),
        css: "body{background-image:unset}body>table:nth-child(2),body>table:nth-child(2)>tbody>tr>td{width:100%!important;}body{scrollbar-width:none;-ms-overflow-style:none;overflow-x:hidden;overflow-y:auto}",
        hide: "body>table:nth-child(1),body>table:nth-child(3)",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "漫漫聚M/KuKu动漫M 自動翻頁",
        url: {
            h: [
                "m.manmanju.cc",
                "s1.m.manmanju.cc",
                "s2.m.manmanju.cc",
                "s3.m.manmanju.cc",
                "m.dididm.cc",
                "wap.dididm.cc",
                "s1.wap.ikukudm.cc",
                "s2.wap.ikukudm.cc",
                "s3.wap.ikukudm.cc"
            ],
            p: /^\/comiclist\/\d+\/\d+\/1\.htm$/,
            i: 1
        },
        include: ".classBox img,.imgBox",
        init: async () => {
            fn.remove("//center[iframe] | //a[img] | //ul[center[li[@class='txtA']]]");
            fn.showMsg(displayLanguage.str_135, 0);
            await fn.getKukudmSrc(siteUrl, document, 0).then(srcs => fn.createImgArray(srcs)).then(async imgs => {
                let tE = fn.ge(".imgBox");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
            fn.remove(".bottom .subNav~div[style*=height],.bottom .pageLine,.bottom .subNav");
            let nav = fn.ge("ul.subNav").cloneNode(true);
            let tE = fn.ge("div.bottom");
            insertBefore(tE, nav);
            await fn.remove("meta[name=viewport]");
            const meta = document.createElement("meta");
            meta.name = "viewport";
            meta.content = "width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=2.0,user-scalable=no";
            document.head.append(meta);
        },
        autoPager: {
            ele: (dom) => fn.getKukudmSrc(nextLink, dom, 0).then(srcs => fn.createImgArray(srcs)),
            pos: [".imgBox", 0],
            observer: ".imgBox>img",
            next: () => {
                let comicListUrl = fn.gu(".subNav a");
                let chapterId = (nextLink ?? siteUrl).split("/")[5];
                let nextXPath = `//li[a[contains(@href,'${chapterId}')]]/preceding-sibling::li[1]/a`;
                return fn.xhrDoc(comicListUrl).then(dom => {
                    let next = fn.ge(nextXPath, dom, dom);
                    return next ? next.href : null;
                })
            },
            title: (dom) => {
                let text = dom.title.replace(/在线漫画.+$/, "");
                if (hasTouchEvent) {
                    return text.split(" ").at(-1);
                } else {
                    return text;
                }
            },
            preloadNextPage: async (dom) => {
                let next = await _this.autoPager.next();
                if (!!next) {
                    fn.xhrDoc(next).then(async nextDoc => {
                        let srcs = await fn.getKukudmSrc(next, nextDoc, 0);
                        let text = _this.autoPager.title(nextDoc);
                        fn.picPreload(srcs, text, "next");
                    });
                }
            }
        },
        css: ".imgBox{margin-bottom:0px!important}.subNav{border-top:1px solid #dcdcde}body{scrollbar-width:none;overflow-x:hidden;overflow-y:auto}",
        category: "comic autoPager"
    }, {
        name: "仙漫网",
        enable: 0,
        url: {
            h: "www.gaonaojin.com",
            p: /^\/\w+\/\d+\.html/
        },
        imgs: (url = fn.url) => {
            const {
                imgDomain,
                picdata
            } = _unsafeWindow;
            if (imgDomain === "") {
                url = url.replace("www.gaonaojin.com", "m.gaonaojin.com");
                fn.showMsg(displayLanguage.str_05, 0);
                return fn.xhrDoc(url, {
                    headers: {
                        "Referer": url,
                        "User-Agent": Mobile_UA
                    }
                }).then(dom => {
                    let code = fn.gst("eval", dom).match(/eval.+\)\)/)[0].slice(4);
                    let imgData = fn.run(fn.run(code).match(/picdata[^;]+/)[0]);
                    return imgData.map(e => "https://res.xiaoqinre.com/" + e);
                });
            } else if (imgDomain === "https://res.xiaoqinre.com/") {
                return picdata.map(e => imgDomain + e);
            } else {
                return [];
            }
        },
        button: [4],
        insertImg: [".comicpage", 2],
        insertImgAF: () => nextLink ? fn.addUrlHtml(nextLink, ".comicpage", 1) : null,
        autoDownload: [0],
        next: "//li[a[@class='active']]/preceding-sibling::li[1]/a",
        prev: "//li[a[@class='active']]/following-sibling::li[1]/a",
        customTitle: "h1.title",
        preloadNext: async (nextDoc, obj) => {
            let url = nextLink.replace("www.gaonaojin.com", "m.gaonaojin.com");
            let arr = await fn.xhrDoc(url, {
                headers: {
                    "Referer": url,
                    "User-Agent": Mobile_UA
                }
            }).then(dom => {
                let code = fn.gst("eval", dom).match(/eval.+\)\)/)[0].slice(4);
                let imgData = fn.run(fn.run(code).match(/picdata[^;]+/)[0]);
                return imgData.map(e => "https://res.xiaoqinre.com/" + e);
            });
            fn.picPreload(arr, nextDoc.title, "next");
        },
        hide: ".dropload-down",
        category: "comic"
    }, {
        name: "仙漫网M",
        enable: 1,
        url: {
            h: "m.gaonaojin.com",
            p: /^\/\w+\/\d+\.html/,
            i: 0
        },
        init: () => fn.createImgBox("#cp_img", 2),
        imgs: (dom = document) => {
            let code = fn.gst("eval", dom).match(/eval.+\)\)/)[0].slice(4);
            let imgData = fn.run(fn.run(code).match(/picdata[^;]+/)[0]);
            return imgData.map(e => "https://res.xiaoqinre.com/" + e);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#cp_img"], 2
        ],
        autoDownload: [0],
        next: "a.btn.next",
        prev: "a.btn.prev",
        customTitle: (dom = document) => fn.title("免费", 1, dom),
        preloadNext: true,
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "仙漫网M 自動翻頁",
        url: {
            h: "m.gaonaojin.com",
            p: /^\/\w+\/\d+\.html/,
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("eval", dom).match(/eval.+\)\)/)[0].slice(4);
            let imgData = fn.run(fn.run(code).match(/picdata[^;]+/)[0]);
            let srcs = imgData.map(e => "https://res.xiaoqinre.com/" + e);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let tE = fn.createImgBox("#cp_img", 2);
            await fn.remove("#cp_img");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: "a.btn.next",
            re: "#title+#title,.pagenation",
            title: (dom) => fn.gt("#title+#title", 1, dom),
            hide: ".recommendList:has(h2)",
            bF: (dom) => fn.gae(".pagenation", dom).forEach(e => e.setAttribute("class", "pagenation")),
            preloadNextPage: 1
        },
        hide: "#cp_img>div[style]",
        category: "comic autoPager"
    }, {
        name: "大树漫画/世伦漫画",
        enable: 1,
        url: {
            h: ["www.dashumanhua.com", "www.shilunart.com"],
            p: /^\/comic\/\w+\/.+\.html/i,
            i: 0
        },
        imgs: (dom = document) => {
            let code = fn.gst("picTree", dom);
            let m = code.match(/eval.+\)\)/)[0].slice(4);
            return fn.run(fn.run(m).slice(12, -1));
        },
        button: [4],
        insertImg: ["#pic-list", 2],
        autoDownload: [0],
        next: "//a[text()='下一话' and not(contains(@href,'--1'))]",
        prev: "//a[text()='上一话' and not(contains(@href,'--1'))]",
        customTitle: (dom = document) => fn.gt(".setnmh-bookname h1", 1, dom) + " - " + fn.gt(".setnmh-bookname h2", 1, dom),
        preloadNext: true,
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "大树漫画/世伦漫画 自動翻頁",
        enable: 1,
        url: {
            h: ["www.dashumanhua.com", "www.shilunart.com"],
            p: /^\/comic\/\w+\/.+\.html/i,
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("picTree", dom);
            let m = code.match(/eval.+\)\)/)[0].slice(4);
            let srcs = fn.run(fn.run(m).slice(12, -1));
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let tE = fn.createImgBox("#pic-list", 2);
            fn.remove("#pic-list,.loading-box");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: "//a[text()='下一话' and not(contains(@href,'--1'))]",
            re: ".setnmh-headsee,.setnmh-controlbottomn>.prev,.setnmh-controlbottomn>.huiname,.setnmh-controlbottomn>.next",
            aF: () => {
                let n = fn.ge(".next>.tandiv>a");
                if (n) {
                    fn.ge(".next>a").href = n.href;
                    fn.remove(".next>a+span,a[v-if=booknext]+span");
                } else {
                    fn.ge(".next>a").classList.add("hui");
                    fn.remove("div[v-if=booknext]");
                }
            },
            title: (dom) => {
                if (hasTouchEvent) {
                    return fn.gt(".setnmh-bookname h2", 1, dom);
                } else {
                    return fn.gt(".setnmh-bookname h1", 1, dom) + " - " + fn.gt(".setnmh-bookname h2", 1, dom);
                }
            },
            hide: ".setnmh-detailspage,#setnmh-footer>nav",
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "韩漫天堂",
        enable: 1,
        url: {
            h: ["www.hmttmh.com", "w226.npdn.top"],
            p: "/chapter/",
            e: "#comicContain",
            i: 0
        },
        init: async () => {
            await fn.waitVar("newImgs");
            _unsafeWindow.newImgs = [];
            fn.createImgBox("#comicContain", 2);
        },
        imgs: (dom = document) => {
            let newImgsCode = fn.gst("newImgs", dom);
            newImgsCode = fn.run(newImgsCode.replace("\n", "").trim().slice(4));
            newImgsCode = newImgsCode.replace("var newImgs=", "");
            let newImgsArr = fn.run(newImgsCode);
            return newImgsArr;
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#comicContain"], 2
        ],
        autoDownload: [0],
        next: "a:has(>img[alt=下一章])",
        prev: "a:has(>img[alt=上一章])",
        customTitle: (dom = document) => fn.ge("meta[itemprop=name]", dom)?.content + " - " + fn.ge("meta[itemprop=chaptername]", dom)?.content,
        preloadNext: true,
        infiniteScroll: true,
        //css: "#FullPictureLoadMainImgBox{max-width: 800px;}",
        category: "comic"
    }, {
        name: "韩漫天堂 自動翻頁",
        enable: 1,
        url: {
            h: ["www.hmttmh.com", "w226.npdn.top"],
            p: "/chapter/",
            e: "#comicContain",
            i: 1
        },
        getSrcs: (dom) => {
            let newImgsCode = fn.gst("newImgs", dom);
            newImgsCode = fn.run(newImgsCode.replace("\n", "").trim().slice(4));
            newImgsCode = newImgsCode.replace("var newImgs=", "");
            let srcs = fn.run(newImgsCode);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            await fn.waitVar("newImgs");
            _unsafeWindow.newImgs = [];
            let tE = fn.createImgBox("#comicContain", 2);
            fn.remove("#comicContain");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: (dom) => {
                let next = fn.ge("a:has(>img[alt=下一章])", dom);
                if (next) {
                    let [, nextId] = next.href.match(/(\d+)\.html$/);
                    return fn.lp.replace(/(\d+)(\.html)$/, `${nextId}$2`);
                } else {
                    return null;
                }
            },
            re: ".main_control",
            title: (dom) => fn.ge("meta[itemprop=chaptername]", dom)?.content,
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "韩漫天堂M",
        enable: 1,
        url: {
            h: ["www.hmttmh.com", "w226.npdn.top"],
            p: "/chapter/",
            e: "#mainView_img",
            i: 0
        },
        init: () => fn.createImgBox("#mainView_img", 2),
        imgs: (dom = document) => {
            let imgsCode = fn.gst("original", dom);
            imgsCode = imgsCode.replace("\n", "").trim().slice(4);
            imgsCode = fn.run(imgsCode);
            return imgsCode.match(/https?:\/\/[^/]+\/\w+\/\d+\/[\w-]+\.\w+/gi);
        },
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#mainView_img"], 2
        ],
        insertImgAF: () => {
            const $ = _unsafeWindow.jQuery;
            $("#FullPictureLoadMainImgBox").click(() => {
                $(".reader-footer").fadeToggle(300);
                $(".van-nav-bar").fadeToggle(300);
            });
        },
        autoDownload: [0],
        next: ".end-itm.next>a",
        prev: ".end-itm.prev>a",
        customTitle: (dom = document) => fn.ge("#mainView_img img", dom)?.alt?.replace("-图1", ""),
        preloadNext: true,
        infiniteScroll: true,
        fancybox: {
            blacklist: 1
        },
        category: "comic"
    }, {
        name: "韩漫天堂M 自動翻頁",
        enable: 1,
        url: {
            h: ["www.hmttmh.com", "w226.npdn.top"],
            p: "/chapter/",
            e: "#mainView_img",
            i: 1
        },
        getSrcs: (dom) => {
            let imgsCode = fn.gst("original", dom);
            imgsCode = imgsCode.replace("\n", "").trim().slice(4);
            imgsCode = fn.run(imgsCode);
            let srcs = imgsCode.match(/https?:\/\/[^/]+\/\w+\/\d+\/[\w-]+\.\w+/gi);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            const $ = _unsafeWindow.jQuery;
            let tE = fn.createImgBox("#mainView_img", 2);
            fn.remove("#mainView_img");
            let imgs = _this.getImgs();
            fragment.append(...imgs);
            tE.append(fragment);
            $("#FullPictureLoadMainImgBox").click(() => {
                $(".reader-footer").fadeToggle(300);
                $(".van-nav-bar").fadeToggle(300);
            });
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: (dom) => {
                let next = fn.ge(".end-itm.next>a", dom);
                if (next) {
                    let [, nextId] = next.href.match(/(\d+)\.html$/);
                    return fn.lp.replace(/(\d+)(\.html)$/, `${nextId}$2`);
                } else {
                    return null;
                }
            },
            re: ".end-btns",
            title: (dom) => fn.ge("meta[itemprop=chaptername]", dom)?.content,
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "Godamanga.ART 英文漫画",
        enable: 1,
        url: {
            h: ["godamh.org"],
            p: /^\/chapter\/\d+\.html$/i,
            i: 0
        },
        init: async () => {
            await fn.waitEle(".touch-manipulation img");
            let setdata = JSON.parse(document.cookie.match(/setdata[\s=]+([^;]+)/)[1]);
            let {
                host,
                ms,
                cs
            } = setdata;
            let api = `${host}/chapter/getinfo?m=${ms}&c=${cs}`;
            await fn.fetchDoc(api, {
                cache: "no-cache"
            }).then(dom => {
                let obj = {
                    ...fn.ge("#c-imagelist", dom).dataset,
                    ...setdata
                };
                siteJson = obj;
            });
        },
        imgs: () => fn.gae(".touch-manipulation img"),
        button: [4],
        insertImg: [".touch-manipulation", 2],
        autoDownload: [0],
        next: "#nextChapterLink",
        prev: "#preChapterLink",
        customTitle: () => siteJson.title + " - " + siteJson.ctitle,
        preloadNext: (dom) => {
            if ("next" in siteJson) {
                //let api = `${siteJson.host}/chapter/getcontent?m=${siteJson.ms}&c=${siteJson.next}`;
                let api = `${siteJson.host}/chapter/getinfo?m=${siteJson.ms}&c=${siteJson.next}`;
                fn.fetchDoc(api, {
                    cache: "no-cache"
                }).then(nextDom => {
                    let srcs = fn.getImgSrcArr(".touch-manipulation img", nextDom);
                    fn.picPreload(srcs, siteJson.nextt, "next");
                });
            }
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Godamanga.ART 自動翻頁",
        enable: 1,
        url: {
            h: ["godamh.org"],
            p: /^\/chapter\/\d+\.html$/i,
            i: 1
        },
        getData: () => {
            let setdata = JSON.parse(document.cookie.match(/setdata[\s=]+([^;]+)/)[1]);
            let {
                host,
                ms,
                cs
            } = setdata;
            let api;
            if ("next" in siteJson) {
                api = `${host}/chapter/getinfo?m=${ms}&c=${siteJson.next}`;
            } else {
                api = `${host}/chapter/getinfo?m=${ms}&c=${cs}`;
            }
            return fn.fetchDoc(api, {
                cache: "no-cache"
            }).then(dom => {
                let dataset = {
                    ...fn.ge("#c-imagelist", dom).dataset
                };
                siteJson = dataset;
                globalImgArray = fn.getImgSrcArr(".touch-manipulation img", dom);
                customTitle = dataset.title + " - " + dataset.ctitle;
                if ("next" in dataset) {
                    tempNextLink = `${host}/chapter/getinfo?m=${ms}&c=${dataset.next}`;
                    fn.fetchDoc(tempNextLink, {
                        cache: "no-cache"
                    }).then(nextDom => {
                        let srcs = fn.getImgSrcArr(".touch-manipulation img", nextDom);
                        fn.picPreload(srcs, dataset.nextt, "next");
                    });
                } else {
                    tempNextLink = null;
                }
            });
        },
        init: async () => {
            await _this.getData();
            let imgs = fn.createImgArray(globalImgArray);
            await fn.waitEle(".touch-manipulation img");
            let tE = fn.createImgBox(".touch-manipulation", 2);
            await fn.remove(".touch-manipulation");
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: () => fn.createImgArray(globalImgArray),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: () => tempNextLink,
            wait: () => _this.getData(),
            title: () => customTitle,
            hide: "div.justify-center:has(>.w-full),.pb-14",
            history: 0
        },
        category: "comic autoPager"
    }, {
        name: "Godamanga.ART 英文漫画",
        enable: 1,
        url: {
            h: ["manhuascans.org"],
            p: /^\/manga\/[\w-]+\/[\w-]+$/i,
            e: "#chapterContent",
            i: 0
        },
        xhrOptions: {
            cache: "no-cache"
        },
        init: async () => await fn.waitEle(".touch-manipulation img"),
        imgs: () => fn.gae(".touch-manipulation img"),
        button: [4],
        insertImg: [".touch-manipulation", 2],
        autoDownload: [0],
        next: "#nextChapterLink[href^='/manga/']",
        prev: "#preChapterLink",
        customTitle: (dom = document) => fn.gt("ol.inline-flex>li:nth-child(2) a", 1, dom) + " - " + fn.gt("ol.inline-flex>li:nth-child(3) a", 1, dom),
        preloadNext: (dom) => {
            let dataE = fn.ge("#chapterContent", dom);
            let ms = dataE.dataset.ms;
            let cs = dataE.dataset.cs;
            let ct = dataE.dataset.ct;
            let host = dataE.dataset.host;
            let api = `${host}/chapter/getcontent?m=${ms}&c=${cs}`;
            fn.fetchDoc(api).then(nextDom => {
                let srcs = fn.getImgSrcArr(".touch-manipulation img", nextDom);
                fn.picPreload(srcs, ct, "next");
            });
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "Godamanga.ART 英文漫画 自動翻頁",
        enable: 1,
        url: {
            h: ["manhuascans.org"],
            p: /^\/manga\/[\w-]+\/[\w-]+$/i,
            e: "#chapterContent",
            i: 1
        },
        xhrOptions: {
            cache: "no-cache"
        },
        getSrcs: (dom) => {
            let dataE = fn.ge("#chapterContent", dom);
            let ms = dataE.dataset.ms;
            let cs = dataE.dataset.cs;
            let host = dataE.dataset.host;
            let api = `${host}/chapter/getcontent?m=${ms}&c=${cs}`;
            return fn.fetchDoc(api).then(apitDom => fn.getImgSrcArr(".touch-manipulation img", apitDom));
        },
        getImgs: async (dom = document) => {
            let srcs = await _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            await fn.waitEle(".touch-manipulation img");
            let imgs = await _this.getImgs();
            let tE = fn.createImgBox(".touch-manipulation", 2);
            fn.remove("//div[ins[@class='adsbygoogle']]");
            await fn.remove(".touch-manipulation");
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            observer: "#FullPictureLoadMainImgBox>img",
            pos: ["#FullPictureLoadMainImgBox", 0],
            next: "#nextChapterLink[href^='/manga/']",
            title: (dom) => fn.ge("#chapterContent", dom).dataset.ct,
            history: 0,
            hide: "div.justify-center:has(>.w-full),.pb-14",
            preloadNextPage: 1
        },
        category: "comic autoPager"
    }, {
        name: "GODA漫畫/包子漫畫",
        enable: 1,
        url: {
            h: [
                "www.cocolamanhua.com",
                "n.cocolamanhua.com",
                "godamh.com",
                "m.godamh.com",
                "g-mh.org",
                "m.g-mh.org",
                "baozimh.org",
                "m.baozimh.org",
                "baozimh.one",
                "m.baozimh.one",
                "bzmh.org",
                "m.bzmh.org",
                "manhuafree.com"
            ],
            p: /^\/manga\/[\w-]+\/[\w-]+$/i,
            e: "#chapterContent",
            i: 0
        },
        init: async () => {
            fn.addMutationObserver(() => fn.remove("iframe,.bannersUite"));
            await fn.waitEle(".touch-manipulation img");
            fn.remove(["#noad-button,.absolute,.adshow", "//div[ins[@class='adsbygoogle']]"]);
            let chapterDataE = fn.ge("#chapterContent");
            let ms = chapterDataE.dataset.ms
            let cs = chapterDataE.dataset.cs
            let api = `https://api-get-v2.mgsearcher.com/api/chapter/getinfo?m=${ms}&c=${cs}`;
            let fetchJson = await fetch(api, {
                cache: "no-cache"
            }).then(res => res.json());
            siteJson = fetchJson;
        },
        imgs: (json = siteJson) => {
            let {
                line,
                images
            } = json.data.info.images;
            let host = line === 2 ? "https://f40-1-4.g-mh.online" : "https://t40-1-4.g-mh.online";
            return images.map(e => host + e.url);
        },
        button: [4],
        insertImg: [".touch-manipulation", 2],
        autoDownload: [0],
        next: "#nextchaptera[href*='/manga/']",
        prev: "#prevchaptera[href*='/manga/']",
        customTitle: (json = siteJson) => json.data.info.mangatitle + " - " + json.data.info.title,
        preloadNext: () => {
            let next = siteJson.data.info?.next;
            if (!!next) {
                let chapterDataE = fn.ge("#chapterContent");
                let ms = chapterDataE.dataset.ms;
                let api = `https://api-get-v2.mgsearcher.com/api/chapter/getinfo?m=${ms}&c=${next}`;
                fetch(api, {
                    cache: "no-cache"
                }).then(res => res.json()).then(json => {
                    let srcs = _this.imgs(json);
                    let text = _this.customTitle(json);
                    fn.picPreload(srcs, text, "next");
                });
            }
        },
        hide: "iframe,.bannersUite,.w-full:has(>amp-ad),#noad-button,.absolute,.adshow",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "GODA漫畫/包子漫畫 自動翻頁",
        enable: 1,
        url: {
            h: [
                "www.cocolamanhua.com",
                "n.cocolamanhua.com",
                "godamh.com",
                "m.godamh.com",
                "g-mh.org",
                "m.g-mh.org",
                "baozimh.org",
                "m.baozimh.org",
                "baozimh.one",
                "m.baozimh.one",
                "bzmh.org",
                "m.bzmh.org",
                "manhuafree.com"
            ],
            p: /^\/manga\/[\w-]+\/[\w-]+$/i,
            e: "#chapterContent",
            i: 1
        },
        getApi: (mode = "current") => {
            let chapterDataE = fn.ge("#chapterContent");
            let ms = chapterDataE.dataset.ms
            let cs = chapterDataE.dataset.cs
            if (mode === "next") {
                return `https://api-get-v2.mgsearcher.com/api/chapter/getinfo?m=${ms}&c=${siteJson.data.info.next}`;
            } else {
                return `https://api-get-v2.mgsearcher.com/api/chapter/getinfo?m=${ms}&c=${cs}`;
            }
        },
        getSrcs: (json = siteJson) => {
            let {
                line,
                images
            } = json.data.info.images;
            let host = line === 2 ? "https://f40-1-4.g-mh.online" : "https://t40-1-4.g-mh.online";
            return images.map(e => host + e.url);
        },
        getImgs: () => {
            let srcs = _this.getSrcs();
            return fn.createImgArray(srcs);
        },
        init: async () => {
            fn.addMutationObserver(() => fn.remove("iframe,.bannersUite,.w-full:has(>amp-ad)"));
            await fn.waitEle(".touch-manipulation img");
            let api = _this.getApi();
            let fetchJson = await fetch(api, {
                cache: "no-cache"
            }).then(res => res.json());
            siteJson = fetchJson;
            let imgs = _this.getImgs();
            let tE = fn.createImgBox(".touch-manipulation", 2);
            fn.remove(["#noad-button,.absolute,.adshow", "//div[ins[@class='adsbygoogle']]"]);
            await fn.remove(".touch-manipulation");
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            mode: "json",
            ele: () => _this.getImgs(),
            observer: "#FullPictureLoadMainImgBox>img",
            pos: ["#FullPictureLoadMainImgBox", 0],
            next: async () => {
                let next = siteJson?.data?.info?.next;
                if (!!next) {
                    return _this.getApi("next");
                } else {
                    return null;
                }
            },
            title: (json = siteJson) => json.data.info.title,
            history: 0,
            hide: ".justify-center:has(>.border-t),div:has(>.banners),div:has(>div>.cardlist)",
            preloadNextPage: () => {
                let next = siteJson.data.info?.next;
                if (next) {
                    let api = _this.getApi("next");
                    fetch(api, {
                        cache: "no-cache"
                    }).then(res => res.json()).then(json => {
                        let srcs = _this.getSrcs(json);
                        let text = _this.autoPager.title(json);
                        fn.picPreload(srcs, text, "next");
                    });
                }
            }
        },
        hide: "iframe,.bannersUite,.w-full:has(>amp-ad),#noad-button,.absolute,.adshow",
        category: "comic autoPager"
    }, {
        name: "漫画時間 日文漫画",
        enable: 1,
        url: {
            h: "www.mangajikan.com",
            p: "chapter-"
        },
        imgs: ".more-box img",
        button: [4],
        insertImg: [".more-box", 2],
        autoDownload: [0],
        next: "//a[text()='次の章'][starts-with(@href,'/')]",
        prev: "//a[text()='前の章'][starts-with(@href,'/')]",
        customTitle: (dom) => fn.title(" - 無料読み - Manga Jikan", 0, dom),
        preloadNext: true,
        category: "comic"
    }, {
        name: "漫畫屋",
        enable: 0,
        url: {
            h: "mh5.tw",
            p: /^\/(series|seriesvip)-\w+-\d+-\d+/
        },
        imgs: () => {
            let max;
            /seriesvip/.test(siteUrl) ? max = fn.gt("a.cur~a:last-child") - 2 : max = fn.gt("a.cur~a:last-child") - 1;
            return fn.getImgIframe(".ptview>img[alt]:not([style])", max, 13, ".setnmh-pagedos", 1000, 0);
        },
        insertImg: [".ptview", 1, 0],
        autoDownload: [0],
        next: "//a[text()='下一話']",
        prev: "//a[text()='上一話']",
        customTitle: () => {
            let ele = fn.ge("h2");
            return ele ? fn.gt("h1") + " - " + fn.gt("h2") : fn.gt(".setnmh-bookname>a:nth-child(5)") + " - " + fn.gt(".setnmh-bookname>a:nth-child(7)");
        },
        css: ".ptview>img{width:100%!important;height:auto!important;max-width:1000px!important;border:none!important;box-shadow:none!important;padding:0!important;margin:0 auto!important}",
        category: "comic"
    }, {
        name: "山立漫畫/TVBS漫畫",
        enable: 0,
        url: {
            h: ["www.setnmh.com", "www.tvbsmh.com"],
            p: /^\/(series|seriesvip)-\w+-\d+-\d+-.+$/
        },
        imgs: () => {
            let max;
            /seriesvip/.test(siteUrl) ? max = fn.gt("a.cur~a:last-child") - 2 : max = fn.gt("a.cur~a:last-child") - 1;
            return fn.getImgIframe(".ptview>img[alt]:not([style])", max, 13, ".setnmh-pagedos,.pagedosw", 1000, 0);
        },
        insertImg: [".ptview", 1, 0],
        autoDownload: [0],
        next: "//a[text()='下一話']",
        prev: "//a[text()='上一話']",
        customTitle: () => document.title.split(" - ")[0].replace(/正在觀看|(\d+P)/ig, "").replace(">", " - "),
        css: ".ptview>img{width:100%!important;height:auto!important;max-width:1000px!important;border:none!important;box-shadow:none!important;padding:0!important;margin:0 auto!important}",
        category: "comic"
    }, {
        name: "如漫画/读漫屋",
        host: ["www.rumanhua.com", "rumanhua.com", "m.rumanhua.com", "www.dumanwu.com", "dumanwu.com", "m.dumanwu.com"],
        url: {
            h: [/rumanhua\.com$/, /dumanwu\.com$/],
            p: /^\/\w+\/\w+.html$/i,
            i: 0
        },
        imgs: ".main_img img",
        button: [4],
        insertImg: [".main_img", 2],
        autoDownload: [0],
        next: "a[href$=html]:has(>.folat-next1),a[href$=html]:has(>.i-rd-next)",
        prev: "a[href$=html]:has(>.folat-prev1),a[href$=html]:has(>.i-rd-prev)",
        customTitle: (dom = document) => {
            let text = fn.dt({
                t: dom.title,
                d: ["漫画 - 如漫画", "漫画 - 读漫屋"]
            });
            let textArr = text.split("_");
            return textArr[1] + " - " + textArr[0];
        },
        preloadNext: (nextDoc, obj) => {
            fn.iframe(nextLink, {
                waitEle: ".main_img img[data-src]",
                waitVar: "__c0rst96",
                cb: (dom, frame) => {
                    let srcs = fn.getImgSrcArr(obj.imgs, dom);
                    fn.picPreload(srcs, obj.customTitle(dom), "next");
                }
            });
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "如漫画/读漫屋 自動翻頁",
        url: {
            h: [/rumanhua\.com$/, /dumanwu\.com$/],
            p: /^\/\w+\/\w+.html$/i,
            i: 1
        },
        getSrcs: (dom) => fn.getImgSrcArr(".main_img img", dom),
        getImgs: (dom = document) => fn.createImgArray(_this.getSrcs(dom)),
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge(".main_img");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            mode: 1,
            waitEle: ".main_img img[data-src]",
            ele: (dom) => _this.getImgs(dom),
            pos: [".main_img", 0],
            observer: ".main_img>img",
            next: "a[href$=html]:has(>.folat-next1),a[href$=html]:has(>.i-rd-next)",
            re: ".footer-right>a,.main_control,.chaphead,.chapter-end,.chap-footer",
            title: (dom) => {
                let text = fn.dt({
                    t: dom.title,
                    d: " - 如漫画"
                });
                let textArr = text.split("_");
                if (hasTouchEvent) {
                    return textArr[0];
                } else {
                    return textArr[1] + " - " + textArr[0];
                }
            },
            hide: ".mults",
            preloadNextPage: (dom) => {
                let next = fn.ge(_this.autoPager.next, dom);
                if (!!next) {
                    fn.iframe(next.href, {
                        waitEle: ".main_img img[data-src]",
                        waitVar: "__c0rst96",
                        cb: async (dom, frame) => {
                            let srcs = fn.getImgSrcArr(".main_img img", dom);
                            fn.picPreload(srcs, _this.autoPager.title(dom), "next");
                        }
                    });
                }
            }
        },
        hide: "a:has(>.end-novel)",
        category: "comic autoPager"
    }, {
        name: "漫画网",
        host: ["www.manhua3.com", "manhuami.cc"],
        url: {
            e: ["div.logo>a[title=漫画网]>img[alt=漫画网]", "#pics"],
            p: /^\/[\d-]+\.html$/,
            i: 0
        },
        init: () => fn.createImgBox("#pics", 1),
        imgs: (frame = _unsafeWindow) => frame.params.images,
        button: [4],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#pics"], 2
        ],
        autoDownload: [0],
        next: "//a[text()='下一章'][starts-with(@href,'/')]",
        prev: "//a[text()='上一章'][starts-with(@href,'/')]",
        customTitle: (dom = document) => fn.dt({
            t: dom.title,
            d: "在线阅读-漫画网"
        }).replace("_", " - "),
        preloadNext: (nextDoc, obj) => {
            fn.iframeVar(nextLink, "params").then(w => {
                let srcs = obj.imgs(w);
                fn.picPreload(srcs, obj.customTitle(nextDoc), "next");
            });
        },
        infiniteScroll: true,
        css: "@media (max-width:559px){.main{padding:20px 0px 0!important;}}",
        category: "comic"
    }, {
        name: "漫画网 自動翻頁",
        url: {
            e: ["div.logo>a[title=漫画网]>img[alt=漫画网]", "#pics"],
            p: /^\/[\d-]+\.html$/,
            i: 1
        },
        getSrcs: () => frameWindow.params.images,
        getImgs: () => fn.createImgArray(_this.getSrcs()),
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.createImgBox("#pics", 1);
            fragment.append(...imgs);
            tE.append(fragment);
            fn.remove("#pics");
            await fn.lazyload();
        },
        autoPager: {
            mode: 1,
            waitEle: "#pics img",
            ele: () => _this.getImgs(),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: "//a[text()='下一章'][starts-with(@href,'/')]",
            re: ".btn.paediy",
            title: (dom) => {
                let text = fn.dt({
                    t: dom.title,
                    d: "在线阅读-漫画网"
                });
                if (hasTouchEvent) {
                    return text.split("_")[1];
                } else {
                    return text.replace("_", " - ");
                }
            },
            preloadNextPage: 1
        },
        css: "@media (max-width:559px){.main{padding:20px 0px 0!important;}}",
        category: "comic autoPager"
    }, {
        name: "36漫画",
        url: {
            h: "www.36mh.org",
            p: /^\/manhua\/[\d-]+\.html$/,
            d: "pc"
        },
        init: () => fn.createImgBox("#images", 1),
        imgs: (frame = _unsafeWindow) => frame.params.images,
        button: [4, "24%", 3],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#images"], 2
        ],
        autoDownload: [0],
        next: "a[href$=html]:has(>img[alt=下一章])",
        prev: "a[href$=html]:has(>img[alt=上一章])",
        customTitle: (dom = document) => {
            let text = fn.dt({
                t: dom.title,
                d: "漫画-36漫画"
            });
            let textArr = text.split("_");
            return textArr[1] + " - " + textArr[0];
        },
        preloadNext: (nextDoc, obj) => {
            fn.iframeVar(nextLink, "params").then(w => {
                let srcs = obj.imgs(w);
                fn.picPreload(srcs, obj.customTitle(nextDoc), "next");
            });
        },
        category: "comic"
    }, {
        name: "36漫画M",
        url: {
            h: "m.36mh.org",
            p: /^\/manhua\/[\d-]+\.html$/,
            d: "m"
        },
        init: () => fn.createImgBox("#cp_img", 1),
        imgs: (frame = _unsafeWindow) => frame.params.images,
        button: [4, "24%", 3],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, "#cp_img"], 2
        ],
        autoDownload: [0],
        next: "//li[p[text()='下一章']]/a",
        prev: "//li[p[text()='上一章']]/a",
        customTitle: (dom = document) => {
            let text = fn.dt({
                t: dom.title,
                d: "漫画-36漫画"
            });
            let textArr = text.split("_");
            return textArr[1] + " - " + textArr[0];
        },
        preloadNext: (nextDoc, obj) => {
            fn.iframeVar(nextLink, "params").then(w => {
                let srcs = obj.imgs(w);
                fn.picPreload(srcs, obj.customTitle(nextDoc), "next");
            });
        },
        category: "comic"
    }, {
        name: "漫画屋",
        host: ["www.manhua55.com"],
        reg: /^https?:\/\/www\.manhua55\.com\/chapter\/[\d-]+\.html$/,
        init: () => fn.createImgBox(".chapter-main", 1),
        imgs: (frame = _unsafeWindow) => frame.params.images.map(src => {
            src = "https://img1.baipiaoguai.org" + src;
            if (frame.params.source_id == 12) {
                let domains = ["img1-2.baipiaoguai.org", "img1-3.baipiaoguai.org", "img1-4.baipiaoguai.org"];
                let domain = domains[Math.floor(Math.random() * domains.length)];
                let newUrl = new URL(src);
                src = src.replace(newUrl.hostname, domain);
            }
            return src;
        }),
        button: [4, "24%", 3],
        insertImg: [
            ["#FullPictureLoadMainImgBox", 0, ".chapter-main"], 2
        ],
        autoDownload: [0],
        next: "#next-chapter",
        prev: "#prev-chapter",
        customTitle: (dom = document) => fn.dt({
            t: dom.title,
            d: [",_在线漫画阅读_漫画屋", "漫画"]
        }).replace("_", " - "),
        category: "comic"
    }, {
        name: "漫画160/非常爱漫新站",
        host: ["www.mh160.cc", "m.mh160.cc", "www.veryim.com"],
        enable: 1,
        url: {
            h: [/^(www|m)\.mh160/, "www.veryim.com"],
            p: ["/kanmanhua/", /^\/manhua\/\d+\/\d+\.html$/],
            i: 0
        },
        init: "document.onkeydown=null",
        imgs: () => {
            const {
                base64_decode,
                qTcms_S_m_murl_e,
                f_qTcms_Pic_curUrl_realpic
            } = _unsafeWindow;
            return base64_decode(qTcms_S_m_murl_e).split("$qingtiandy$").map(e => f_qTcms_Pic_curUrl_realpic(e));
        },
        button: [4],
        insertImg: ["//td[//img[@onclick]] | //div[@class='UnderPage']", 2],
        autoDownload: [0],
        next: "#k_Pic_nextArr",
        prev: "#k_Pic_backArr",
        customTitle: () => {
            const {
                qTcms_S_m_name,
                qTcms_S_m_playm
            } = _unsafeWindow;
            return qTcms_S_m_name + " - " + qTcms_S_m_playm;
        },
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("qTcms_S_m_murl_e", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(), "next");
        },
        infiniteScroll: true,
        css: ".action-list li{width:50% !important}@media only screen and (max-width:480px){.container,.content-body{padding:0px !important}}",
        hide: "body>a[target],#action>ul>li:nth-child(n+2):nth-child(-n+3)",
        category: "comic"
    }, {
        name: "漫画160/非常爱漫新站 自動翻頁",
        enable: 1,
        url: {
            h: [/^(www|m)\.mh160/, "www.veryim.com"],
            p: ["/kanmanhua/", /^\/manhua\/\d+\/\d+\.html$/],
            i: 1
        },
        getImgs: () => {
            const {
                base64_decode,
                qTcms_S_m_murl_e,
                f_qTcms_Pic_curUrl_realpic
            } = _unsafeWindow;
            let srcs = base64_decode(qTcms_S_m_murl_e).split("$qingtiandy$").map(e => f_qTcms_Pic_curUrl_realpic(e));
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.createImgBox("//td[//img[@onclick]] | //div[@class='UnderPage']", 2);
            fn.remove("//td[//img[@onclick]] | //div[@class='UnderPage']");
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            script: "//script[contains(text(),'qTcms_S_m_murl_e')]",
            ele: () => _this.getImgs(),
            pos: ["#FullPictureLoadMainImgBox", 0],
            observer: "#FullPictureLoadMainImgBox>img",
            next: (dom, r = 1) => {
                let n = fn.ge("#k_Pic_nextArr[href$='html']", dom);
                if (n) {
                    return n.href;
                } else {
                    if (r === 1) {
                        let n = fn.ge("#k_Pic_nextArr");
                        n.href = fn.lp.replace(/\d+\.html$/, "");
                        let text;
                        if (fn.lh.includes("mh160")) {
                            text = "返回目录";
                        } else {
                            text = "目录";
                        }
                        n.innerText = text;
                        if (fn.lh === "www.mh160.cc") {
                            n.remove();
                        }
                    }
                    return null;
                }
            },
            re: ".title,.main-btn,.breadcrumb,.BarTit,#action,.pager:not([id])",
            title: (dom, frame = _unsafeWindow) => {
                const {
                    qTcms_S_m_name,
                    qTcms_S_m_playm
                } = frame;
                if (hasTouchEvent) {
                    return qTcms_S_m_playm;
                } else {
                    return qTcms_S_m_name + " - " + qTcms_S_m_playm;
                }
            },
            hide: "#m_r_bottom~.imgBox,.globalPadding",
            lazyload: 0,
            preloadNextPage: (dom) => {
                let next = _this.autoPager.next(dom);
                if (!!next) {
                    fn.iframe(next, {
                        waitVar: "qTcms_S_m_murl_e",
                        cb: async (nextDom, frame) => {
                            let srcs = frame.base64_decode(frame.qTcms_S_m_murl_e).split("$qingtiandy$").map(e => frame.f_qTcms_Pic_curUrl_realpic(e));
                            let text = _this.autoPager.title(nextDom, frame);
                            fn.picPreload(srcs, text, "next");
                        }
                    });
                }
            }
        },
        css: ".action-list li{width:50% !important}@media only screen and (max-width:480px){.container,.content-body{padding:0px !important}}",
        hide: "body>a[target],#action>ul>li:nth-child(n+2):nth-child(-n+3),li:has(>#prev),li:has(>.curPage),li:has(>#k_next)",
        category: "comic autoPager"
    }, {
        name: "非常爱漫新站 AD",
        url: {
            h: "www.veryim.com",
            p: "/manhua/"
        },
        hide: "body>a[target]",
        category: "ad"
    }, {
        name: "笨狗漫画",
        enable: 0,
        url: {
            h: ["www.bengou.co", "m.bengou.co"],
            p: /^\/\w+\/\w+\/\d+\.html$/
        },
        init: "document.onkeydown=null;",
        imgs: () => {
            const {
                base64_decode,
                qTcms_S_m_murl_e,
                f_qTcms_Pic_curUrl_realpic
            } = _unsafeWindow;
            return base64_decode(qTcms_S_m_murl_e).split("$qingtiandy$").map(e => f_qTcms_Pic_curUrl_realpic(e));
        },
        insertImg: ["//td[img[@id='qTcms_pic']]", 2],
        autoDownload: [0],
        next: () => {
            const {
                qTcms_Pic_nextArr
            } = _unsafeWindow;
            return (!/^java/.test(qTcms_Pic_nextArr) && qTcms_Pic_nextArr !== "") ? location.origin + qTcms_Pic_nextArr : null;
        },
        prev: 1,
        customTitle: () => {
            const {
                qTcms_S_m_name,
                qTcms_S_m_playm
            } = _unsafeWindow;
            return qTcms_S_m_name + " - " + qTcms_S_m_playm;
        },
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("qTcms_S_m_murl_e", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(), "next");
        },
        css: ".action-list li{width:50% !important}",
        hide: "#mypic_k0,.action-list>ul>li:nth-child(n+2):nth-child(-n+3)",
        category: "comic"
    }, {
        name: "星辰漫画网",
        enable: 1,
        url: {
            h: ["www.xcmh.com", "m.xcmh.com"],
            p: /^\/\w+\/\w+\/\d+\.html$/
        },
        init: "document.onkeydown=null;",
        imgs: () => {
            const {
                base64_decode,
                qTcms_S_m_murl_e,
                f_qTcms_Pic_curUrl_realpic
            } = _unsafeWindow;
            return base64_decode(qTcms_S_m_murl_e).split("$qingtiandy$").map(e => location.origin + f_qTcms_Pic_curUrl_realpic(e));
        },
        button: [4],
        insertImg: ["//td[img[@id='qTcms_pic']]", 2],
        autoDownload: [0],
        next: () => {
            const {
                qTcms_Pic_nextArr
            } = _unsafeWindow;
            return (!/^java/.test(qTcms_Pic_nextArr) && qTcms_Pic_nextArr !== "") ? location.origin + qTcms_Pic_nextArr : null;
        },
        prev: 1,
        customTitle: () => {
            const {
                qTcms_S_m_name,
                qTcms_S_m_playm
            } = _unsafeWindow;
            return qTcms_S_m_name + " - " + qTcms_S_m_playm;
        },
        preloadNext: (nextDoc, obj) => {
            let code = fn.gst("qTcms_S_m_murl_e", nextDoc);
            fn.script(code, 0, 1);
            fn.picPreload(obj.imgs(), obj.customTitle(), "next");
        },
        hide: "#mypic_k0",
        category: "comic"
    }, {
        name: "哔咔漫画",
        enable: 0,
        url: {
            h: ["www.bikamanhua.com", "m.bikamanhua.com"],
            p: /^\/[\d-]+\.html$/
        },
        imgs: "img.lazy-read",
        button: [4],
        insertImg: ["div:has(>div>img.lazy-read),.episode-detail", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'] | //a[text()='下一话']",
        prev: "//a[text()='上一章'] | //a[text()='上一话']",
        customTitle: (dom = document) => fn.title(" - ", 3, dom),
        preloadNext: true,
        category: "comic"
    }, {
        name: "聚合漫画屋/酷看漫画/去去漫画/皮皮漫画/六漫画/有品漫画",
        url: {
            h: ["www.52hah.com", /^www.kukanmanhua./, "www.ququmh.com", "www.mh369.com", "www.pipiman.com", "www.cicoo.cc", "www.ypdsm.com"],
            p: ["/chapter/", "/book/"],
            d: "pc"
        },
        imgs: ".comiclist img",
        button: [4],
        insertImg: [".comicpage", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: (dom = document) => fn.gt("h1.title", 1, dom),
        preloadNext: (nextDoc, obj) => fn.iframeDoc(nextLink, ".comiclist img:not([src*=loading])", 30000).then(nextIframeDoc => fn.picPreload(fn.getImgSrcArr(obj.imgs, nextIframeDoc), obj.customTitle(nextIframeDoc), "next")),
        category: "comic"
    }, {
        name: "聚合漫画屋M/酷看漫画M/去去漫画M/皮皮漫画M/六漫画M/有品漫画M",
        url: {
            h: ["www.52hah.com", /^www.kukanmanhua./, "www.ququmh.com", "www.mh369.com", "www.pipiman.com", "www.cicoo.cc", "www.ypdsm.com"],
            p: ["/chapter/", "/book/"],
            d: "m"
        },
        imgs: "#cp_img img",
        button: [4],
        insertImg: ["#cp_img", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => {
            let [, text] = fn.gst("bookInfo").match(/bookInfo[\s=]+([^;]+)/);
            let bookInfo = fn.run(text);
            return bookInfo.book_name.replace(/_\d+$/, "") + " - " + bookInfo.chapter_name;
        },
        preloadNext: (nextDoc, obj) => fn.iframeDoc(nextLink, "#cp_img img[data-original]:not([src*=loading])", 30000).then(nextIframeDoc => fn.picPreload(fn.getImgSrcArr(obj.imgs, nextIframeDoc), nextIframeDoc.title, "next")),
        category: "comic"
    }, {
        name: "云端漫画",
        enable: 0,
        url: {
            h: "www.bcloudmerge.com",
            p: "/bmergechapter/"
        },
        init: () => fn.remove("//div[p[@class='open']] | //div[p[contains(text(),'小贴士')]] | //div[div[button[text()='无删韩漫']]]"),
        imgs: ".mh_list img,#content img",
        button: [4],
        insertImg: [".mh_list,#content", 2],
        autoDownload: [0],
        next: "//a[text()='下一章']",
        prev: "//a[text()='上一章']",
        customTitle: () => {
            const {
                read
            } = _unsafeWindow;
            return read.articlename + " - " + read.cname;
        },
        category: "comic"
    }, {
        name: "最次元/野蛮/优乐漫画",
        enable: 0,
        url: {
            h: ["zcymh.com", "yemancomic.com", "www.beston-test.com"],
            p: /^\/\w+\/\d+\/\d+\.html$/
        },
        imgs: "#img-box img,#imgsec img",
        button: [4],
        insertImg: ["#img-box,#imgsec", 2],
        autoDownload: [0],
        next: "#js_pageNextBtn>a,a#next",
        prev: "#js_pagePrevBtn>a,a#prev",
        customTitle: () => {
            let code = fn.gst("read");
            let [, objText] = code.match(/read[\s=]+([^;]+)/);
            let json = fn.run(objText);
            return json.articlename + " - " + json.chaptername;
        },
        category: "comic"
    }, {
        name: "爱看漫",
        url: {
            h: "ikmmh.com",
            p: /^\/\w+\/\d+\/\d+\.html$/,
            d: "pc"
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            return fn.xhrDoc(siteUrl, {
                headers: {
                    "User-Agent": Mobile_UA
                }
            }).then(dom => {
                fn.hideMsg();
                return fn.gae(".episode-detail img", dom);
            });
        },
        button: [4, "24%", 4],
        insertImg: ["#img-box", 2],
        autoDownload: [0],
        next: "#js_pageNextBtn>a",
        prev: "#js_pagePrevBtn>a",
        customTitle: () => {
            let code = fn.gst("read");
            let [, objText] = code.match(/read[\s=]+([^;]+)/);
            let json = fn.run(objText);
            return json.articlename + " - " + json.chaptername;
        },
        css: "#img-box{max-width:800px;margin:0 auto}",
        category: "comic"
    }, {
        name: "爱看漫M/灰狗漫画M/众飞漫画",
        url: {
            h: [/ikmmh\.com$/, "www.greyhoundsoul.com", "www.zonfibra.com"],
            p: [/^\/\w+\/\d+\/\d+\.html$/, "/greychapter/", "/zonfchapter/"],
            d: "m"
        },
        imgs: ".episode-detail img",
        button: [4],
        insertImg: [".episode-detail", 2],
        autoDownload: [0],
        next: "a#next",
        prev: "a#prev",
        customTitle: () => {
            let code = fn.gst("read");
            let [, objText] = code.match(/read[\s=]+([^;]+)/);
            objText = objText.slice(1, -1).replaceAll("'", "");
            let properties = objText.split(",");
            let obj = {};
            properties.forEach(property => {
                let [key, value] = property.split(":");
                obj[key?.trim()] = value?.trim();
            });
            return obj.articlename + " - " + obj.chaptername;
        },
        hide: "body>div[style]:has(>p),.epContent+.z-index-99:has(>.down-app),.down-app,.z-index-99 div:has(p>br),.z-index-99 div[style]:has(>button[style][onclick])",
        fancybox: {
            blacklist: 1
        },
        category: "comic"
    }, {
        name: "灰狗漫画",
        host: ["www.greyhoundsoul.com"],
        enable: 1,
        url: {
            h: "www.greyhoundsoul.com",
            p: "/greychapter/"
        },
        imgs: "#reader-scroll img[width]",
        button: [4, "24%", 4],
        insertImg: ["#reader-scroll", 2],
        endColor: "white",
        autoDownload: [0],
        next: "#js_pageNextBtn>a",
        prev: "#js_pagePrevBtn>a",
        customTitle: () => {
            let code = fn.gst("read");
            let [, objText] = code.match(/read[\s=]+([^;]+)/);
            let json = fn.run(objText);
            return json.articlename + " - " + json.chaptername;
        },
        category: "comic"
    }, {
        name: "拷貝漫畫",
        host: ["www.copymanga.tv", "copymanga.tv", "www.mangacopy.com", "mangacopy.com"],
        enable: 1,
        url: {
            h: /copymanga|mangacopy/,
            p: /^\/comic\/\w+\/chapter\//,
            d: "pc",
            i: 0
        },
        delay: 300,
        fetchJson: (url = siteUrl) => {
            //let host = fn.lh.replace("www.", "");
            //let api = siteUrl.replace(/.*?(?=\/comic\/)/, `https://api.${host}/api/v3`);
            let [, , name, , id] = new URL(url).pathname.split("/");
            let api = `/api/v3/comic/${name}/chapter2/${id}?platform=3`;
            return fetch(api).then(res => res.json());
        },
        init: async () => {
            fn.copymangaUI();
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchJson = await _this.fetchJson();
            siteJson = fetchJson;
            debug("\n此頁JSON資料\n", fetchJson);
            let readHistoryData = localStorage.getItem("copymangaReadHistory");
            let [, , comic, , chapter] = fn.lp.split("/");
            let json;
            readHistoryData ? json = JSON.parse(readHistoryData) : json = {};
            json[comic] = chapter;
            localStorage.setItem("copymangaReadHistory", JSON.stringify(json));
        },
        //imgs: () => siteJson.results.chapter.contents.map(e => e.url.replace("c800x.", "c1500x.")),
        imgs: (json = siteJson) => {
            const srcs = [];
            const {
                words,
                contents
            } = siteJson.results.chapter;
            words.forEach((w, i) => (srcs[w] = contents[i].url.replace("c800x.", "c1500x.")));
            return srcs;
        },
        button: [4],
        insertImg: [".comicContent-list", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='下一話'][starts-with(@href,'/comic/')]",
        prev: "//a[text()='上一話'][starts-with(@href,'/comic/')]",
        customTitle: (json = siteJson) => json.results.comic.name + " - " + json.results.chapter.name,
        preloadNext: (nextDoc, obj) => {
            obj.fetchJson(nextLink).then(json => {
                let srcs = obj.imgs(json);
                let title = obj.customTitle(json);
                fn.picPreload(srcs, title, "next");
            });
        },
        topButton: true,
        hide: ".header+div[style],.comicContainerAds",
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "拷貝漫畫 自動翻頁",
        url: {
            h: /copymanga|mangacopy/,
            p: /^\/comic\/\w+\/chapter\//,
            d: "pc",
            i: 1
        },
        delay: 300,
        getImgs: (url = siteUrl) => {
            let [, , comic, , chapter] = new URL(url).pathname.split("/");
            let api = `/api/v3/comic/${comic}/chapter2/${chapter}?platform=3`;
            return fetch(api).then(res => res.json()).then(json => {
                const srcArr = [];
                const {
                    words,
                    contents
                } = json.results.chapter;
                words.forEach((w, i) => (srcArr[w] = contents[i].url.replace("c800x.", "c1500x.")));
                customTitle = json.results.comic.name + " - " + json.results.chapter.name;
                let readHistoryData = localStorage.getItem("copymangaReadHistory");
                let obj;
                readHistoryData ? obj = JSON.parse(readHistoryData) : obj = {};
                obj[comic] = chapter;
                localStorage.setItem("copymangaReadHistory", JSON.stringify(obj));
                return srcArr;
            }).then(srcs => fn.createImgArray(srcs));
        },
        init: async () => {
            fn.copymangaUI();
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getImgs().then(async imgs => {
                let tE = fn.ge(".comicContent-list");
                tE.innerHTML = "";
                fragment.append(...imgs);
                tE.append(fragment);
                fn.hideMsg();
                await fn.lazyload();
            });
            fn.addMutationObserver(() => {
                if (fn.ge("//li[img[@data-src]]")) {
                    fn.remove("//li[img[@data-src]]");
                }
            });
        },
        autoPager: {
            ele: () => _this.getImgs(nextLink),
            pos: [".comicContent-list", 0],
            observer: ".comicContent-list>img",
            next: "//a[text()='下一話'][starts-with(@href,'/comic/')]",
            re: ".header,.footer",
            title: () => customTitle
        },
        hide: ".header+div[style],.comicContainerAds",
        category: "comic autoPager"
    }, {
        name: "拷貝漫畫 目錄頁",
        reg: /^https?:\/\/(www\.)?(copymanga\.tv|mangacopy\.com)\/comic\/\w+$/,
        delay: 300,
        init: async () => {
            await fn.waitEle(".tab-pane.show.active a");
            const updateLastChapter = () => {
                let [, , comic] = fn.lp.split("/");
                let readHistoryData = localStorage.getItem("copymangaReadHistory");
                if (!!readHistoryData) {
                    let json = JSON.parse(readHistoryData);
                    if (comic in json) {
                        let selector = `.tab-content a[href$="${json[comic]}"]`;
                        fn.gae(".lastchapter").forEach(a => a.classList.remove("lastchapter"));
                        fn.gae(selector).forEach(a => a.classList.add("lastchapter"));
                        setTimeout(() => {
                            let lastReadUrl = fn.lp + "/chapter/" + json[comic];
                            let lastText = fn.ge(".lastchapter").title;
                            let lastE = fn.ge("#lastRead");
                            if (!lastE && !fn.ge("//span[contains(text(),'最後閱讀')]")) {
                                let a = document.createElement("a");
                                a.id = "lastRead";
                                a.target = "_blank";
                                let tableRight = fn.ge(".table-default-right");
                                tableRight.insertAdjacentElement("afterbegin", a);
                                const span = document.createElement("span");
                                span.innerText = "最後閱讀:";
                                tableRight.insertAdjacentElement("afterbegin", span);
                                a.href = lastReadUrl;
                                a.innerText = lastText;
                            } else if (!!lastE) {
                                let a = lastE;
                                a.href = lastReadUrl;
                                a.innerText = lastText;
                            }
                        }, 200);
                    }
                }
            };
            updateLastChapter();
            document.addEventListener("visibilitychange", updateLastChapter);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            setTimeout(() => fn.clearAllTimer(3), 1000);
        },
        css: ".lastchapter{color:#fff !important;background:#1790E6}",
        hide: ".comicDetailAds",
        category: "none"
    }, {
        name: "拷貝漫畫 清除不給開啟開發人員工具",
        reg: () => !hasTouchEvent && /^(www\.)?(copymanga\.tv|mangacopy\.com)$/.test(fn.lh) && !fn.ge("//title[text()='漫畫觀看']"),
        delay: 300,
        init: () => {
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            fn.gae("img[data-src]").forEach(img => (img.src = img.dataset.src));
        },
        category: "none"
    }, {
        name: "拷貝漫畫M",
        host: ["www.copymanga.tv", "copymanga.tv", "www.mangacopy.com", "mangacopy.com"],
        enable: 1,
        url: {
            h: /copymanga|mangacopy/,
            p: /^\/h5\/comicContent\/\w+\//,
            d: "m",
            i: 0
        },
        xhrJson: (url = siteUrl) => {
            //let [name, id] = url.split("/").slice(-2);
            //let host = fn.lh.replace("www.", "");
            //let api = `https://api.${host}/api/v3/comic/${name}/chapter/${id}`;
            let [name, id] = url.split("/").slice(-2);
            let api = `/api/v3/comic/${name}/chapter2/${id}?platform=3`;
            return fn.xhr(api, {
                responseType: "json",
                headers: {
                    "Referer": `https://${fn.lh}/comic/${name}/chapter/${id}`,
                    "User-Agent": PC_UA
                }
            });
        },
        init: async () => {
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            siteJson = await _this.xhrJson();
            debug("\n此頁JSON資料\n", siteJson);
            const addHtml = (url, text) => {
                let str = `<div style="padding: 10px 0; text-align: center;"><a href="${url}"style="width: 100%;font-size: 26px;line-height: 50px;height: 50px;text-align: center;">${text}</a></div>`;
                fn.ge(".comicContentPopupImageList").insertAdjacentHTML("afterend", str);
            };
            let s = siteUrl.split("/").slice(-2);
            let url = `https://${fn.lh}/h5/details/comic/${s[0]}`;
            let hUrl = `https://${fn.lh}/h5/index`;
            addHtml(hUrl, "首頁");
            addHtml(url, "目錄");
            let nUrl = _this.next();
            if (nUrl) addHtml(nUrl, "點選進入下一話");
            fn.copymanga_M_UI(url, hUrl);
        },
        //imgs: () => siteJson.results.chapter.contents.map(e => e.url.replace("c800x.", "c1500x.")),
        imgs: (json = siteJson) => {
            const srcs = [];
            const {
                words,
                contents
            } = json.results.chapter;
            words.forEach((w, i) => (srcs[w] = contents[i].url));
            return srcs;
        },
        button: [4],
        insertImg: [".comicContentPopupImageList", 2],
        next: () => {
            let next = siteJson.results.chapter.next;
            return next ? siteUrl.replace(/[\w-]+$/, "") + next : null;
        },
        customTitle: () => siteJson.results.comic.name + " - " + siteJson.results.chapter.name,
        preloadNext: (nextDoc, obj) => {
            obj.xhrJson(nextLink).then(json => {
                let srcs = obj.imgs(json);
                let title = json.results.comic.name + " - " + json.results.chapter.name;
                fn.picPreload(srcs, title, "next");
            });
        },
        css: ".comicControlBottom a:-webkit-any-link{color:white!important}.comicContentPopup .comicControlBottom .comicControlBottomBottom span{margin:0 1rem!important}",
        hide: ".comicFixed,.comicControlBottom.hide",
        fancybox: {
            blacklist: 1
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "拷貝漫畫M 自動翻頁",
        enable: 1,
        url: {
            h: /copymanga|mangacopy/,
            p: /^\/h5\/comicContent\/\w+\//,
            d: "m",
            i: 1
        },
        getData: () => {
            let [name, id] = new URL(document.URL).pathname.split("/").slice(-2);
            let api = `/api/v3/comic/${name}/chapter2/${id}?platform=3`;
            return fn.xhr(api, {
                responseType: "json",
                headers: {
                    "Referer": `https://${fn.lh}/comic/${name}/chapter/${id}`,
                    "User-Agent": PC_UA
                }
            }).then(json => {
                const srcs = [];
                const {
                    words,
                    contents
                } = json.results.chapter;
                words.forEach((w, i) => (srcs[w] = contents[i].url));
                globalImgArray = srcs;
                customTitle = json.results.chapter.name;
                let next = json.results.chapter?.next;
                console.log("\n拷貝漫畫M_JSON\n", json, globalImgArray, customTitle, next);
                if (!!next) {
                    tempNextLink = document.URL.replace(/[^\/]+$/, "") + next;
                } else {
                    tempNextLink = null;
                }
            });
        },
        init: async () => {
            fn.showMsg(displayLanguage.str_135, 0);
            await _this.getData();
            let imgs = fn.createImgArray(globalImgArray);
            let tE = fn.ge(".comicContentPopupImageList");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
            fn.hideMsg();
            const addHtml = (url, text) => {
                let str = `<div style="padding: 0 0 12px; text-align: center;"><a href="${url}"style="width: 100%;font-size: 26px;line-height: 34px;height: 34px;text-align: center;">${text}</a></div>`;
                fn.ge(".comicContentPopupImageList").insertAdjacentHTML("afterend", str);
            };
            let s = siteUrl.split("/").slice(-2);
            let url = `https://${fn.lh}/h5/details/comic/${s[0]}`;
            let hUrl = `https://${fn.lh}/h5/index`;
            addHtml(hUrl, "首頁");
            addHtml(url, "目錄");
            fn.copymanga_M_UI(url, hUrl);
        },
        autoPager: {
            ele: () => fn.createImgArray(globalImgArray),
            pos: [".comicContentPopupImageList", 0],
            observer: ".comicContentPopupImageList>img",
            next: () => tempNextLink,
            wait: async () => await _this.getData(),
            title: () => customTitle
        },
        css: ".comicControlBottom a:-webkit-any-link{color:white!important}.comicContentPopup .comicControlBottom .comicControlBottomBottom span{margin:0 1rem!important}",
        hide: ".comicFixed,.comicControlBottom.hide",
        category: "comic autoPager"
    }, {
        name: "拷貝漫畫M 清除不給開啟開發人員工具",
        reg: /^https?:\/\/(www\.)?(copymanga\.tv|mangacopy\.com)\/h5/,
        init: async () => {
            fn.clearAllTimer(3);
            if ("aboutBlank" in _unsafeWindow) _unsafeWindow.aboutBlank = null;
        },
        category: "none"
    }, {
        name: "二次元動漫/看漫畫",
        host: ["www.2animx.com", "www.k886.net"],
        enable: 0,
        reg: /^https?:\/\/(www\.2animx\.com|www\.k886\.net)\/index-look-name-.+/,
        init: "$(document).unbind('click');",
        imgs: (url = siteUrl, dom = document, msg = 1, request = 0) => {
            let max = fn.ge("#total", dom).value;
            let links = fn.arr(max, (v, i) => fn.getModeUrl(url, 20, (i + 1)));
            return fn.getImgA("#ComicPic", links, 100, null, msg, request);
        },
        button: [4],
        insertImg: ["//div[img[@id='ComicPic']]", 2],
        autoDownload: [0],
        next: ".n.zhangjie",
        prev: ".p.zhangjie",
        customTitle: dom => {
            let [, , comic_name, comic_chapter] = fn.gt(".b", 1, dom).split(" - ");
            return comic_name + " - " + comic_chapter.replace(/(\d+P)/i, "");
        },
        preloadNext: async (nextDoc, obj) => fn.picPreload(await obj.imgs(nextLink, nextDoc, 0, 1), obj.customTitle(nextDoc), "next"),
        css: "#ComicPic{display:block!important;margin: 0 auto !important;}",
        hide: ".c>*:not(.n.zhangjie):not(.p.zhangjie)",
        category: "comic"
    }, {
        name: "看漫畫M",
        enable: 0,
        url: {
            h: "m.k886.net",
            p: "/cid/"
        },
        imgs: (url = siteUrl, dom = document, msg = 1, request = 0) => {
            let max = fn.gt(".manga-page", 1, dom).match(/\d+/g).at(-1);
            let links = fn.arr(max, (v, i) => i == 0 ? url : url + "/p/" + (i + 1));
            return fn.getImgA("#manga img[alt]", links, 100, null, msg, request);
        },
        button: [4],
        insertImg: ["#manga", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][not(starts-with(@href,'java'))]",
        prev: "//a[text()='下一章'][not(starts-with(@href,'java'))]",
        customTitle: dom => fn.gt("#mangaTitle", 1, dom),
        preloadNext: async (nextDoc, obj) => fn.picPreload(await obj.imgs(nextLink, nextDoc, 0, 1), obj.customTitle(nextDoc), "next"),
        css: ".action-list li{width:50% !important}",
        category: "comic"
    }, {
        name: "漫画DB",
        enable: 1,
        url: {
            h: "www.manhuadb.com",
            p: /^\/manhua\/\d+\/\w+\.html$/,
            i: 0
        },
        imgs: (frame = _unsafeWindow) => {
            const {
                img_data_arr,
                img_host,
                img_pre
            } = frame;
            return img_data_arr.map(e => img_host + img_pre + e.img);
        },
        button: [4],
        insertImg: ["#all", 2],
        autoDownload: [0],
        next: () => {
            const {
                p_ccid,
                p_id,
                vg_r_data,
                p_d
            } = _unsafeWindow;
            return fetch("/book/goNumPage", {
                "headers": {
                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
                },
                "body": `ccid=${p_ccid}&id=${p_id}&num=${Number(vg_r_data.data("num")) + 1}&d=${p_d}&type=next`,
                "method": "POST"
            }).then(res => res.json()).then(json => json.state == 0 ? null : location.origin + json.url);
        },
        prev: "//a[text()='上集']",
        customTitle: (dom) => fn.title("-漫画DB", 0, dom),
        preloadNext: () => {
            fn.iframe(nextLink, {
                waitVar: "img_data_arr",
                cb: async (dom, frame) => {
                    let srcs = _this.imgs(frame);
                    let text = _this.customTitle(dom);
                    fn.picPreload(srcs, text, "next");
                }
            });
        },
        infiniteScroll: true,
        category: "comic"
    }, {
        name: "漫画DB 自動翻頁",
        url: {
            h: "www.manhuadb.com",
            p: /^\/manhua\/\d+\/\w+\.html$/,
            i: 1
        },
        getSrcs: (dom) => {
            let code = fn.gst("img_data", dom);
            let base64Text = code.slice(16, -2);
            //let decodeBase64 = atob(base64Text);
            let decodeBase64 = _unsafeWindow.jQuery.base64.decode(base64Text);
            let imgDataArr = JSON.parse(decodeBase64);
            let vgData = fn.ge(".vg-r-data", dom);
            let imgHost = vgData.dataset.host;
            let imgPre = vgData.dataset.img_pre;
            let srcs = imgDataArr.map(e => imgHost + imgPre + e.img);
            return srcs;
        },
        getImgs: (dom = document) => {
            let srcs = _this.getSrcs(dom);
            return fn.createImgArray(srcs);
        },
        init: async () => {
            let imgs = _this.getImgs();
            let tE = fn.ge("#all");
            tE.innerHTML = "";
            fragment.append(...imgs);
            tE.append(fragment);
            await fn.lazyload();
        },
        autoPager: {
            ele: (dom) => _this.getImgs(dom),
            pos: ["#all", 0],
            observer: "#all>img",
            next: (dom) => {
                let vgData = fn.ge(".vg-r-data", dom);
                let ccid = vgData.dataset.ccid;
                let id = vgData.dataset.id;
                let num = vgData.dataset.num;
                let d = vgData.dataset.d;
                return fetch("/book/goNumPage", {
                    "headers": {
                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
                    },
                    "body": `ccid=${ccid}&id=${id}&num=${Number(num) + 1}&d=${d}&type=next`,
                    "method": "POST"
                }).then(res => res.json()).then(json => json.state == 0 ? null : json.url);
            },
            title: (dom) => {
                let m = fn.gt("h1.h2>a", 1, dom);
                let c = fn.gt("h2.h4", 1, dom).replace(/\[|\]/g, "");
                return hasTouchEvent ? c : m + " - " + c;
            },
            hide: ".comic-viewer-toc",
            preloadNextPage: 1
        },
        hide: ".form-inline>.pre,.form-inline>.next,div:has(>#page-selector)",
        category: "comic autoPager"
    }, {
        name: "快岸漫画",
        enable: 0,
        url: {
            h: "ikanbook.net",
            p: /^\/comic\/\d+\/\d+/
        },
        init: async () => {
            await fn.waitVar("x_tokens");
            fn.run("$(document).unbind('keydown');$(document).unbind('keyup');");
        },
        imgs: () => {
            const {
                is_refresh,
                x_tokens,
                Gm,
                comic_id,
                version_id,
                part_id,
                my_sha2,
                data
            } = _unsafeWindow;
            return is_refresh == 0 ? x_tokens.map(e => Gm.getImgUrl(comic_id + "/" + version_id + "/" + part_id + "/" + my_sha2(e))) : data.url.map(e => Gm.getImgUrl(e));
        },
        button: [4],
        insertImg: ["#all", 2],
        endColor: "white",
        autoDownload: [0],
        next: "//a[text()='下一章' and not(starts-with(@href,'javascript'))]",
        prev: "//a[text()='上一章' and not(starts-with(@href,'javascript'))]",
        customTitle: () => fn.gt("h2.h2>a") + " - " + fn.gt("span.h4:nth-child(5)"),
        category: "comic"
    }, {
        name: "樱花漫画",
        enable: 1,
        url: {
            h: "yinghuamh.net",
            p: /^\/comic\/\w+\/\d+\/\d+/
        },
        init: async () => {
            await fn.waitVar("x_tokens");
            fn.run("$(document).off();");
            let lastScrollTop = 0;
            document.addEventListener("scroll", event => {
                let st = event.srcElement.scrollingElement.scrollTop;
                if (st > lastScrollTop) {
                    fn.ge(".view-title").style.top = "-60px";
                    lastScrollTop = st;
                } else if (st < lastScrollTop - 20) {
                    fn.ge(".view-title").style.top = "0px";
                    lastScrollTop = st;
                }
            });
        },
        imgs: () => {
            const {
                x_tokens,
                Gm
            } = _unsafeWindow;
            return x_tokens.map(e => Gm.getImgUrl(Gm.fitImgUrl(e)));
        },
        button: [4],
        insertImg: ["#all", 2],
        endColor: "white",
        autoDownload: [0],
        next: "a.next_part:not([href^=java])",
        prev: ".paginationContent>a:first-child:not([href^=java])",
        customTitle: () => {
            const {
                comic_name,
                part_name
            } = _unsafeWindow;
            return comic_name + " - " + part_name;
        },
        preloadNext: () => {
            fn.iframeVar(nextLink, "x_tokens").then(frame => {
                const {
                    x_tokens,
                    Gm,
                    comic_name,
                    part_name
                } = frame;
                let srcs = x_tokens.map(e => Gm.getImgUrl(Gm.fitImgUrl(e)));
                let text = comic_name + part_name;
                fn.picPreload(srcs, text, "next");
            });
        },
        category: "comic"
    }, {
        name: "哔哩哔哩漫画",
        host: ["manga.bilibili.com"],
        enable: 0,
        url: {
            h: "manga.bilibili.com",
            p: "/mc",
            s: "manga_detail",
            d: "pc"
        },
        getHeaders: () => {
            return {
                "accept": "application/json, text/plain, */*",
                "content-type": "application/json;charset=UTF-8"
            }
        },
        init: () => {
            let [, comic_id, ep_id] = location.pathname.match(/\/mc(\d+)\/(\d+)/);
            siteJson = {
                comic_id,
                ep_id
            };
        },
        imgs: () => fetch("/twirp/comic.v1.Comic/GetImageIndex?device=pc&platform=web", {
            "headers": _this.getHeaders(),
            "body": JSON.stringify({
                ep_id: siteJson.ep_id
            }),
            "method": "POST"
        }).then(res => res.json()).then(json => json.data.images.map(e => e.path)).then(imgsRes => fetch("/twirp/comic.v1.Comic/ImageToken?device=pc&platform=web", {
            "headers": _this.getHeaders(),
            "body": JSON.stringify({
                urls: JSON.stringify(imgsRes)
            }),
            "method": "POST"
        }).then(res => res.json()).then(json => json.data.map(e => `${e.url}?token=${e.token}`))),
        insertImg: [".image-list", 3],
        endColor: "white",
        next: () => fetch("/twirp/comic.v1.Comic/ComicDetail?device=pc&platform=web", {
            "headers": _this.getHeaders(),
            "body": JSON.stringify({
                comic_id: siteJson.comic_id
            }),
            "method": "POST"
        }).then(res => res.json()).then(json => json.data.ep_list.sort((a, b) => a.ord - b.ord)).then(ep_list => {
            let next = null;
            ep_list.some((e, i, a) => {
                if (siteJson.ep_id == e.id) {
                    if (a[i + 1] !== undefined) {
                        //next = a[i + 1];
                        next = location.href.replace(siteJson.ep_id, a[i + 1].id);
                    }
                    return true;
                }
            });
            return next;
        }),
        prev: 1,
        customTitle: () => fetch("/twirp/comic.v1.Comic/GetEpisode?device=pc&platform=web", {
            "headers": _this.getHeaders(),
            "body": JSON.stringify({
                id: siteJson.ep_id
            }),
            "method": "POST"
        }).then(res => res.json()).then(json => {
            let {
                comic_title,
                short_title,
                title
            } = json.data;
            return comic_title + ` - 第 ${short_title} 话 ` + title;
        }),
        category: "comic"
    }, {
        name: "看漫画",
        host: ["www.kanman.com"],
        enable: 0,
        url: {
            h: "www.kanman.com",
            p: /^\/\d+\/[\w-]+\.html$/,
            d: "pc"
        },
        init: async () => {
            let [, comic_id, id] = fn.lp.split("/");
            id = id.replace(".html", "");
            let api = `/api/getchapterinfov2?product_id=1&productname=kmh&platformname=pc&comic_id=${comic_id}&chapter_newid=${id}&isWebp=1&quality=middle`;
            await fetch(api).then(res => res.json()).then(json => (siteJson = json));
            debug("\n此頁JSON資料\n", siteJson);
        },
        imgs: () => siteJson.data.current_chapter.chapter_img_list,
        next: () => {
            let {
                comic_id,
                next_chapter
            } = siteJson.data;
            if (next_chapter) {
                return "/" + comic_id + "/" + next_chapter.chapter_newid + ".html";
            } else {
                return null;
            }
        },
        prev: 1,
        customTitle: () => siteJson.data.comic_name + " - " + siteJson.data.current_chapter.chapter_name,
        category: "comic"
    }, {
        name: "zero搬运网",
        host: ["www.zerobywz.com"],
        enable: 1,
        url: {
            h: "www.zero",
            p: "/plugin",
            s: "a=read",
            e: "//script[contains(text(),'listimg')]"
        },
        imgs: () => {
            let code = fn.gst("listimg");
            let [arrText] = code.match(/listimg[\s=]+([^;]+)/);
            let dataArr = fn.run(arrText);
            return dataArr.map(e => e.file);
        },
        button: [4],
        insertImg: [".uk-alert.uk-alert-danger.uk-text-center,.uk-zjimg", 3],
        autoDownload: [0],
        next: "//a[contains(text(),'下一章')]",
        prev: "//a[contains(text(),'上一章')]",
        customTitle: () => fn.title(" - zero搬运网"),
        category: "comic"
    }, {
        name: "zero搬运网M",
        enable: 1,
        url: {
            h: "www.zero",
            p: "/plugin",
            s: "a=read",
            e: ".areadiv"
        },
        imgs: ".zjimg>img",
        button: [4],
        insertImg: [".areadiv", 3],
        autoDownload: [0],
        next: "//a[contains(text(),'下一章')]",
        prev: "//a[contains(text(),'上一章')]",
        customTitle: () => fn.title(/_ zero搬运网.+/),
        category: "comic"
    }, {
        name: "漫蛙", //方向鍵上一章下一章、清除擋廣告警告、向下滾動隱藏工具列、反反偵錯,,下載需先手動觸發全部載入圖片,函式使用到canvas需要繪製過程會有點卡。
        host: ["manwa.fun"],
        link: "https://fuw11.cc/maKapG",
        enable: 1,
        url: {
            h: "manwa",
            p: /^\/chapter\/\d+(\?img_host=\d)?$/
        },
        //delay: 1000,
        init: async () => {
            _unsafeWindow.Function.prototype.constructor = () => {};
            //await fn.scrollEles(".img-content img", 200);
            fn.css(".ad-area{opacity:0!important;}#cp_img>.two-ad-area:nth-child(1)>.ad-area,#cp_img>.two-ad-area:nth-child(2){display:none!important}");
            fn.remove(".ad-area,body>div[id]:not([id^='pv-'],[class^='pv-'],[id^='pagetual'],[class^='pagetual'],#comicRead,#fab,[id^='FullPictureLoad'],[class^='FullPictureLoad'],[class^=fancybox])", 5000);
            let lastScrollTop = 0;
            document.addEventListener("scroll", event => {
                const $ = _unsafeWindow.jQuery;
                let st = event.srcElement.scrollingElement.scrollTop;
                if (st > lastScrollTop) {
                    $(".view-fix-top-bar").attr("style", "top: -60px;");
                    $(".view-fix-bottom-bar").attr("style", "bottom: -60px;");
                    $(".detail-comment-fix-bottom").hide("fast");
                    lastScrollTop = st;
                } else if (st < lastScrollTop - 20) {
                    $(".view-fix-top-bar").attr("style", "top: 0px;");
                    $(".view-fix-bottom-bar").attr("style", "bottom: 0px;");
                    $(".detail-comment-fix-bottom").show("fast");
                    lastScrollTop = st;
                }
            });
            await fn.waitEle(".content-img.lazy_img[src^=blob]");
            if (autoScrollAllElement === 1) _this.scrollEle();
        },
        imgs: () => fn.imgBlobUrlArr(".content-img[src^=blob]"),
        scrollEle: () => fn.aotoScrollEles(".img-content .content-img", (img) => /^blob/.test(img.src)),
        next: ".view-fix-bottom-bar-item-menu-next",
        prev: ".view-fix-bottom-bar-item-menu-prev",
        customTitle: () => fn.title("在线阅读", 1),
        css: "body{padding-bottom:0px!important}",
        category: "comic"
    }, {
        name: "漫蛙選目錄展開全部章節",
        url: {
            h: "manwa",
            p: /^\/book\/\d+$/
        },
        init: async () => {
            _unsafeWindow.Function.prototype.constructor = () => {};
            await fn.waitEle("#detail-list-select li");
            await fn.waitVar(["titleSelect", "charpterMore"]);
            EClick("//a[text()='目录']");
            EClick("a.detail-list-more");
        },
        category: "none"
    }, {
        name: "漫蛙自動載入更多",
        url: {
            h: "manwa",
            p: /^\/update$/
        },
        init: "Function.prototype.constructor=()=>{};",
        observerClick: "#loadMore",
        category: "autoPager"
    }, {
        name: "開車漫画",
        host: ["18p.fun"],
        enable: 1,
        reg: /^https?:\/\/(www\.)?(18p|gohaveababy|imynest|healthway|beforeout)\.[a-z]{2,5}\/(ForInject\/|Article\/|content\/)/,
        imgs: async () => {
            await fn.waitEle("//script[contains(text(),'_curChap')]");
            if (fn.lh != "18p.fun") {

                location.replace("https://18p.fun/ForInject/Chapter/?id=" + _unsafeWindow.$_curChap.id);
                await delay(3000);
            }
            await fn.getNP("img[data-src].lazy:not(.demo-lazy)", "//a[@data-url and contains(text(),'下一頁')] | //a[@data-url and contains(text(),'下一章')]", null, "div[class^=picnext]");
            return fn.gae("img[data-src].lazy:not(.demo-lazy)");
        },
        insertImg: ["div[class^=pictures]", 3],
        endColor: "white",
        fetch: 1,
        category: "comic"
    }, {
        name: "開車漫画",
        host: ["18p.fun"],
        enable: 0,
        icon: 0,
        key: 0,
        reg: /^https?:\/\/18p\.fun\//,
        include: ".loadmore>button",
        init: () => fn.addMutationObserver(() => fn.gae("img.lazy[src$=svg]").forEach(img => (img.src = img.dataset.src))),
        observerClick: ".loadmore>button",
        openInNewTab: "#itemlist li>a:not([target=_blank])",
        css: ".loadmore{display:block!important}",
        hide: ".page",
        category: "comic"
    }, {
        name: "风之动漫",
        host: ["www.fffdm.com"],
        enable: 1,
        reg: /^https?:\/\/(www\.fffdm\.com|manhua\.fffdm\.com)\/(manhua\/)?\d+\/[^/]+\/$/i,
        fetchJson: (url = siteUrl) => {
            let [mhId, mhcId] = new URL(url).pathname.split("/").slice(-3);
            let api = `/api/manhua/${mhId}/${mhcId}`;
            return fetch(api).then(res => res.json());
        },
        init: async () => {
            let json = await _this.fetchJson();
            debug("\n此頁JSON資料\n", json);
            siteJson = json;
        },
        imgs: async (json = siteJson, msg = 1) => {
            let hostArr = fn.gau("link[rel='dns-prefetch']");
            let [firstPic] = json.cont;
            let testArr = hostArr.map(e => e + firstPic);
            let ok = false;
            let host;
            for (let [i, test] of testArr.entries()) {
                let obj = await fn.checkImgStatus(test, msg);
                console.log(`確認圖片[${i}]`, obj);
                if (obj.ok) {
                    ok = true;
                    host = hostArr[i];
                    break;
                }
            }
            return ok ? siteJson.cont.map(e => host + e) : [];
        },
        button: [4],
        insertImg: ["#mh", 2],
        insertImgAF: async () => {
            let url = await _this.next();
            if (!!url) {
                let text = `<div style="padding: 36px 0; text-align: center;"><a href="${url}"style="font-size: 26px;line-height: 50px;height: 50px;text-align: center;">點選進入下一話</a></div>`;
                fn.ge("#mh").insertAdjacentHTML("afterend", text);
                fn.ge("#mh+div").addEventListener("click", () => setTimeout(() => location.reload(), 200));
            }
        },
        next: () => {
            let comicListUrl = decodeURIComponent(siteUrl.replace(/[^\/]+\/$/i, ""));
            let chapter = decodeURIComponent(siteUrl.match(/[^\/]+\/$/)[0]);
            let nextXPath = `//div[@id='content']/li[a[@href='${chapter}']]/preceding-sibling::li[1]/a`;
            return fn.fetchDoc(comicListUrl).then(dom => {
                let next = fn.ge(nextXPath, dom, dom);
                return next ? comicListUrl + next.getAttribute("href") : null;
            });
        },
        prev: 1,
        customTitle: (dom = document) => fn.title("第1页", 1, dom),
        preloadNext: async (nextDoc, obj) => {
            let json = await obj.fetchJson(nextLink);
            fn.picPreload(await obj.imgs(json, 0), obj.customTitle(nextDoc), "next");
        },
        fancybox: {
            v: 3,
            insertLibrarys: 1
        },
        category: "comic"
    }, {
        name: "漫画皮",
        host: ["www.manhuapi.cc", "m.manhuapi.cc"],
        enable: 1,
        url: {
            h: "manhuapi",
            p: "/chapter/"
        },
        init: "document.onkeydown=null;$('body').unbind();",
        imgs: (dom = document) => fn.gae("option[jhc-data]", dom).map(e => e.getAttribute("jhc-data").replace("-mht.middle.webp", "")).map(e => e.replace(new URL(e).protocol, location.protocol)),
        button: [4],
        insertImg: [".mh_list,#content", 2],
        autoDownload: [0],
        next: "//a[text()='下一章'][contains(@href,'chapter')]",
        prev: "//a[text()='上一章'][contains(@href,'chapter')]",
        customTitle: (dom = document) => fn.attr("meta[name='keywords']", "content", dom).replace(",", " - "),
        preloadNext: true,
        hide: "#prePage,#nextPage,select[onchange],.jump-list,.apjg,a[href*=taobao]",
        category: "comic"
    }, {
        name: "哈哈漫画",
        enable: 1,
        url: {
            h: "www.hahacomic.com",
            p: /^\/manhua\/\d+\/\d+\.html/
        },
        imgs: "img[data-original]",
        button: [4],
        insertImg: [".chapter-images", 2],
        autoDownload: [0],
        next: "//a[label[text()='下一章'] and not(starts-with(@href,'java'))]",
        prev: "//a[label[text()='上一章'] and not(starts-with(@href,'java'))]",
        preloadNext: async (nextDoc, obj) => fn.picPreload(fn.getImgSrcArr(obj.imgs, nextDoc), nextDoc.title, "next"),
        category: "comic"
    }, {
        name: "哈哈漫画 - 分類自動翻頁",
        enable: 1,
        url: {
            h: "www.hahacomic.com",
            p: "/list/"
        },
        autoPager: {
            ele: ".mdui-col-lg-2",
            observer: ".mdui-col-lg-2",
            next: (dom) => fn.ge("span.current+a", dom) ? siteUrl.replace(/\?page=\d+/, "") + "?page=" + fn.ge("span.current+a", dom).getAttribute("href").match(/\d+/)[0] : null,
            re: ".pages",
            pageNum: () => nextLink.match(/\d+$/)[0]
        },
        openInNewTab: ".mdui-col-lg-2>a",
        category: "autoPager"
    }, {
        name: "轻之国度",
        enable: 1,
        url: {
            h: "www.lightnovel.us",
            p: /^\/\w+\/detail\/\d+/
        },
        imgs: ".article-content img",
        button: [4],
        insertImg: [".article-content", 3],
        customTitle: ".article-title",
        category: "comic"
    }, {
        name: "微信公众号",
        enable: 1,
        url: {
            h: "mp.weixin.qq.com",
            p: /^\/[^&]+&mid=\d+/
        },
        imgs: "img.js_insertlocalimg",
        category: "comic"
    }, {
        name: "虎扑社区",
        enable: 1,
        url: {
            h: "bbs.hupu.com",
            p: /^\/\d+\.html/
        },
        init: () => (siteJson = JSON.parse(fn.attr("#bbs-admin-main-post-container", "data-admininfo"))),
        imgs: () => {
            let data = JSON.parse(siteJson.format);
            if (data.imgList) {
                return data.imgList.map(e => e.remoteUrl);
            } else if (data.jsonV3) {
                return data.jsonV3.content.filter(item => item.type == "image").map(e => e.attrs.src);
            } else {
                return [];
            }
        },
        customTitle: () => siteJson.postTitle,
        category: "comic"
    }, {
        name: "微漫画 目錄頁",
        host: ["medibang.com"],
        enable: 1,
        url: {
            h: "medibang.com",
            p: "/book/",
            d: "pc"
        },
        init: () => fn.createImgBox("#contentsDetailShow"),
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let links;
            let chapterIds;
            if (fn.ge("a.btn_more")) {
                links = fn.gau("a.btn_more").reverse();
                chapterIds = links.map(url => url.split("/").at(-1));
            } else {
                links = fn.gau(".btn_book_read>a");
                chapterIds = links.map(url => url.split("/").at(-2));
            }
            let resArr = [];
            let fetchNum = 0;
            for (let id of chapterIds) {
                let res = fetch(`/api/book/fixedList2/${id}/?quality=pc`).then(res => res.json()).then(json => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${links.length}`, 0);
                    try {
                        let arr = [json.coverUrl];
                        json.chapterList[0].pageList.forEach(e => arr.push(e.publicBgImage));
                        return arr;
                    } catch (error) {
                        console.error(error);
                        return [];
                    }
                });
                resArr.push(res);
            }
            return Promise.all(resArr).then(data => data.flat());
        },
        button: [4],
        insertImg: ["#FullPictureLoadMainImgBox", 3],
        go: 1,
        customTitle: ".box_data>h1.tit",
        category: "comic"
    }, {
        name: "微漫画 閱讀頁",
        host: ["medibang.com"],
        enable: 1,
        url: {
            h: "medibang.com",
            p: "/viewer/",
            d: "pc"
        },
        imgs: () => {
            fn.showMsg(displayLanguage.str_05, 0);
            let id = fn.lp.split("/").at(-2);
            return fetch(`/api/book/fixedList2/${id}/?quality=pc`).then(res => res.json()).then(json => {
                try {
                    let arr = [json.coverUrl];
                    json.chapterList[0].pageList.forEach(e => arr.push(e.publicBgImage));
                    return arr;
                } catch (error) {
                    console.error(error);
                    return [];
                }
            });
        },
        capture: () => _this.imgs(),
        hide: ".mdModal.mdWd1",
        category: "comic"
    }, {
        name: "漫畫類 自動展開目錄",
        reg: [
            /(mangabz|xmanhua|yymanhua|dm5|1kkk|manhuaren|manben|mkzhan)\.com\/[\w-]+\//,
            /(m\.dmzj\.com|m\.gmh1234\.com)\/(info|comic)\/\d+\.html$/,
            /(dgmanhua|acgwd|magayuan|manhua456|dashumanhua|shilunart|mh160|szcdmj)\.(com|cc)\/(comic|manhua|manga|maga|kanmanhua|szcbook)\/[\w-]+\/?$/,
            /www\.mhua5\.com\/[\w-]+\.html/,
            /m\.guoman\.net\/comic\/\w+/,
            /(www|m)\.77mh\.\w+\/colist_\d+\.html/,
            /www\.manhw\.com\/index\.php\/comic\/\w+$/,
            /m\.gaonaojin\.com\/\w+\/$/,
            /rumanhua.com\/\w+\/$/i,
            /haoguoman\.net\/\d+$/,
            /^https?:\/\/www\.hmttmh\.com\/book\//
        ],
        init: async () => {
            if (["www.magayuan.com", "m.magayuan.com"].some(h => h === fn.lh)) {
                fn.css(".Introduct_Sub{background:url(https://m.idmzj.com/images/int_bg.png)!important;background-size:100% 100%!important}");
            }
            if (hasTouchEvent) {
                if (["xmanhua", "yymanhua"].some(h => fn.lh.includes(h)) && fn.ge("//a[text()='章節']")) {
                    EClick("//a[text()='章節']");
                }
            }
            if (fn.lh.includes("haoguoman")) {
                setTimeout(() => {
                    EClick(".j-chapter-more");
                }, 1500);
            }
        },
        autoClick: [`
        span.more,
        a.detail-list-form-more,
        a.detail-list-more,
        .deatil-list-more>a,
        .detail-more,
        .moreChapter,
        .show-more,
        a#zhankai,
        .gengduo_dt1>button,
        .morechapter>button,
        .gengduo_dt1>a,
        .chapterList+.more,
        li.add,a.extend,
        a.action-collapse:not(.on),
        .chapter__more .down,
        .listmore,
        .more.chapLiList-cont>a,
        .m-load-more-sm>a,
        .more>a,
        .allmulu,
        .show-more>a,
        .morechp,
        .nnmore>a,
        .chaplist-more>button
        `, 1500],
        hide: ".comic-info-box+a,.cartoon-introduction.cmg,.cartoon-introduction+a,.msloga,.comic_intro>a,.Introduct+a,[class^='ad']",
        category: "none"
    }, {
        name: "94i.in 自動簽到",
        host: ["94i.in"],
        reg: /^https?:\/\/94i\.in\//,
        autoClick: "#pper_a:not([style='display: none;'])",
        category: "none"
    }, {
        name: "Supjav 立即顯示影片縮圖",
        host: ["supjav.com"],
        delay: 300,
        reg: /^https?:\/\/supjav\.com\/(zh\/|ja\/)?\d+\.html/,
        init: async () => {
            let t = fn.ge("title");
            t.innerText = t.innerText.replace(/-\sSupjav.com.+/, "").trim();
            let ele = "#vserver.play-button";
            if (await fn.waitEle(ele)) EClick(ele);
        },
        category: "none"
    }, {
        name: "ouo.io 自動跳轉",
        host: ["ouo.io"],
        reg: /^https?:\/\/ouo\./,
        init: async () => {
            let ele = "#btn-main:not(.disabled)";
            if (await fn.waitEle(ele)) EClick(ele);
        },
        category: "none"
    }, {
        name: "cuty.io 自動跳轉",
        host: ["cuty.io"],
        reg: /^https?:\/\/cutt?y\.(io|app)\/\w+/i,
        init: async () => {
            let ele = "//button[@id='submit-button' and text()= 'Continue' or text()= 'I am not a robot' or text()= 'Go ->']";
            if (await fn.waitEle(ele)) EClick(ele);
        },
        category: "none"
    }, {
        name: "m.4khd.com 自動跳轉",
        host: ["m.4khd.com"],
        url: {
            h: "m.4khd.com",
            p: /^\/\w+$|^\/link\/|^\/vip\//i
        },
        init: () => {
            if (fn.lp.includes("/vip/")) {
                fn.css(FullPictureLoadStyle, "FullPictureLoadMainStyle");
                fn.showMsg("系統錯誤,1秒後關閉。");
                return setTimeout(() => window.close(), 1000);
            }
            const selector = "//a[text()='GET LINK']|//a[span[text()='GET LINK']]";
            if (fn.ge(selector)) {
                let url = fn.gu(selector);
                EClick(selector);
                ge("#cz").innerHTML = "&#9650";
                ge("#zc_tiaozhuan").style.display = "block";
                fn.clearAllTimer(3);
            }
        },
        hide: "#divExoLayerWrapper,.exo-ipp,.exo_wrapper,div:has(>.centered-contai),.center-container,.centered-contai",
        category: "none"
    }, {
        name: "4kup.net 自動跳轉",
        host: ["4kup.net"],
        reg: /^https?:\/\/4kup\.net\/getlink\/$/,
        init: async () => {
            let selectorArr = ["#output:not([style*=none]) button", "#gotolink:not([disabled])"];
            for (let selector of selectorArr) {
                await fn.waitEle(selector);
                EClick(selector);
                await delay(200);
            }
        },
        category: "none"
    }, {
        name: "terabox.fun 自動跳轉",
        host: ["terabox.fun"],
        reg: /^https?:\/\/terabox\.fun\/slmiddlepage\//,
        init: async () => {
            let ele = ".btn.active";
            setInterval(async () => {
                if (await fn.waitEle(ele)) EClick(ele);
            }, 1000);
        },
        category: "none"
    }, {
        name: "MediaFire 自動下載",
        host: ["www.mediafire.com"],
        reg: /^https?:\/\/www\.mediafire\.com\//,
        autoClick: ".download_link:not(.started) #downloadButton",
        category: "none"
    }, {
        name: "anonfiles 自動下載",
        host: ["anonfiles.com"],
        reg: /^https?:\/\/anonfiles\.com\//,
        autoClick: ["#download-url"],
        category: "none"
    }, {
        name: "letsupload 自動下載",
        host: ["letsupload.cc"],
        reg: /^https?:\/\/letsupload\.cc\//,
        autoClick: ["#download-url"],
        category: "none"
    }, {
        name: "stfly.me 半自動跳轉",
        host: ["stfly.me"],
        reg: () => fn.ge("img[src^='https://stfly.me/']") ? true : false,
        init: async () => {
            if (await fn.waitEle(".btn-captcha:not(.disable)")) setInterval(() => EClick(".btn-captcha:not(.disable)"), 3000);
        },
        category: "none"
    }, {
        name: "link1s 自動跳轉",
        host: ["link1s.com"],
        reg: () => fn.ge("a.site-logo[href='https://link1s.com/'],a.logo-image[href='https://link1s.com/']") ? true : false,
        init: async () => {
            if (await fn.waitEle("//button[@onclick='link1sgo()'] | //button[@id='link' and contains(@style,'none')] | //a[text()='Get Link']")) EClick("//button[@onclick='link1sgo()'] | //a[@id='link1s'] | //a[text()='Get Link']");
        },
        category: "none"
    }, {
        name: "Binto.click 自動跳轉",
        host: ["binto.click"],
        reg: () => /^https?:\/\/binto\.click\/\w+$/i.test(siteUrl) && fn.ge("#go-link"),
        init: async () => {
            if (await fn.waitEle("//a[text()='Get Link']")) location.href = fn.gu("//a[text()='Get Link']");
        },
        category: "none"
    }, {
        name: "網址清單新分頁開啟",
        host: ["github.com"],
        reg: [
            /github\.com\/skofkyo\/AutoPager\/tree\/main\/CustomPictureDownload$/,
            /github\.com\/skofkyo\/AutoPager\/blob\/main\/CustomPictureDownload\/README\.md$/
        ],
        init: async () => await fn.waitEle(".markdown-body a"),
        openInNewTab: ".markdown-body a[href]:not([target=_blank]):not([id])",
        css: ".markdown-body a{text-decoration:none!important}",
        category: "none"
    }, {
        name: "google search 新分頁開啟",
        url: {
            h: "google.",
            p: "/search"
        },
        openInNewTab: "#center_col a:not([target])",
        category: "none"
    }, {
        name: "CivitAi Auto Show NSFW",
        host: ["civitai.com"],
        reg: /^https?:\/\/civitai\.com\//,
        init: async () => {
            await fn.waitEle("img[src*='width='],video[src*='width=']");
            //自動顯示NSFW
            const unBlur = async () => {
                if (/\/posts\/|\/models\//.test(fn.lp)) {
                    try {
                        let [ele] = [...document.querySelectorAll(".mantine-1t4bhd4")];
                        let elePath = ele.querySelector("span>svg>path");
                        if (elePath) {
                            let d = elePath.getAttribute("d");
                            if (d == "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0") EClick(ele);
                            await delay(1000);
                        }
                    } catch {}
                }
                [...document.querySelectorAll("button.cursor-pointer")].forEach(ele => {
                    let elePath = ele.querySelector("span>svg>path");
                    if (elePath) {
                        let d = elePath.getAttribute("d");
                        if (d == "M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0") EClick(ele);
                    }
                });
            };
            fn.addMutationObserver(unBlur);
            //將預覽縮圖替換為原始圖片,延遲載入原始圖片URL,透過腳本管理器選單開啟。
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("img[src*='width=']:not([src^='data'],.mantine-Avatar-image,.mantine-anvagt,.mantine-d881q8,.mantine-cdh9bk,.mantine-qh395j,.mantine-7aj0so[loading],.mantine-34i7e7,.mantine-lrbwmi,.mantine-14evxiu)")].forEach(item => {
                        //console.log(item);
                        if (!/\.mp4/.test(item.dataset.src ?? item.src)) {
                            let thumbnail = item.dataset.src ?? item.src;
                            item.dataset.thumb = thumbnail;
                            item.dataset.url = thumbnail.replace(/width=[\d+\.]\//, ""); //Original Image URL to replace when an error occurs
                            let original = thumbnail.replace(/width=[\d\.]+\//, "original=true/");
                            let [imgDir] = original.match(/.+\//);
                            if (item.alt != "" && /\.\w+$/.test(item.alt)) original = imgDir + item.alt.trim();
                            item.dataset.src = original;
                            item.src = loading_bak;
                            fn.imagesObserver.observe(item);
                        }
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img[src*=original]:not([src^='data'],.mantine-Avatar-image,.mantine-anvagt,.mantine-d881q8,.mantine-cdh9bk,.mantine-qh395j,.mantine-7aj0so[loading],.mantine-34i7e7,.mantine-lrbwmi,.mantine-14evxiu),img[data-src*=original]:not(.mantine-Avatar-image,.mantine-anvagt,.mantine-d881q8,.mantine-cdh9bk,.mantine-qh395j,.mantine-7aj0so[loading],.mantine-34i7e7,.mantine-lrbwmi,.mantine-14evxiu)",
        css: "img[src^=data]{margin:auto;}img[src*=original]:not([src^='data'],.mantine-Avatar-image,.mantine-anvagt,.mantine-d881q8,.mantine-cdh9bk,.mantine-qh395j,.mantine-34i7e7){margin: 0 auto !important;width:unset !important;height:unset !important;max-width:100% !important;max-height:100% !important;min-width:unset !important;min-height:unset !important}",
        category: "lazyLoad"
    }, {
        name: "LiblibAI",
        host: ["www.liblib.art"],
        reg: /^https?:\/\/www\.liblib\.art\//,
        init: () => {
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("img.bg-lighter:not([data-src])")].forEach(img => {
                        let thumbnail = img.dataset.src ?? img.src;
                        img.dataset.thumb = thumbnail.replace(/\?image_process=.+/, "") + "?image_process=format,webp&x-oss-process=image/resize,w_600,m_lfit/format,webp";
                        let original = thumbnail.replace(/\?image_process=.+/, "");
                        img.dataset.src = original;
                        img.src = thumbnail;
                        fn.imagesObserver.observe(img);
                    });
                    [...document.querySelectorAll(".relative.cursor-pointer>img:not(.rounded-full,[data-src]),div.image-card img.CarouselWrap_imgItem__h90eB:not([data-src])")].forEach(img => {
                        let thumbnail = img.dataset.src ?? img.src;
                        img.dataset.thumb = thumbnail.replace(/\?x-oss-process=image.+/, "") + "?x-oss-process=image/resize,w_600,m_lfit/format,webp";
                        let original = thumbnail.replace(/\?x-oss-process=image.+/, "");
                        img.dataset.src = original;
                        img.src = thumbnail;
                        fn.imagesObserver.observe(img);
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img.bg-lighter[data-src],.relative.cursor-pointer>img[data-src],div.image-card img.CarouselWrap_imgItem__h90eB[data-src]",
        category: "lazyLoad"
    }, {
        name: "Tensor.Art",
        host: ["tensor.art"],
        reg: /^https?:\/\/tensor\.art\//,
        init: () => {
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll(".thumbnail-image.transition-transform>img.w-full.h-full:not([data-src]),.thumbnail-image.cursor-pointer>img.w-full.h-full:not([data-src])")].forEach(img => {
                        let thumbnail = img.dataset.src ?? img.src;
                        let splitArr = thumbnail.split("/");
                        let bigSrc;
                        if (splitArr.length == 9 || splitArr.length == 10) {
                            splitArr[5] = "w=3840";
                            bigSrc = splitArr.join("/");
                        } else {
                            bigSrc = thumbnail;
                        }
                        img.dataset.src = bigSrc;
                        img.src = loading_bak;
                        fn.imagesObserver.observe(img);
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: ".thumbnail-image>img[data-src]",
        css: ".thumbnail-image>img{width:unset !important;height:unset !important;max-width:100% !important;max-height:100% !important;min-width:unset !important;min-height:unset !important;margin:0px auto}",
        category: "lazyLoad"
    }, {
        name: "PixAI",
        host: ["pixai.art"],
        reg: /^https?:\/\/pixai\.art\//,
        init: async () => {
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("img.object-cover[src*='/stillThumb/']:not([data-src])")].forEach(img => {
                        let thumbnail = img.src;
                        img.dataset.thumb = thumbnail;
                        img.dataset.src = thumbnail.replace("/stillThumb/", "/orig/");
                        img.src = loading_bak;
                        fn.imagesObserver.observe(img);
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img.object-contain,a.group img[data-src]",
        css: "a.group img.object-cover{width:unset !important;height:unset !important;max-width:100% !important;max-height:100% !important;min-width:unset !important;min-height:unset !important;margin:0px auto}",
        category: "lazyLoad"
    }, {
        name: "Yodayo",
        host: ["yodayo.com"],
        reg: /^https?:\/\/yodayo\.com\/explore\//,
        init: async () => {
            await fn.waitEle("img[alt='post thumbnail']");
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("img[alt='post thumbnail']:not([data-src])")].forEach(img => {
                        let thumbnail = img.dataset.src ?? img.src;
                        img.dataset.thumb = thumbnail;
                        fn.fetchDoc(img.parentNode.parentNode.href).then(dom => {
                            let original = dom.querySelector(".image-gallery-image").src;
                            img.dataset.src = original;
                            img.src = original;
                        });
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img[alt='post thumbnail'][data-src]",
        category: "lazyLoad"
    }, {
        name: "NightCafe Creator",
        host: ["creator.nightcafe.studio"],
        reg: /^https?:\/\/creator\.nightcafe\.studio\//,
        init: async () => {
            await fn.waitEle("img.css-9whsf3");
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    setTimeout(() => {
                        [...document.querySelectorAll("img.css-9whsf3:not([data-src])")].forEach(img => {
                            let thumbnail = img.dataset.src ?? img.src;
                            img.dataset.thumb = thumbnail;
                            let original = thumbnail.replace(/\?.+$/, "");
                            img.dataset.src = original;
                            img.src = loading_bak;
                            fn.imagesObserver.observe(img);
                        });
                    }, 200)
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img.css-9whsf3[data-src]",
        css: "img.css-9whsf3{width:unset !important;height:unset !important;max-width:100% !important;max-height:100% !important;min-width:unset !important;min-height:unset !important}",
        category: "lazyLoad"
    }, {
        name: "Midjourney",
        host: ["midjourney.com"],
        reg: /^https?:\/\/legacy\.midjourney\.com\//,
        capture: "img[data-job-id]",
        category: "lazyLoad"
    }, {
        name: "neural.love",
        host: ["neural.love"],
        reg: /^https?:\/\/neural\.love\//,
        init: async () => {
            await fn.waitEle("a.shadow.bg-dark,img[src*='cdn/ai-photostoc']");
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("a.shadow.bg-dark:not([data-src]):not([fetch])")].forEach(a => {
                        a.setAttribute("fetch", "fetch");
                        let id = a.href.split("/")[4];
                        let api = `https://saas.neural.love/api/ai-photostock/orders/${id}?id=${id}`;
                        fetch(api).then(res => res.json()).then(json => {
                            let [data] = json.output;
                            let original = data.full ?? data.fullWebp;
                            a.dataset.src = original;
                            a.style.backgroundImage = `url("${original}")`;
                        });
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "a.shadow.bg-dark[data-src],img[src*='cdn/ai-photostoc']",
        category: "lazyLoad"
    }, {
        name: "Playground",
        host: ["playground.com"],
        link: "https://playground.com/feed",
        reg: /^https?:\/\/playground\.com\//,
        init: async () => {
            await fn.waitEle("a.image-card-grid,img[data-testid=image-post-image]");
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = async () => {
                    let postImg = document.querySelector("img[data-testid=image-post-image]");
                    if (postImg) {
                        let original = document.querySelector("meta[property='og:image'][content]").content;
                        postImg.dataset.src = original;
                        fn.imagesObserver.observe(postImg);
                    }
                    let aEles = [...document.querySelectorAll("a.image-card-grid:not([data-src]):not([fetch])")];
                    aEles.forEach(a => a.setAttribute("fetch", "fetch"));
                    aEles.map(async a => {
                        let img = fn.ge("img", a);
                        if (img) {
                            let src = img.src;
                            let testSrc = src.replace(/\.jpe?g$/, ".png");
                            let original = await new Promise((resolve) => {
                                fetch(testSrc, {
                                    method: "HEAD"
                                }).then((res) => {
                                    if (res.status == 200) {
                                        resolve(testSrc);
                                    } else {
                                        resolve(src);
                                    }
                                }).catch((error) => {
                                    resolve(src);
                                });
                            });
                            a.dataset.src = original;
                            img.dataset.src = original;
                            fn.imagesObserver.observe(img);
                        }
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "a.image-card-grid[data-src],img[data-testid=image-post-image][data-src]",
        category: "lazyLoad"
    }, {
        name: "Pornderful.ai",
        host: ["pornderful.ai"],
        reg: /^https?:\/\/pornderful\.ai\//,
        init: async () => {
            await fn.waitEle("a.tw-relative");
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("a.tw-relative:not([data-src]):not([fetch])")].forEach(a => {
                        a.setAttribute("fetch", "fetch");
                        fn.fetchDoc(a.href).then(dom => {
                            let data = JSON.parse(dom.querySelector("generator-v3-component").attributes[0].nodeValue);
                            let original = data.path;
                            a.dataset.src = original;
                            let img = a.querySelector("img");
                            img.dataset.src = original;
                            img.src = loading_bak;
                            fn.imagesObserver.observe(img);
                        });
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "a.tw-relative[data-src]",
        observerClick: "button.tw-mx-auto",
        category: "lazyLoad"
    }, {
        name: "SeaArt AI",
        host: ["www.seaart.ai"],
        reg: /^https?:\/\/www\.seaart\.ai\//,
        init: async () => {
            if (lazyLoadFullResolution == 1) {
                const lazyLoad = () => {
                    [...document.querySelectorAll("img[src*='low.']:not([data-src])")].forEach(img => {
                        let thumbnail = img.dataset.src ?? img.src;
                        img.dataset.thumb = thumbnail;
                        let original = thumbnail.replace("_low.", "_high.");
                        img.dataset.src = original;
                        img.src = loading_bak;
                        fn.imagesObserver.observe(img);
                    });
                };
                fn.addMutationObserver(lazyLoad);
            }
        },
        capture: "img[data-src*='_high.']",
        css: "*{backdrop-filter:unset!important}",
        category: "lazyLoad"
    }];

    //const debug = (str, obj = "", title = "debug") => console.log(`%c[Full Picture Load] ${title}:`, "background-color: #C9FFC9;", str, obj);
    function debug(str, obj = "", title = "debug") {
        console.log(`%c[Full Picture Load] ${title}:`, "background-color: #C9FFC9;", str, obj);
    }

    function getType(object) {
        return Object.prototype.toString.call(object).replace("[object ", "").replace("]", "");
    }

    const hasTouchEvent = ("ontouchstart" in _unsafeWindow);
    const isFirefox = _unsafeWindow.navigator.userAgent.includes("Firefox");
    const isXBrowser = ("mbrowser" in _unsafeWindow) && !!_unsafeWindow?.mbrowser?.GM_xmlhttpRequest;
    const isVia = ("via" in _unsafeWindow) && ("via_gm" in _unsafeWindow);
    const isString = str => getType(str) === "String";
    const isNumber = num => getType(num) === "Number";
    const isBoolean = b => getType(b) === "Boolean";
    const isRegExp = reg => getType(reg) === "RegExp";
    const isObject = obj => getType(obj) === "Object";
    const isArray = arr => getType(arr) === "Array";
    const isSet = set => getType(set) === "Set";
    const isFn = fn => getType(fn).endsWith("Function");
    const isPromise = p => getType(p) === "Promise";
    const isEle = e => (getType(e).startsWith("HTML") && getType(e).endsWith("Element")) || getType(e) === "DocumentFragment";
    const isURL = (url) => {
        if ("canParse" in URL) {
            return URL.canParse(url);
        }
        try {
            new URL(url);
            return true;
        } catch {
            return false;
        }
    };
    const _GM_xmlhttpRequest = (() => isFn(GM_xmlhttpRequest) ? GM_xmlhttpRequest : GM.xmlHttpRequest)();
    const _GM_openInTab = (() => isFn(GM_openInTab) ? GM_openInTab : GM.openInTab)();
    const _GM_getValue = (() => isFn(GM_getValue) ? GM_getValue : GM.getValue)();
    const _GM_setValue = (() => isFn(GM_setValue) ? GM_setValue : GM.setValue)();
    const _GM_listValues = (() => isFn(GM_listValues) ? GM_listValues : GM.listValues)();
    const _GM_deleteValue = (() => isFn(GM_deleteValue) ? GM_deleteValue : GM.deleteValue)();
    const _GM_registerMenuCommand = (() => isFn(GM_registerMenuCommand) ? GM_registerMenuCommand : GM.registerMenuCommand)();
    const _GM_unregisterMenuCommand = (() => isFn(GM_unregisterMenuCommand) ? GM_unregisterMenuCommand : GM.unregisterMenuCommand)();
    const _GM_getResourceText = (() => isFn(GM_getResourceText) ? GM_getResourceText : GM.getResourceText)();
    const _GM_addElement = (() => isFn(GM_addElement) ? GM_addElement : GM.addElement)();

    const ajaxHookerJS = _GM_getResourceText("ajaxHookerJS");
    const JqueryJS = _GM_getResourceText("JqueryJS");
    const FancyboxV5JS = _GM_getResourceText("FancyboxV5JS");
    const FancyboxV5Css = _GM_getResourceText("FancyboxV5Css");
    const FancyboxV3JS = _GM_getResourceText("FancyboxV3JS");
    const FancyboxV3Css = _GM_getResourceText("FancyboxV3Css");
    const ViewerJs = _GM_getResourceText("ViewerJs");
    const ViewerJsCss = _GM_getResourceText("ViewerJsCss");

    const addAjaxHookerLibrary = () => {
        if (!("ajaxHooker" in _unsafeWindow)) {
            _GM_addElement(document.body, "script", {
                textContent: ajaxHookerJS
            });
        }
        return _unsafeWindow.ajaxHooker;
    };

    const addLibrarysV3 = async () => {
        try {
            const jsArr = [JqueryJS, FancyboxV3JS];
            for (let [i, code] of jsArr.entries()) {
                if (i == 0 && ("jQuery" in _unsafeWindow)) continue;
                //fn.script(code, 0, 1);
                _GM_addElement(document.body, "script", {
                    textContent: code
                });
            }
            if (siteData.fancybox && siteData.fancybox.css !== false) {
                fn.css(FancyboxV3Css, "FancyboxV3Css");
            }
        } catch (error) {
            console.error("\naddLibrarysV3() 注入函式庫失敗", error);
        }
    };

    const addLibrarysV5 = () => {
        try {
            const jsArr = [JqueryJS, FancyboxV5JS];
            for (let [i, code] of jsArr.entries()) {
                if (i == 0 && ("jQuery" in _unsafeWindow)) continue;
                //fn.script(code, 0, 1);
                _GM_addElement(document.body, "script", {
                    textContent: code
                });
            }
            fn.css(FancyboxV5Css);
        } catch (error) {
            console.error("\naddLibrarysV5() 注入函式庫失敗", error);
        }
    };

    const FancyboxWheelValue = _GM_getValue("FancyboxWheel", 1);
    let FancyboxWheel;
    if (FancyboxWheelValue == 0) {
        FancyboxWheel = "zoom";
    } else {
        FancyboxWheel = "slide";
    }
    const FancyboxSlideshowTimeout = Number(_GM_getValue("FancyboxSlideshowTimeout", 3));
    const FancyboxSlideshowTimeoutNum = FancyboxSlideshowTimeout == 0 ? 500 : (FancyboxSlideshowTimeout * 1000);
    const FancyboxSlideshowTransition = _GM_getValue("FancyboxSlideshowTransition", "fade") == "no" ? "false" : _GM_getValue("FancyboxSlideshowTransition", "fade");

    let isOpenFancybox = false;
    let FancyboxOptions;
    let slideIndex = null;

    if (hasTouchEvent) {
        FancyboxOptions = {
            Hash: false,
            idle: false,
            showClass: false,
            hideClass: false,
            Images: {
                Panzoom: {
                    maxScale: 2
                },
                zoom: false
            },
            Slideshow: {
                timeout: FancyboxSlideshowTimeoutNum,
            },
            Carousel: {
                transition: FancyboxSlideshowTransition,
            },
            Thumbs: {
                showOnStart: false
            },
            Toolbar: {
                display: {
                    left: ["infobar"],
                    middle: ["flipX", "flipY"],
                    right: ["iterateZoom", "slideshow", "thumbs", "close"]
                }
            },
            on: {
                done: (fancybox, slide) => {
                    if (fancybox.isCurrentSlide(slide)) {
                        slideIndex = slide.index;
                        fn.scrollEvent(slideIndex);
                    } else {
                        fn.scrollEvent(fancybox.getSlide().index);
                    }
                },
                close: fancybox => {
                    document.body.classList.remove("imgbox-show", "hide-scrollbar");
                    slideIndex = fancybox.getSlide().index;
                    fn.scrollEvent(slideIndex);
                }
            }
        };
    } else {
        FancyboxOptions = {
            Hash: false,
            idle: false,
            showClass: false,
            hideClass: false,
            wheel: FancyboxWheel,
            Images: {
                Panzoom: {
                    maxScale: 2
                },
                zoom: false
            },
            Slideshow: {
                timeout: FancyboxSlideshowTimeoutNum,
            },
            Carousel: {
                transition: FancyboxSlideshowTransition
            },
            Thumbs: {
                showOnStart: false
            },
            Toolbar: {
                display: {
                    left: ["infobar"],
                    middle: ["zoomIn", "zoomOut", "iterateZoom", "toggle1to1", "rotateCCW", "rotateCW", "flipX", "flipY", "fitX", "fitY", "reset"],
                    right: ["slideshow", "fullscreen", "thumbs", "close"]
                }
            },
            on: {
                done: (fancybox, slide) => {
                    isOpenFancybox = true;
                    if (fancybox.isCurrentSlide(slide)) {
                        slideIndex = slide.index;
                        fn.scrollEvent(slideIndex);
                    } else {
                        fn.scrollEvent(fancybox.getSlide().index);
                    }
                },
                close: fancybox => {
                    document.body.classList.remove("imgbox-show", "hide-scrollbar");
                    slideIndex = fancybox.getSlide().index;
                    fn.scrollEvent(slideIndex);
                    setTimeout(() => {
                        isOpenFancybox = false;
                    }, 100);
                }
            }
        };
    }

    const fancyboxBlackList = () => siteData.fancybox?.blacklist === 1;

    //顯示語言
    switch (language) {
        case "zh-TW":
        case "zh-HK":
        case "zh-MO":
        case "zh-Hant-TW":
        case "zh-Hant-HK":
        case "zh-Hant-MO":
            displayLanguage = {
                str_01: "獲取圖片元素中...",
                str_02: "獲取圖片中 ",
                str_03: "獲取圖片逾時",
                str_04: "等待關鍵元素中...",
                str_05: "獲取資料中...",
                str_06: "獲取資料中 ",
                str_07: "確認登錄狀態中...",
                str_08: "獲取預覽圖中...",
                str_09: "獲取最後一張圖...",
                str_10: "是否複製連結至剪貼簿?",
                str_11: "已複製連結至剪貼簿",
                str_12: "只有複製連結功能",
                str_13: "請輸入圖片抓取最大次數",
                str_14: "獲取下一頁中...",
                str_15: "獲取下一頁結束",
                str_16: "獲取元素中...",
                str_17: "獲取元素中 ",
                str_18: "已聚集所有圖片",
                str_19: "用來定位插入的元素不存在",
                str_20: "沒有能插入的圖片",
                str_21: "延遲",
                str_22: "毫秒",
                str_23: "第",
                str_24: "張下載",
                str_25: "完成",
                str_26: "錯誤",
                str_27: "下載失敗了",
                str_28: "張",
                str_29: "\n是否只保存目前下載成功的圖片?\n只要圖片不是100%掛掉,可以調低下載線程數或重新載入網頁後重新下載試試看。",
                str_30: "圖片extension錯誤",
                str_31: "壓縮進度: ",
                str_32: "自動下載倒數",
                str_33: "秒",
                str_34: "nextJS前往下一頁",
                str_35: "已點擊下一頁",
                str_36: "自動下載完畢",
                str_37: "沒有下一頁元素",
                str_38: "返回上一頁",
                str_39: "已點擊上一頁",
                str_40: "沒有上一頁元素",
                str_41: "已取消",
                str_42: "字數小於3已取消",
                str_43: "下載失敗數據為空...",
                str_44: "沒有任何圖片元素...",
                str_45: "網址已複製",
                str_46: "即將進行滾動...",
                str_47: "左鍵:進行下載打包壓縮\n中鍵:匯出網址URLs.txt文件\n右鍵:複製圖片網址和標題或手動模式聚集所有圖片",
                str_48: "下載&壓縮中請稍後再操作!",
                str_49: "獲取圖片中請稍後再操作!",
                str_50: "自訂網站收藏的網址在新分頁開啟",
                str_51: "請輸入自訂壓縮檔資料夾名稱",
                str_52: "聚圖數量",
                str_53: "圖片繪製中...",
                str_54: "403,未登錄網站?",
                str_55: "下載載入中...",
                str_56: "確認圖片狀態中...",
                str_57: "自動翻頁載入中...",
                str_58: "已到達最後一頁",
                str_59: "沒有任何主體元素",
                str_60: "圖片縮放",
                str_61: "取消縮放",
                str_62: "前往第一張圖",
                str_63: "左鍵:前往最後一張圖\n右鍵:匯出網址URLs.txt文件",
                str_64: "即將開始自動下載!!!",
                str_65: "已停止自動下載!!!",
                str_66: "💬 反饋",
                str_67: "⚙️ 設定",
                str_68: "當前(※全局)網站 Full Picture Load 選項",
                str_69: "顯示左下圖示按鈕",
                str_70: "最大下載線程數:",
                str_71: "下載後壓縮打包",
                str_72: "壓縮檔副檔名:",
                str_73: "自動下載",
                str_74: " ( 快捷鍵 [ ctrl + . ] 開始或取消 )",
                str_75: "自動下載倒數秒數:",
                str_76: "啟用當前漫畫站點規則",
                str_77: "移動裝置雙擊前往下一頁",
                str_78: "Fancybox燈箱功能",
                str_79: "頁面容器圖片縮放比例:",
                str_80: "頁面容器圖片並排數量:",
                str_81: "comic類固定為2,comic類並排後為右至左的漫讀模式,hcomic類也設定為2將套用。",
                str_82: hasTouchEvent ? "取消" : "取消 (Esc)",
                str_83: "重置設定",
                str_84: "保存設定",
                str_85: hasTouchEvent ? "腳本選項" : "腳本選項(*)",
                str_86: hasTouchEvent ? "切換模式" : "切換模式(5)",
                str_87: hasTouchEvent ? "比例縮放" : "比例縮放(-+)",
                str_88: hasTouchEvent ? "取消縮放" : "取消縮放(.)",
                str_89: "暫停自動翻頁",
                str_90: "啟用自動翻頁",
                str_91: "初始化設定",
                str_92: "原始模式",
                str_93: "並排模式",
                str_94: "返回開頭了",
                str_95: "前往下一集",
                str_96: "已是最後一集",
                str_97: "共",
                str_98: "頁獲取出錯,建議反饋",
                str_99: "重試第",
                str_100: "次",
                str_101: "網址.txt已匯出",
                str_102: "格式轉換中...",
                str_103: "頁面容器預設使用並排模式",
                str_104: hasTouchEvent ? "匯出圖址" : "匯出圖址(7)",
                str_105: hasTouchEvent ? "複製圖址" : "複製圖址(1)",
                str_106: hasTouchEvent ? "分頁畫廊" : "分頁畫廊(8)",
                str_107: hasTouchEvent ? "一鍵下載" : "一鍵下載(3)",
                str_108: "※訊息提示顯示的位置:",
                str_109: {
                    c: "置中",
                    ul: "左上",
                    ur: "右上",
                    ll: "左下",
                    lr: "右下",
                },
                str_110: "※Webp轉換為Jpg",
                str_111: "惰性載入大圖",
                str_112: "惰性載入單欄布局",
                str_113: "惰性載入預讀大圖",
                str_114: "E/EX-HENTAI 載入原始圖片連結",
                str_115: "關閉自動滾動至首張圖片",
                str_116: "自動滾動所有惰性載入的圖片元素",
                str_117: "顯示浮動選單",
                str_118: "圖集標題已更新",
                str_119: "FancyboxV5滾輪圖片縮放",
                str_120: "此網站分頁畫廊使用ViewerJs插件",
                str_121: "關閉頁面容器圖片導覽快捷鍵",
                str_122: "此漫畫站使用無限滾動閱讀模式",
                str_123: "顯示右下捕獲之眼圖示",
                str_124: "此網站下載影片",
                str_125: "🔄 重置此網站儲存的所有腳本設定",
                str_126: "🔄 重置腳本儲存的所有全局設定",
                str_127: "右鍵:匯出圖址(7)",
                str_128: hasTouchEvent ? "開啟收藏" : "開啟收藏(9)",
                str_129: "關閉收藏",
                str_130: "編輯收藏",
                str_131: "保存",
                str_132: "關閉",
                str_133: "選單",
                str_134: "浮動選單",
                str_135: "無限滾動初始化中...",
                str_136: "右鍵:增加圖片縮放級別(+)",
                str_137: "頁面圖片添加燈箱模式",
                str_138: "此網站禁用",
                str_139: "自動聚圖至頁面容器",
                str_140: "自動進入影子畫廊",
                str_141: hasTouchEvent ? "影子畫廊" : "影子畫廊(G)",
                str_142: "離開畫廊 (Esc)",
                str_143: "下一話",
                str_144: "下一篇",
                str_145: "Fancybox5&ViewerJs 幻燈片播放間隔:",
                str_146: "Fancybox5滾輪操作:",
                str_147: "畫廊 ( 0、1、3 ) 滾輪操作:",
                str_148: "Fancybox5幻燈片過場效果:",
                str_149: "已取消下載!!!",
                str_150: "JK滾動",
                str_151: "JK平滑滾動",
                str_152: "視口高",
                str_153: "標題:",
                str_154: "全部選取",
                str_155: "取消全選",
                str_156: "重新載入",
                str_157: "開始下載",
                str_158: hasTouchEvent ? "篩選下載" : "篩選下載(F)",
                str_159: hasTouchEvent ? "自訂函式" : "自訂函式(6)",
                str_160: hasTouchEvent ? "插入圖片" : "插入圖片(1)",
                str_161: "同時載入的圖片數量:",
                str_162: "圖片預載數:",
                str_163: "🖼️ 開啟簡易模式",
                str_164: "🖼️ 關閉簡易模式",
                str_165: "圖片總數:",
                str_166: "篩選數量:",
                str_167: "篩選寬度:",
                str_168: "篩選高度:",
                str_169: "佈景主題:",
                str_170: "反向選取",
                str_171: "顯示檔案大小",
                str_172: "拖動排序",
                str_173: "可拖動圖片來改變圖片順序。",
                str_174: "匯出JSON格式",
                str_175: "已匯出JSON格式",
                str_176: "匯出為MD格式",
                str_177: "已匯出Markdown格式",
                str_178: "複製為MD格式",
                str_179: "複製為Markdown格式",
                str_180: "自動匯出URLs.txt",
                galleryMenu: {
                    webtoon: hasTouchEvent ? "條漫模式" : "條漫模式 (4,+,-)",
                    rtl: hasTouchEvent ? "右至左模式" : "右至左模式 (3,R)",
                    small: hasTouchEvent ? "小圖像模式" : "小圖像模式 (2,R)",
                    single: hasTouchEvent ? "單圖像模式" : "單圖像模式 (1)",
                    default: hasTouchEvent ? "預設模式" : "預設模式 (0,R)",
                },
                FancyboxWheel: {
                    z: "圖片縮放",
                    s: "圖片切換"
                },
                FancyboxTransition: {
                    crossfade: "淡入淡出",
                    fade: "淡出",
                    slide: "滑動",
                    classic: "經典",
                    no: "無過場效果"
                },
                ShadowGalleryWheel: {
                    d: "畫廊滾動",
                    t: "圖片切換",
                    s: "圖列切換"
                },
                backgroundColor: {
                    l: "亮色",
                    d: "暗色"
                }
            };
            break;
        case "zh":
        case "zh-CN":
        case "zh-SG":
        case "zh-Hans-CN":
        case "zh-Hans-SG":
            displayLanguage = {
                str_01: "获取图片元素中...",
                str_02: "获取图片中 ",
                str_03: "获取图片逾时",
                str_04: "等待关键元素中...",
                str_05: "获取数据中...",
                str_06: "获取数据中 ",
                str_07: "确认登录状态中...",
                str_08: "获取预览图中...",
                str_09: "获取最后一张图...",
                str_10: "是否拷贝链接至剪贴板?",
                str_11: "已拷贝链接至剪贴板",
                str_12: "只有拷贝链接功能",
                str_13: "请输入图片抓取最大次数",
                str_14: "获取下一页中...",
                str_15: "获取下一页结束",
                str_16: "获取元素中...",
                str_17: "获取元素中 ",
                str_18: "已聚集所有图片",
                str_19: "用来定位插入的元素不存在",
                str_20: "没有能插入的图片",
                str_21: "延迟",
                str_22: "毫秒",
                str_23: "第",
                str_24: "张下载",
                str_25: "完成",
                str_26: "错误",
                str_27: "下载失败了",
                str_28: "张",
                str_29: "\n是否只保存目前下载成功的图片?\n只要图片不是100%挂掉,可以调低下载线程数或重新加载网页后重新下载试试看。",
                str_30: "图片extension错误",
                str_31: "压缩进度: ",
                str_32: "自动下载倒数",
                str_33: "秒",
                str_34: "nextJS前往下一页",
                str_35: "已点击下一页",
                str_36: "自动下载完毕",
                str_37: "没有下一页元素",
                str_38: "返回上一页",
                str_39: "已点击上一页",
                str_40: "没有上一页元素",
                str_41: "已取消",
                str_42: "字数小于3已取消",
                str_43: "下载失败数据为空...",
                str_44: "没有任何图片元素...",
                str_45: "网址已拷贝",
                str_46: "即将进行滚动...",
                str_47: "左键:进行下载打包压缩\n中键:导出网址URLs.txt文档\n右键:拷贝图片网址和标题或手动模式聚集所有图片",
                str_48: "下载&压缩中请稍后再操作!",
                str_49: "获取图片中请稍后再操作!",
                str_50: "自定义网站收藏的网址在新标籤页打开",
                str_51: "请输入自定义压缩档文件夹名称",
                str_52: "聚图数量",
                str_53: "图片绘制中...",
                str_54: "403,未登录网站?",
                str_55: "下载加载中...",
                str_56: "确认图片状态中...",
                str_57: "自动翻页加载中...",
                str_58: "已到达最后一页",
                str_59: "没有任何主体元素",
                str_60: "图片缩放",
                str_61: "取消缩放",
                str_62: "前往第一张图",
                str_63: "左键:前往最后一张图\n右键:导出网址URLs.txt文档",
                str_64: "即将开始自动下载!!!",
                str_65: "已停止自动下载!!!",
                str_66: "💬 反馈",
                str_67: "⚙️ 设置",
                str_68: "当前(※全局)网站 Full Picture Load 设置",
                str_69: "显示左下图标按钮",
                str_70: "下载后最大下载线程数:",
                str_71: "压缩打包",
                str_72: "压缩档文件扩展名:",
                str_73: "自动下载",
                str_74: " ( 快捷键 [ ctrl + . ] 开始或取消 )",
                str_75: "自动下载倒数秒数:",
                str_76: "启用当前漫画站点规则",
                str_77: "移动设备双击前往下一页",
                str_78: "Fancybox灯箱功能",
                str_79: "页面容器图片缩放比例:",
                str_80: "页面容器图片并排数量:",
                str_81: "comic类固定为2,comic类并排后为右至左的漫读模式,hcomic类也设置为2将套用。",
                str_82: hasTouchEvent ? "取消" : "取消 (Esc)",
                str_83: "重置设置",
                str_84: "保存设置",
                str_85: hasTouchEvent ? "脚本设置" : "脚本设置(*)",
                str_86: hasTouchEvent ? "切换模式" : "切换模式(5)",
                str_87: hasTouchEvent ? "比例缩放" : "比例缩放(-+)",
                str_88: hasTouchEvent ? "取消缩放" : "取消缩放(.)",
                str_89: "暂停自动翻页",
                str_90: "启用自动翻页",
                str_91: "初始化设置",
                str_92: "原始模式",
                str_93: "并排模式",
                str_94: "返回开头了",
                str_95: "前往下一集",
                str_96: "已是最后一集",
                str_97: "共",
                str_98: "页获取出错,建议反馈",
                str_99: "重试第",
                str_100: "次",
                str_101: "网址.txt已导出",
                str_102: "格式转换中...",
                str_103: "页面容器默认使用并排模式",
                str_104: hasTouchEvent ? "导出图址" : "导出图址(7)",
                str_105: hasTouchEvent ? "拷贝图址" : "拷贝图址(1)",
                str_106: hasTouchEvent ? "标签画廊" : "标签画廊(8)",
                str_107: hasTouchEvent ? "一键下载" : "一键下载(3)",
                str_108: "※讯息提示显示的位置:",
                str_109: {
                    c: "置中",
                    ul: "左上",
                    ur: "右上",
                    ll: "左下",
                    lr: "右下",
                },
                str_110: "※Webp转换为Jpg",
                str_111: "懒加载大图",
                str_112: "懒加载单栏布局",
                str_113: "懒加载预读大图",
                str_114: "E/EX-HENTAI 加载原始图片链接",
                str_115: "关闭自动滚动至首张图片",
                str_116: "自动滚动所有懒加载的图片元素",
                str_117: "显示浮动菜单",
                str_118: "图集标题已更新",
                str_119: "FancyboxV5滚轮图片缩放",
                str_120: "此网站标签画廊使用ViewerJs插件",
                str_121: "关闭页面容器图片导览快捷键",
                str_122: "此漫画站使用无限滚动阅读模式",
                str_123: "显示右下捕获之眼图标",
                str_124: "此网站下载视频",
                str_125: "🔄 重置此网站存储的所有脚本设置",
                str_126: "🔄 重置脚本存储的所有全局设置",
                str_127: "右键:导出图址(7)",
                str_128: hasTouchEvent ? "打开收藏" : "打开收藏(9)",
                str_129: "关闭收藏",
                str_130: "编辑收藏",
                str_131: "保存",
                str_132: "关闭",
                str_133: "菜单",
                str_134: "浮动菜单",
                str_135: "无限滚动初始化中...",
                str_136: "右键:增加图片缩放级别(+)",
                str_137: "页面图片添加灯箱模式",
                str_138: "此网站禁用",
                str_139: "自动聚图至页面容器",
                str_140: "自動進入影子畫廊",
                str_141: hasTouchEvent ? "影子画廊" : "影子画廊(G)",
                str_142: "离开画廊 (Esc)",
                str_143: "下一话",
                str_144: "下一篇",
                str_145: "Fancybox5&ViewerJs 幻灯片播放间隔:",
                str_146: "Fancybox5滚轮操作:",
                str_147: "画廊 ( 0、1、3 ) 滚轮操作:",
                str_148: "Fancybox5幻灯片过场效果:",
                str_149: "已取消下载!!!",
                str_150: "JK滚动",
                str_151: "JK平滑滚动",
                str_152: "视口高",
                str_153: "标题:",
                str_154: "全部选取",
                str_155: "取消全选",
                str_156: "重新加载",
                str_157: "开始下载",
                str_158: hasTouchEvent ? "筛选下载" : "筛选下载(F)",
                str_159: hasTouchEvent ? "定义函式" : "定义函式(6)",
                str_160: hasTouchEvent ? "插入图片" : "插入图片(1)",
                str_161: "同时加载的图片数量:",
                str_162: "图片预载数:",
                str_163: "🖼️ 开启简易模式",
                str_164: "🖼️ 关闭简易模式",
                str_165: "图片总数:",
                str_166: "筛选数量:",
                str_167: "筛选宽度:",
                str_168: "筛选高度:",
                str_169: "布景主题:",
                str_170: "反向选取",
                str_171: "显示文件大小",
                str_172: "拖动排序",
                str_173: "可拖动图片来改变图片顺序。",
                str_174: "导出JSON格式",
                str_175: "已导出JSON格式",
                str_176: "导出为MD格式",
                str_177: "已导出Markdown格式",
                str_178: "拷贝为MD格式",
                str_179: "拷贝为Markdown格式",
                str_180: "自动导出URLs.txt",
                galleryMenu: {
                    webtoon: hasTouchEvent ? "条漫模式" : "条漫模式 (4,+,-)",
                    rtl: hasTouchEvent ? "右至左模式" : "右至左模式 (3,R)",
                    small: hasTouchEvent ? "小图像模式" : "小图像模式 (2,R)",
                    single: hasTouchEvent ? "单图像模式" : "单图像模式 (1)",
                    default: hasTouchEvent ? "默认模式" : "默认模式 (0,R)",
                },
                FancyboxWheel: {
                    z: "图片缩放",
                    s: "图片切换"
                },
                FancyboxTransition: {
                    crossfade: "淡入淡出",
                    fade: "淡出",
                    slide: "滑动",
                    classic: "经典",
                    no: "无过场效果"
                },
                ShadowGalleryWheel: {
                    d: "画廊滚动",
                    t: "图片切换",
                    s: "图列切换"
                },
                backgroundColor: {
                    l: "亮色",
                    d: "暗色"
                }
            };
            break;
        default:
            displayLanguage = {
                str_01: "Get Images...",
                str_02: "Get Images ",
                str_03: "Get timed out",
                str_04: "Wait Element...",
                str_05: "Get Data...",
                str_06: "Get Data ",
                str_07: "Confirm Login Status",
                str_08: "Get Preview Thumbnail",
                str_09: "Get Element...",
                str_10: "Whether To Copy Link To Clipboard?",
                str_11: "Copied",
                str_12: "Only Link Can Be Copied",
                str_13: "Please Enter The Number Of Images",
                str_14: "Get Next Page...",
                str_15: "Get Next Page End",
                str_16: "Get Element...",
                str_17: "Get Element ",
                str_18: "All Images Gathered",
                str_19: "Element Does Not Exist",
                str_20: "No Images",
                str_21: "Delay",
                str_22: "ms",
                str_23: "No. ",
                str_24: " Download ",
                str_25: "Completed",
                str_26: "Error",
                str_27: "Download Failed",
                str_28: "P",
                str_29: "\nDo you want to save only the Images that have been successfully downloaded so far?\nAs long as the image is not 100% dead, you can reduce the number of download threads or reload the web page and try downloading again.",
                str_30: "Image Extension Error",
                str_31: "Compression Progress: ",
                str_32: "Countdown ",
                str_33: " sec",
                str_34: "JS Go To Next Page",
                str_35: "Next Page Clicked",
                str_36: "AutoDownload Completed",
                str_37: "No Next Page Element",
                str_38: "Return To Previous Page",
                str_39: "Previous Page Clicked",
                str_40: "No Previous Page Element",
                str_41: "Cancelled",
                str_42: "Cancelled",
                str_43: "Download Failed Data Is Empty",
                str_44: "No Picture Element",
                str_45: "URLs Copied ",
                str_46: "About To Scroll...",
                str_47: "Left Click:Download And Compress\nMiddle Click:Export URLs.txt\nRight Click:Copy Image URL And Title Or Aggregate Images",
                str_48: "Downloading & Compressing, Please Try Again Later!",
                str_49: "Get Pictureing Please Try Again Later!",
                str_50: "Favored Website URL Open in New Tab",
                str_51: "Please Enter A Custom zip File Folder Name",
                str_52: "Number Of Images",
                str_53: "Picture Drawing...",
                str_54: "403,Not Logged In To Website?",
                str_55: "Download Loading...",
                str_56: "Check Picture Statusing...",
                str_57: "AutoPager Loading...",
                str_58: "Reached The Last Page",
                str_59: "No Main Element",
                str_60: "Image Zoom",
                str_61: "Cancel Eoom",
                str_62: "Go To First Image",
                str_63: "Left Click:Go To Last Image\nLeft Click:Export URLs.txt",
                str_64: "Start AutoDownload!!!",
                str_65: "Stop AutoDownload!!!",
                str_66: "💬 Feedback",
                str_67: "⚙️ Settings",
                str_68: "Current(※Global) Website Full Picture Load Options",
                str_69: "Show Lower Left Icon Button",
                str_70: "Max Download Thread:",
                str_71: "Compressed Packaging",
                str_72: "Compressed File Extension:",
                str_73: "AutoDownload",
                str_74: " ( [ ctrl + . ] Start or Cancel)",
                str_75: "AutoDownload Countdown Sec:",
                str_76: "Comic Site Rules Switch",
                str_77: "Double Click Go To Next Page",
                str_78: "Fancybox Plugin",
                str_79: "Image Zoom Ratio:",
                str_80: "Number Of Images Side By Side:",
                str_81: "Comic Category Fixed To 2",
                str_82: hasTouchEvent ? "Cancel" : "Cancel (Esc)",
                str_83: "Reset",
                str_84: "Save",
                str_85: hasTouchEvent ? "Settings" : "Settings(*)",
                str_86: hasTouchEvent ? "Toggle" : "ToggleMode(5)",
                str_87: hasTouchEvent ? "Zoom" : "ToggleZoom(-+)",
                str_88: hasTouchEvent ? "Cancel" : "CancelZoom(.)",
                str_89: "Pause Automatic Page Turning",
                str_90: "Enable Automatic Page Turning",
                str_91: "Initialization Settings",
                str_92: "Original Mode",
                str_93: "Side-By-Side Mode",
                str_94: "Back To The Beginning",
                str_95: "Go To Next Episode",
                str_96: "It’s The Last Episode",
                str_97: "Have",
                str_98: "Page Fetch Error Please Feedback",
                str_99: "Retry No.",
                str_100: "Bout",
                str_101: "MediaURLs.txt Exported",
                str_102: "Format Converting",
                str_103: "Enable Side-By-Side Mode",
                str_104: hasTouchEvent ? "Export" : "ExportURLs(7)",
                str_105: hasTouchEvent ? "Copy" : "CopyURLs(1)",
                str_106: hasTouchEvent ? "TabView" : "NewTabView(8)",
                str_107: hasTouchEvent ? "Download" : "FastDownload(3)",
                str_108: "※Where the message appears:",
                str_109: {
                    c: "Center",
                    ul: "Upper left",
                    ur: "Upper right",
                    ll: "Lower left",
                    lr: "Lower right",
                },
                str_110: "※Convert Webp to Jpg",
                str_111: "Lazy Load Full Resolution",
                str_112: "Lazy Load Single Column Layout",
                str_113: "Lazy Load Preload Images",
                str_114: "E/EX-HENTAI Load Original Image",
                str_115: "Turn Off Auto Scroll To First Image",
                str_116: "Auto Scroll All Image Elements",
                str_117: "Show Fixed Menu",
                str_118: "Album title has been updated",
                str_119: "FancyboxV5 Wheel Toggle Zoom",
                str_120: "This Website New Tab View uses ViewerJs Plug-in",
                str_121: "Turn Off Page Content Image Navigation Shortcut Keys",
                str_122: "This website uses Infinite Scroll Read Mode",
                str_123: "Show Capture Eye Icon",
                str_124: "This website downloads videos",
                str_125: "🔄 Reset all script settings stored on this site",
                str_126: "🔄 Reset all saved global settings",
                str_127: "Right Click:Export URLs(7)",
                str_128: hasTouchEvent ? "OpenFavor" : "OpenFavor(9)",
                str_129: "Close Favor",
                str_130: "Edit Favor",
                str_131: "save",
                str_132: "close",
                str_133: "Menu",
                str_134: "Float Menu",
                str_135: "Infinite Scroll Initializing",
                str_136: "Right Click:Increase Image Zzoom Level(+)",
                str_137: "Add Fancybox To Image",
                str_138: "This Website Is Disabled",
                str_139: "Page Content Auto Insert Images",
                str_140: "Enable Shadow Gallery",
                str_141: "Shadow Gallery",
                str_141: hasTouchEvent ? "ShadowGallery" : "ShadowGallery(G)",
                str_142: "Close (Esc)",
                str_143: "Next Chapter",
                str_144: "Next Post",
                str_145: "Fancybox5&ViewerJs Play Delay:",
                str_146: "Fancybox5 Wheel:",
                str_147: "Gallery (0、1、3) Wheel:",
                str_148: "Fancybox5 Slideshow Transition:",
                str_149: "Download Canceled!!!",
                str_150: "JK Scroll ",
                str_151: "JK Smooth Scroll",
                str_152: "Viewport",
                str_153: "Title:",
                str_154: "Select All",
                str_155: "Unselect All",
                str_156: "Reload",
                str_157: "Download",
                str_158: hasTouchEvent ? "FilterDownload" : "FilterDownload(F)",
                str_159: hasTouchEvent ? "Function" : "Function(6)",
                str_160: hasTouchEvent ? "Insert Images" : "Insert Images(1)",
                str_161: "The Number Of Images Loaded At The Same Time:",
                str_162: "Preload:",
                str_163: "🖼️ Enable Simple Mode",
                str_164: "🖼️ Turn Off Simple Mode",
                str_165: "Total Number Of Images:",
                str_166: "Number Of Filters:",
                str_167: "Filter Width:",
                str_168: "Filter Height:",
                str_169: "Setting Theme:",
                str_170: "Reverse Selection",
                str_171: "Show File Size",
                str_172: "Drag Sort",
                str_173: "Drag the image to change the order of images",
                str_174: "Export JSON",
                str_175: "Exported JSON",
                str_176: "Export Markdown",
                str_177: "Exported Markdown",
                str_178: "Copy Markdown",
                str_179: "Copied to Markdown format",
                str_180: "Auto Export URLs.txt",
                galleryMenu: {
                    webtoon: hasTouchEvent ? "Webtoon" : "Webtoon (4,+,-)",
                    rtl: hasTouchEvent ? "Right To Left" : "Right To Left (3,R)",
                    small: hasTouchEvent ? "Small Image" : "Small Image (2,R)",
                    single: hasTouchEvent ? "Single Image" : "Single Image (1)",
                    default: hasTouchEvent ? "Default" : "Default (0,R)",
                },
                FancyboxWheel: {
                    z: "zoom",
                    s: "slide"
                },
                FancyboxTransition: {
                    crossfade: "Crossfade",
                    fade: "Fade",
                    slide: "Slide",
                    classic: "Classic",
                    no: "No Animation"
                },
                ShadowGalleryWheel: {
                    d: "Scroll",
                    t: "Toggle Image",
                    s: "Toggle Row"
                },
                backgroundColor: {
                    l: "Light",
                    d: "Dark"
                }
            };
            break;
    }

    const FullPictureLoadBlacklist = localStorage.getItem("FullPictureLoadBlacklist") ?? 0;
    _GM_registerMenuCommand(displayLanguage.str_66, () => _GM_openInTab("https://greasyfork.org/scripts/463305/feedback"));
    _GM_registerMenuCommand("📓 Github README.md", () => _GM_openInTab("https://github.com/skofkyo/AutoPager/blob/main/CustomPictureDownload/README.md"));
    /*const FullPictureLoadBlacklist_menu_command_id = */
    _GM_registerMenuCommand(FullPictureLoadBlacklist == 0 ? "❌ " + displayLanguage.str_138 : "✔️  " + displayLanguage.str_138, () => {
        FullPictureLoadBlacklist == 0 ? localStorage.setItem("FullPictureLoadBlacklist", 1) : localStorage.setItem("FullPictureLoadBlacklist", 0);
        location.reload();
    });
    if (FullPictureLoadBlacklist == 1) return;

    const fn = {
        url: (() => siteUrl)(),
        lo: (() => _unsafeWindow.location.origin)(),
        lp: (() => _unsafeWindow.location.pathname)(),
        lh: (() => _unsafeWindow.location.hostname)(),
        ls: (() => _unsafeWindow.location.search)(),
        ex: e => {
            const object = {
                j: "jpg",
                p: "png",
                g: "gif",
                w: "webp",
                b: "bmp"
            };
            return object[e];
        },
        checkUrl: (obj = {}) => {
            const {
                h: hosts,
                p: pathname,
                s: search,
                e: elements,
                t: title,
                d: device,
                i: comicInfiniteScroll
            } = obj;
            const {
                imgs: imgSelector,
                customTitle: titleSelector
            } = tempData;
            let checkH = true;
            let checkP = true;
            let checkS = true;
            let checkE = true;
            let checkI = true;
            let checkT = true;
            let checkD = true;
            if ("i" in obj) {
                checkI = comicInfiniteScroll === 0 ? comicInfiniteScrollMode != 1 : comicInfiniteScrollMode == 1;
                if (!checkI) return false;
            }
            if ("d" in obj) {
                if (device === "pc") {
                    checkD = !hasTouchEvent;
                } else if (device === "m") {
                    checkD = hasTouchEvent;
                }
                if (!checkD) return false;
            }
            if ("h" in obj) {
                if (isArray(hosts)) {
                    checkH = hosts.some(h => {
                        if (isRegExp(h)) {
                            return h.test(fn.lh);
                        } else if (isString(h)) {
                            return h === fn.lh;
                        }
                        return false;
                    });
                } else if (isRegExp(hosts)) {
                    checkH = hosts.test(fn.lh);
                } else if (isString(hosts)) {
                    checkH = fn.lh.includes(hosts);
                }
                if (!checkH) return false;
            }
            if ("t" in obj) {
                if (isArray(title)) {
                    checkT = title.some(t => {
                        if (isString(t)) {
                            return document.title.includes(t);
                        } else if (isRegExp(t)) {
                            return t.test(document.title);
                        }
                        return false;
                    });
                } else if (isString(title)) {
                    checkT = document.title.includes(title);
                } else if (isRegExp(title)) {
                    checkT = title.test(document.title);
                }
                if (!checkT) return false;
            }
            if ("e" in obj) {
                if (isArray(elements)) {
                    checkE = elements.every(selector => !!fn.ge(selector));
                } else if (isString(elements)) {
                    checkE = !!fn.ge(elements);
                }
                if (!checkE) return false;
            }
            if ("p" in obj) {
                if (isArray(pathname)) {
                    checkH = pathname.some(p => {
                        if (isRegExp(p)) {
                            return p.test(fn.lp);
                        } else if (isString(p)) {
                            return fn.lp.includes(p);
                        }
                        return false;
                    });
                } else if (isRegExp(pathname)) {
                    checkP = pathname.test(fn.lp);
                } else if (isString(pathname)) {
                    checkP = fn.lp.includes(pathname);
                }
                if (!checkP) return false;
            }
            if ("s" in obj) {
                if (isRegExp(search)) {
                    checkS = search.test(fn.ls);
                } else if (isString(search)) {
                    checkS = fn.ls.includes(search);
                }
                if (!checkS) return false;
            }
            if ("imgs" in tempData && isString(imgSelector) && !("SPA" in tempData)) {
                checkI = !!fn.ge(imgSelector);
            }
            if ("customTitle" in tempData && isString(titleSelector) && !("SPA" in tempData)) {
                checkT = !!fn.ge(titleSelector);
            }
            return checkH && checkP && checkS && checkE && checkI && checkT;
        },
        checkAutoPagerEle: (data = {}) => {
            let check = true;
            const {
                ele: pageElementSelector,
                observer: observerSelector,
                next: nextSelector,
                re: replaceSelector
            } = data;
            const selectors = [
                pageElementSelector,
                observerSelector,
                nextSelector,
                replaceSelector
            ].filter(item => isString(item));
            if (selectors.length > 0) {
                check = selectors.every(selector => !!fn.ge(selector));
                if (check) {
                    debug("\n圖片全載AutoPager\n頁面包含自動翻頁必須的所有元素");
                } else {
                    console.error("\n圖片全載AutoPager\n頁面沒有包含自動翻頁必須的所有元素");
                }
            }
            return check;
        },
        getModeUrl: (url, mode, i) => {
            //【.html ==> .html?page=2】第一頁 ==> 第二頁
            //【 ==> ?page=2】第一頁 ==> 第二頁
            if (mode === 1) return url.replace(/\?page=\d+$/, "") + "?page=" + i;
            //【.html ==> /2.html】 第一頁 ==> 第二頁
            if (mode === 2) return url.slice(0, -5) + "/" + i + ".html";
            //【.html ==> _1.html】  第一頁 ==> 第二頁
            //return siteUrl.replace(/(_\d+)?\.html$/, "") + "_" + (i - 1) + ".html";
            if (mode === 3) return url.replace(/\.html$/, "") + "_" + (i - 1) + ".html";
            //【/ ==> /2/】  第一頁 ==> 第二頁
            if (mode === 4) return url.slice(0, -1) + "/" + i + "/";
            //【 ==> /2】  第一頁 ==> 第二頁
            if (mode === "4") return url + "/" + i;
            //【.html ==> -2.html】  第一頁 ==> 第二頁
            if (mode === 5) return url.replace(/\.html$/, "") + "-" + i + ".html";
            //【-1.html ==> -2.html】  第一頁 ==> 第二頁
            if (mode === "5") return url.replace(/(-\d+)?\.html$/, "") + "-" + i + ".html";
            //【?p=1 ==> ?p=2】  第一頁 ==> 第二頁
            if (mode === 6) return url.replace(/\?p=\d+$/, "") + "?p=" + i;
            //【/1 ==> /2】  第一頁 ==> 第二頁
            //【.html ==> .html/2】  第一頁 ==> 第二頁
            if (mode === 7) return url.replace(/(\.html).*$/, "$1").replace(/\/\d+$/, "") + "/" + i;
            //【 ==> &page=1】  第一頁 ==> 第二頁
            if (mode === 8) return url.replace(/&page=\d+$/, "") + "&page=" + (i - 1);
            //【 ==> &page=2】  第一頁 ==> 第二頁
            if (mode === "8") return url.replace(/&page=\d+$/, "") + "&page=" + i;
            //【.html ==> _2.html】  第一頁 ==> 第二頁
            if (mode === 9) return url.replace(/(_\d+)?\.html$/, "") + "_" + i + ".html";
            //【.html ==> .html/2】  第一頁 ==> 第二頁
            if (mode === 10) return url.replace(/\.html(\/\d+)?$/, "") + ".html/" + i;
            //【/ ==> /2.html】  第一頁 ==> 第二頁
            //【/1.html ==> /2.html】  第一頁 ==> 第二頁
            if (mode === 11) return url.replace(/\/(\d+\.html)?$/, "") + "/" + i + ".html";
            //【/ ==> /2.htm】  第一頁 ==> 第二頁
            //【/1.htm ==> /2.htm】  第一頁 ==> 第二頁
            if (mode === 12) return url.replace(/\/(\d+\.htm)?$/, "") + "/" + i + ".htm";
            //【-1-* ==> -2-*】  第一頁 ==> 第二頁
            if (mode === 13) return url.replace(/-\d+-[^-]+$/, "") + "-" + i;
            //【/1/ ==> /2/】  第一頁 ==> 第二頁
            if (mode === 14) return url.replace(/\/\d+\/$/, "") + "/" + i + "/";
            //【/index.html ==> /index_2.html】  第一頁 ==> 第二頁
            if (mode === 15) return url.replace(/\/(index(_\d+)?\.html)?$/, "") + "/index_" + i + ".html";
            //【 ==> /2#list】  第一頁 ==> 第二頁
            if (mode === 16) return url.replace(/\/(index(_\d+)?\.html)?$/, "") + "/" + i + "#list";
            //【.htm ==> _2.htm】  第一頁 ==> 第二頁
            if (mode === 17) return url.replace(/#$/, "").replace(/(_\d+)?\.htm$/, "") + "_" + i + ".htm";
            //【/ ==> /page/2/】  第一頁 ==> 第二頁
            if (mode === 18) return url.replace(/\/(page\/\d+\/)?$/, "") + "/page/" + i + "/";
            //【-1 ==> -2】  第一頁 ==> 第二頁
            if (mode === 19) return url.replace(/-\d+$/, "") + "-" + i;
            //【 ==> -p-2】  第一頁 ==> 第二頁
            if (mode === 20) return url.replace(/-p-\d+$/, "") + "-p-" + i;
        },
        //重新發送請求
        retryUrl: async (url, res, func, retryCount = 10) => {
            debug(`\n${func}連線錯誤碼:${res.status}\n`, url);
            let retryNum = 1;
            let obj = {
                fn: func,
                url: url,
                status: res.status
            };
            debug(`\n${func}連線錯誤碼:${res.status}重試第${retryNum}次\n`, url);
            let retry = await new Promise(async resolve => {
                for (let check = 1; check <= retryCount; check++) {
                    let checkRes = await fetch(url);
                    if (checkRes.status == 304 || checkRes.status == 200) {
                        let buffer = await checkRes.arrayBuffer();
                        resolve({
                            ok: true,
                            buffer: buffer
                        });
                        break;
                    } else {
                        debug(`\n${func}連線錯誤碼:${checkRes.status}重試第${retryNum += 1}次\n`, url);
                        await delay(3000);
                    }
                    if (check >= retryCount) {
                        resolve({
                            ok: false
                        });
                    }
                }
            });
            if (retry.ok) {
                return retry.buffer;
            } else {
                fetchErrorArray.push(obj);
                return null;
            }
        },
        fetchErrorMsg: () => {
            if (fetchErrorArray.length > 0) {
                debug(`\nfetchErrorArray\n`, fetchErrorArray);
                setTimeout(() => fn.showMsg(`${displayLanguage.str_97}${fetchErrorArray.length}${displayLanguage.str_98}`, 10000), 1500);
            }
        },
        //並行請求取得圖片網址,返回圖片網址。
        getImg: async (img, maxPage = 1, mode = 1, rText = null, time = 50, url = siteUrl, msg = 1, request = 0) => {
            if (fn.ge(".FullPictureLoadImage") && request == 0) return fn.gae(".FullPictureLoadImage:not(.small)");
            isFetching = true;
            if (!getImgFn.includes("getImg()")) getImgFn += " > fn.getImg()";
            if (msg == 1) fn.showMsg(displayLanguage.str_01, 0);
            let imgsArray = [];
            let fetchNum = 0;
            const html = _url => fetch(_url).then(async res => {
                debug(`\nfn.getImg() URL`, _url);
                if (res.status >= 400) {
                    let resData = await fn.retryUrl(_url, res, "fn.getImg()");
                    if (resData !== null) return resData;
                }
                return res.arrayBuffer();
            }).then(buffer => {
                const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                const htmlText = decoder.decode(buffer);
                if (msg == 1) fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${Number(maxPage)}`, 0);
                return htmlText;
            }).catch(error => {
                console.error(`\nfn.getImg() > fetch()出錯:\n${decodeURIComponent(_url)}`, error);
            });
            const resArr = [];
            resArr.push(html(url));
            if (Number(maxPage, 10) > 1) {
                for (let i = 2; i <= Number(maxPage); i++) {
                    resArr.push(html(fn.getModeUrl(url, mode, i)));
                    await delay(time);
                }
            }
            await Promise.all(resArr).then(htmls => {
                isFetching = false;
                if (msg == 1) fn.hideMsg();
                for (let i = 0; i < htmls.length; i++) {
                    let dom = fn.doc(htmls[i]);
                    let imgs = fn.gae(img, dom, dom);
                    //debug(`\nfn.getImg() DOM${i}`, dom);
                    for (let p = 0; p < imgs.length; p++) {
                        let check = fn.checkImgSrc(imgs[p], rText);
                        check.ok ? imgsArray.push(decodeURIComponent(check.src)) : debug(`\nfn.getImg() imgs[${p}]錯誤`, imgs[p]);
                    }
                }
            });
            fn.fetchErrorMsg();
            return imgsArray;
        },
        //單線程請求取得圖片網址,完成一個請求會把圖片元素先插入到當前文檔,類翻頁模式,返回圖片網址。
        getImgO: async (img, maxPage = 1, mode = 1, rText = null, time = 200, replaceElement = null, url = siteUrl, msg = 1, request = 0) => {
            if (fn.ge(".FullPictureLoadImage") && request == 0) return fn.gae(".FullPictureLoadImage:not(.small)");
            isFetching = true;
            if (!getImgFn.includes("getImgO()")) getImgFn += " > fn.getImgO()";
            if (msg == 1) fn.showMsg(displayLanguage.str_01, 0);
            let imgsArray = [];
            let fetchNum = 0;
            const html = async (_url, id = 1) => {
                await delay(time);
                return fetch(_url).then(async res => {
                    debug(`\nfn.getImgO() URL`, _url);
                    if (res.status >= 400) {
                        let resData = await fn.retryUrl(_url, res, "fn.getImgO()");
                        if (resData !== null) return resData;
                    }
                    return res.arrayBuffer();
                }).then(buffer => {
                    const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                    const htmlText = decoder.decode(buffer);
                    let dom = fn.doc(htmlText);
                    fn.gae(img, dom, dom).forEach(ele => {
                        let check = fn.checkImgSrc(ele);
                        if (ele.tagName == "IMG" && check.ok) ele.src = check.src;
                        if (id == 1) {
                            let targetEle = fn.gae(img).at(-1);
                            insertAfter(targetEle, ele.cloneNode(true));
                        }
                    });
                    if (isString(replaceElement)) {
                        fn.gae(".invisible", dom).forEach(ele => ele.classList.remove("invisible"));
                        let ce = fn.gae(replaceElement);
                        let re = fn.gae(replaceElement, dom, dom);
                        if (ce.length === re.length) {
                            ce.forEach((e, i) => (e.outerHTML = re[i].outerHTML));
                        }
                    }
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${Number(maxPage)}`, 0);
                    return htmlText;
                }).catch(error => {
                    console.error(`\nfn.getImgO() > fetch()出錯:\n${decodeURIComponent(_url)}`, error);
                });
            };
            const resArr = [];
            resArr.push(await html(url, 0));
            if (Number(maxPage) > 1) {
                for (let i = 2; i <= Number(maxPage); i++) {
                    resArr.push(await html(fn.getModeUrl(url, mode, i)));
                }
            }
            await Promise.all(resArr).then(htmls => {
                isFetching = false;
                fn.hideMsg();
                for (let i = 0; i < htmls.length; i++) {
                    let dom = fn.doc(htmls[i]);
                    let imgs = fn.gae(img, dom, dom);
                    //debug(`\nfn.getImgO() DOM${i}`, dom);
                    for (let p = 0; p < imgs.length; p++) {
                        let check = fn.checkImgSrc(imgs[p], rText);
                        check.ok ? imgsArray.push(decodeURIComponent(check.src)) : debug(`\nfn.getImgO() imgs[${p}]錯誤`, imgs[p]);
                    }
                }
            });
            fn.fetchErrorMsg();
            return imgsArray;
        },
        //使用Iframe框架加載網頁,完成一個加載會把圖片元素先插入到當前文檔,類翻頁模式,返回圖片網址。
        getImgIframe: async (img, maxPage = 1, mode = 1, rEle = null, time = 500, showMsg = 1) => {
            if (fn.ge(".FullPictureLoadImage")) return fn.gae(".FullPictureLoadImage:not(.small)");
            isFetching = true;
            if (!getImgFn.includes("getImgIframe()")) getImgFn += " > fn.getImgIframe()";
            if (showMsg == 1) fn.showMsg(displayLanguage.str_01, 0);
            let imgsArray = [];
            let fetchNum = 1;
            await fn.waitEle(img);
            fn.gae(img).forEach(ele => imgsArray.push(ele));
            const html = async (url, index = 0) => {
                let targetEle = fn.gae(img).at(-1);
                let load = document.createElement("p");
                load.className = "FullPictureLoadLoading";
                load.innerText = "Loading...";
                insertAfter(targetEle, load);
                await delay(time);
                let dom = null;
                for (let i = 1; i < 20; i++) {
                    dom = await fn.iframeSrcDoc(url, img);
                    if (dom !== null) {
                        break;
                    } else {
                        fn.remove("#FullPictureLoadIframe");
                    }
                }
                if (dom) {
                    debug("iframeDoc" + index, dom);
                    fn.gae(img, dom, dom).forEach(ele => {
                        imgsArray.push(ele);
                        insertAfter(targetEle, ele.cloneNode(true));
                    });
                    if (rEle) {
                        let ce = fn.gae(rEle);
                        let re = fn.gae(rEle, dom, dom);
                        if (ce.length === re.length) {
                            ce.forEach((e, i) => (e.outerHTML = re[i].outerHTML));
                        }
                    }
                    load.remove();
                    if (showMsg == 1) fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${Number(maxPage)}`, 0);
                } else {
                    fetchNum += 1;
                    load.remove();
                    let obj = {
                        fn: "fn.getImgIframe()",
                        url: url
                    };
                    fetchErrorArray.push(obj);
                    fn.showMsg(displayLanguage.str_03, 3000);
                    return;
                }
            }
            if (Number(maxPage) > 1) {
                for (let i = 2; i <= Number(maxPage); i++) {
                    await html(fn.getModeUrl(siteUrl, mode, i), i);
                }
            }
            debug("\nfn.getImgiframe() 聚集的所有IMG", imgsArray);
            isFetching = false;
            fn.hideMsg();
            fn.fetchErrorMsg();
            return imgsArray;
        },
        //從指定的所有連結取得圖片網址,有並行請求、單線程、翻頁模式,返回圖片網址。
        getImgA: async (elementSelector, link, mode = 0, rText = null, showMsg = 1, request = 0) => {
            if (fn.ge(".FullPictureLoadImage") && request == 0) return fn.gae(".FullPictureLoadImage:not(.small)");
            isFetching = true;
            if (!getImgFn.includes("getImgA()")) getImgFn += " > fn.getImgA()";
            if (showMsg == 1) fn.showMsg(displayLanguage.str_01, 0);
            let links, linkEles, linksNum;
            if (isFn(link)) {
                links = await link();
                linksNum = links.length;
            } else if (isArray(link)) {
                links = link;
                linksNum = links.length;
            } else if (isString(link)) {
                linkEles = fn.gae(link);
                links = [...new Set(linkEles.map(a => a.href))];
                linksNum = links.length + 1;
            } else {
                console.error("\nfn.getImgA() link參數錯誤", link);
                return;
            }
            debug("\nfn.getImgA() links", links);
            let imgsArray = [];
            let fetchNum = 0;
            const html = url => fetch(url).then(async res => {
                debug(`\nfn.getImgA() URL`, url);
                if (res.status >= 400) {
                    let resData = await fn.retryUrl(url, res, "fn.getImgA()");
                    if (resData !== null) return resData;
                }
                return res.arrayBuffer();
            }).then(buffer => {
                if (showMsg == 1) fn.showMsg(`${displayLanguage.str_02}${fetchNum+=1}/${linksNum}`, 0);
                const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                const htmlText = decoder.decode(buffer);
                return htmlText;
            }).catch(error => {
                console.error(`\nfn.getImgA fetch()出錯:\n${decodeURIComponent(url)}`, error);
            });
            const resArr = [];
            if (isString(link)) resArr.push(html(siteUrl));
            for (let i = 0; i < links.length; i++) {
                if (mode == 0) {
                    resArr.push(html(links[i]));
                } else if (mode >= 100) {
                    await delay(mode);
                    resArr.push(html(links[i]));
                } else if (mode == 1) {
                    let res = await html(links[i]);
                    resArr.push(res);
                    if (isString(link)) {
                        let dom = fn.doc(res);
                        debug(`\nfn.getImgA()單線程模式 DOM\n${links[i].href}`, dom);
                        let imgs = fn.gae(elementSelector, dom, dom);
                        let imgHtml = "";
                        for (let p = 0; p < imgs.length; p++) {
                            let imgSrc;
                            let check = fn.checkImgSrc(imgs[p], rText);
                            if (check.ok) {
                                imgSrc = check.src;
                                //let blob = await GM_XHR_Download(imgSrc);
                                //let objectURL = await URL.createObjectURL(blob.blob);
                                //imgSrc = objectURL;
                                debug("\nfn.getImgA() 單線程模式imgSrc", imgSrc);
                            } else {
                                console.error("\nfn.getImgA() 單線程模式出錯", imgs[p]);
                                continue;
                            }
                            imgHtml += `<img src="${imgSrc}" style="width: auto; height: auto; max-width: 100%; max-height: unset; display:block; float: unset; opacity: 1; border: none; border-radius: unset; padding: 0; margin: 0 auto; transition: unset; transform: unset;">`;
                        }
                        linkEles[i].outerHTML = imgHtml;
                    }
                } else if (mode == 2) {
                    let res = await html(links[i]);
                    await delay(200);
                    resArr.push(res);
                    if (i !== 0) {
                        let dom = fn.doc(res);
                        let tE = fn.gae(elementSelector).at(-1);
                        let eles = fn.gae(elementSelector, dom, dom);
                        eles.forEach(e => insertAfter(tE, e));
                    }
                }
            }
            await Promise.all(resArr).then(htmls => {
                isFetching = false;
                fn.hideMsg();
                for (let i = 0; i < htmls.length; i++) {
                    let dom = fn.doc(htmls[i]);
                    //if (mode != 1) debug(`\nfn.getImgA() DOM${i}`, dom);
                    let imgs = fn.gae(elementSelector, dom, dom);
                    for (let p = 0; p < imgs.length; p++) {
                        let check = fn.checkImgSrc(imgs[p], rText);
                        check.ok ? imgsArray.push(check.src) : console.error("\nfn.getImgA() PromiseAll出錯", imgs[p]);
                    }
                }
            });
            fn.fetchErrorMsg();
            return imgsArray;
        },
        //跨域從指定的所有連結取得圖片網址,並行請求有請求間隔參數,返回圖片網址。
        getImgCorsA: (imgSelector, aSelector, time = 100) => {
            isFetching = true;
            fn.showMsg(displayLanguage.str_01, 0);
            let xhrNum = 0;
            let links;
            isString(aSelector) ? links = fn.gau(aSelector) : links = aSelector;
            let resArr = links.map(async (url, i, arr) => {
                await delay(time * i);
                return fn.xhrDoc(url).then(dom => {
                    fn.showMsg(`${displayLanguage.str_02}${xhrNum+=1}/${arr.length}`, 0);
                    return fn.gae(imgSelector, dom, dom);
                });
            });
            return Promise.all(resArr).then(arr => {
                isFetching = false;
                fn.hideMsg();
                return fn.getImgSrcArr(arr.flat());
            });
        },
        //補全網址
        complementSrc: (src, rText = null) => {
            if (src.startsWith("//")) {
                src = location.protocol + src;
            }
            if (src.startsWith("data:")) {
                src = fn.dataURLtoBlobURL(src);
            }
            if (/^\/[^\/]+/.test(src)) {
                src = location.origin + src;
            }
            if (!/^(https?:|blob:|data:)/.test(src) && /^\w+/i.test(src)) {
                src = location.origin + "/" + src;
            }
            if (isArray(rText) && rText.length == 2) {
                src = src.replace(rText[0], rText[1]);
            }
            return src;
        },
        //確認元素和圖片網址,嘗試取得網址和補全網址。
        checkImgSrc: (ele, rText = null) => {
            let imgSrc;
            let check = fn.checkDataset(ele);
            if (isEle(ele) && ["IMG", "DIV", "A", "SPAN", "LI", "FIGURE", "ARTICLE", "P", "VIDEO"].some(n => n === ele.tagName) && check.ok) {
                imgSrc = fn.complementSrc(check.src, rText);
            } else if (isEle(ele) && ["IMG", "AMP-IMG"].some(n => n === ele.tagName)) {
                if (ele.tagName == "IMG") {
                    imgSrc = ele.src;
                }
                if (ele.tagName == "AMP-IMG") {
                    imgSrc = ele.getAttribute("src");
                }
                imgSrc = fn.complementSrc(imgSrc, rText);
            } else if (["A", "LINK"].some(n => n === ele.tagName)) {
                imgSrc = ele.href;
                if (isArray(rText) && rText.length == 2) {
                    imgSrc = imgSrc.replace(rText[0], rText[1]);
                }
            } else if (isString(ele) && /^(https?:|blob:|data:|\/|\w+)/i.test(ele)) {
                imgSrc = ele;
                imgSrc = fn.complementSrc(imgSrc, rText);
            }
            if (isURL(imgSrc)) {
                if (imgSrc === location.href) {
                    return {
                        ok: false
                    }
                }
                return {
                    ok: true,
                    src: imgSrc
                }
            } else {
                return {
                    ok: false
                }
            }
        },
        //確認元素有沒有把圖片原始網址放在src以外的屬性
        checkDataset: ele => {
            if (!isEle(ele)) {
                return {
                    ok: false
                }
            }
            if (["IMG", "DIV", "A", "SPAN", "LI", "FIGURE", "P", "ARTICLE", "VIDEO"].some(n => n === ele.tagName)) {
                const datasetArr = [
                    "data-loadsrc",
                    "data-orig-file",
                    "data-src",
                    "data-original",
                    "data-original-url",
                    "data-url",
                    "data-echo",
                    "data-ecp",
                    "data-lazyload-src",
                    "data-lazy-src",
                    "data-lazy",
                    "data-lazyload",
                    "data-lbwps-srcsmall",
                    "data-cfsrc",
                    "data-pin-media",
                    "data-img-url",
                    "data-mfp-src",
                    "data-wpfc-original-src",
                    "data-high-res-src",
                    "data-full-path",
                    "data-thumb",
                    "data-bgset",
                    "data-src_big",
                    "data-bigsrc",
                    "z-image-loader-url",
                    "ng-src",
                    "bigimg",
                    "lg-data-src",
                    "org_img_url",
                    "lazysrc",
                    "file",
                    "zoomfile",
                    "original",
                    "mydatasrc",
                    "ess-data",
                    "poster"
                ];
                for (let p of datasetArr) {
                    let imgSrc = ele.getAttribute(p)?.trim();
                    if (!!imgSrc) {
                        return {
                            ok: true,
                            src: imgSrc
                        }
                    }
                }
                let backgroundImage = getComputedStyle(ele).getPropertyValue("background-image");
                if (backgroundImage != "none" && backgroundImage?.startsWith("url")) {
                    let imgSrc = backgroundImage.slice(5, -2).trim();
                    if (!!imgSrc) {
                        return {
                            ok: true,
                            src: imgSrc
                        }
                    }
                }
            }
            return {
                ok: false
            }
        },
        //確認加了CDN的圖片網址是否有效,無效則刪除CDN返回原始來源的圖片網址
        checkImageCDN: srcArr => {
            fn.showMsg("fn.xhrHEA(check)...", 0);
            let xhrNum = 0;
            return srcArr.map(async (src, i, arr) => {
                await delay(25 * i);
                let res = await fn.xhrHEAD(src);
                fn.showMsg(`fn.xhrHEAD(${xhrNum+=1}/${arr.length})`, 0);
                let status = res.status;
                if (src.includes("wsrv.nl")) {
                    return status > 399 ? src.replace("https://wsrv.nl/?url=", "") : src; //wsrv.nl_CDN
                } else {
                    return status > 399 ? src.replace(/i\d\.wp\.com\/|\?.+$/g, "") : src; //WordPressCDN
                }
            });
        },
        //移除CDN返回原始來源的圖片網址
        removeImageCDN: srcArr => {
            return srcArr.map(async (src, i, arr) => {
                if (src.includes("wsrv.nl")) {
                    return src.replace("https://wsrv.nl/?url=", ""); //wsrv.nl_CDN
                } else {
                    return src.replace(/i\d\.wp\.com\/|\?.+$/g, ""); //WordPressCDN
                }
            });
        },
        //從用AList架設的雲端硬碟,提取圖片和影片網址
        getAList: () => {
            let paths = [...document.querySelectorAll("a.list-item")].map(a => decodeURIComponent(a.getAttribute("href"))).map(href => /\.jpe?g$|\.png$|\.gif$|\.mp4$|\.mov$|\.ts$/i.test(href) ? href : null).filter(item => item);
            fn.showMsg(displayLanguage.str_05, 0);
            let fetchNum = 0;
            let password;
            if ("browser-password" in localStorage) {
                password = localStorage.getItem("browser-password");
            } else {
                password = "";
            }
            let resArr = paths.map((path, i, arr) => {
                const body = {
                    path,
                    password
                };
                return fetch("/api/fs/get", {
                    "headers": {
                        "accept": "application/json, text/plain, */*",
                        "content-type": "application/json;charset=UTF-8"
                    },
                    "body": JSON.stringify(body),
                    "method": "POST"
                }).then(res => res.json()).then(json => {
                    fn.showMsg(`${displayLanguage.str_06}${fetchNum+=1}/${arr.length}`, 0);
                    return json.code == 200 ? {
                        name: json.data.name,
                        url: decodeURIComponent(json.data.raw_url)
                    } : null;
                });
            });
            return Promise.all(resArr).then(arr => arr.map(obj => {
                if (/\.mp4$|\.mov$|\.ts$/i.test(obj.name)) {
                    videoSrcArray.push(obj.url);
                    return null;
                } else {
                    return obj.url;
                }
            }).filter(item => item));
        },
        //指定元素選擇器或元素陣列,返回提取出的圖片網址陣列。
        getImgSrcArr: (selector, dom = document) => {
            let imgs;
            isString(selector) ? imgs = fn.gae(selector, dom, dom) : imgs = selector;
            let srcs = imgs.map(ele => {
                let check = fn.checkImgSrc(ele);
                return check.ok ? check.src : null;
            }).filter(item => item);
            return [...new Set(srcs)];
        },
        //指定圖片元素選擇器或圖片元素陣列,返回提取出的圖片網址陣列。
        getImgSrcset: (selector, dom = document) => {
            let imgs;
            isString(selector) ? imgs = fn.gae(selector, dom, dom) : imgs = selector;
            let srcs = imgs.map(ele => {
                let srcset = ele.getAttribute("srcset");
                if (srcset && /[xw],/.test(srcset)) {
                    let splitArr = srcset.split(",").map(src => src.trim());
                    splitArr = splitArr.sort((a, b) => a.match(/\s([\d\.]+)(w|x)$/)[1] - b.match(/\s([\d\.]+)(w|x)$/)[1]);
                    let [src] = splitArr.at(-1).trim().split(" ");
                    if (/^https:\/\/i\d\.wp\.com/.test(src)) {
                        src = src.replace(/\?.+$/, "?ssl=1");
                    }
                    //if (decodeURIComponent(src).includes("/none")) console.log(ele);
                    try {
                        return decodeURIComponent(src);
                    } catch {
                        return src;
                    }
                } else {
                    if (ele?.parentElement?.id === "pagetual-preload") return null;
                    if (isSimpleMode && ele?.tagName === "A") {
                        let check = fn.checkDataset(ele);
                        if (check.ok) {
                            //if (decodeURIComponent(check.src).includes("/none")) console.log(ele);
                            if (!/\.(jpe?g|png|webp|gif|bmp|tif|svg)/i.test(check.src)) {
                                console.log("\n可能不是含圖片網址的A元素\n", ele);
                                return null;
                            }
                            try {
                                return decodeURIComponent(check.src);
                            } catch {
                                return check.src;
                            }
                        } else {
                            return null;
                        }
                    }
                    let check = fn.checkImgSrc(ele);
                    if (check.ok) {
                        let src = check.src;
                        if (/^https:\/\/i\d\.wp\.com/.test(src)) {
                            src = src.replace(/\?.+$/, "?ssl=1").replace(/-\d+x\d+\./, ".");
                        } else {
                            src = src.replace(/-\d+x\d+\./, ".");
                        }
                        //if (decodeURIComponent(src).includes("/none")) console.log(ele);
                        try {
                            return decodeURIComponent(src);
                        } catch {
                            return src;
                        }
                    } else {
                        return null;
                    }
                }
            }).filter(item => item);
            return srcs;
        },
        //指定元素選擇器或元素陣列,返回元素背景圖片的圖片網址陣列。
        getBackgroundImage: (selector, dom = document) => {
            let eles;
            isString(selector) ? eles = fn.gae(selector, dom, dom) : eles = selector;
            let srcs = eles.map(ele => {
                let backgroundImage = getComputedStyle(ele).getPropertyValue("background-image");
                if (backgroundImage != "none" && backgroundImage?.startsWith("url")) {
                    let imgSrc = backgroundImage.slice(5, -2).trim();
                    return imgSrc;
                } else {
                    return null;
                }
            }).filter(item => item);
            return [...new Set(srcs)];
        },
        //從頭一路翻到尾的自動翻頁函式
        getNP: async (pageEle, nextLinkEle, lastEle = null, replaceElement = null, time = 0, dataset = null, msg = 1, retry = 10) => {
            //翻頁模式聚集所有圖片或是預覽縮圖然後fn.getImgA()
            //用在規則init,fn.getNP(picsEle, nextLinkEle, lastEle, replaceElement, time);
            if (fn.ge(".FullPictureLoadImage")) return;
            if (isString(nextLinkEle) && !fn.ge(nextLinkEle)) return;
            isFetching = true;
            if (!getImgFn.includes("getNP()")) getImgFn += " > fn.getNP()";
            let nextlink = null;
            let page = 1;
            if (msg == 1) fn.showMsg(displayLanguage.str_14, 0);
            const getNextLink = async (url = "", dom = document) => {
                if (isFn(nextLinkEle)) {
                    nextlink = await nextLinkEle(dom);
                } else if (isString(nextLinkEle)) {
                    let ele = fn.ge(nextLinkEle, dom, dom);
                    if (!!ele) {
                        if (!!ele?.dataset?.url) {
                            if (!/^http/.test(ele.dataset.url)) return null;
                            nextlink = ele.dataset.url;
                        } else if (ele.tagName === "A") {
                            nextlink = ele.href;
                            let nh = ele.hostname;
                            let lh = fn.lh;
                            if (nh != lh) nextlink = nextlink.replace(nh, lh);
                        } else {
                            try {
                                ele.getAttribute("href") ? nextlink = ele.getAttribute("href") : nextlink = ele.getAttribute("_href");
                            } catch {
                                nextlink = null;
                            }
                        }
                    } else {
                        nextlink = null;
                    }
                } else {
                    nextlink = null;
                }
                if (isString(url) && isString(nextlink) && (url === nextlink)) {
                    if (msg == 1) fn.showMsg(displayLanguage.str_15);
                    nextlink = null;
                }
                return nextlink;
            };
            const getNextPageEles = async url => {
                if (msg == 1) fn.showMsg(`${displayLanguage.str_14} (Page${page += 1})`, 0);
                await fetch(url).then(async res => {
                    if (res.status >= 400) {
                        let resData = await fn.retryUrl(url, res, "fn.getNP()");
                        if (resData !== null) return resData;
                    }
                    return res.arrayBuffer();
                }).then(buffer => {
                    const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                    const htmlText = decoder.decode(buffer);
                    return htmlText;
                }).then(async htmlText => {
                    let dom = fn.doc(htmlText);
                    let lastPage = null;
                    if (isString(lastEle)) {
                        lastPage = fn.ge(lastEle, dom, dom);
                    } else if (isFn(lastEle)) {
                        try {
                            lastPage = await lastEle(dom);
                        } catch (error) {
                            debug("fn.getNP() lastEle() 函式錯誤", error);
                            lastPage = null;
                        }
                    }
                    if (lastPage) {
                        isFetching = false;
                        if (msg == 1) fn.showMsg(displayLanguage.str_15);
                        return;
                    }
                    if (!fn.ge(pageEle, dom, dom)) {
                        for (let i = 1; i <= retry; i++) {
                            dom = await fn.iframeSrcDoc(url, pageEle);
                            if (dom != null) {
                                break;
                            } else {
                                fn.remove("#FullPictureLoadIframe");
                            }
                        }
                    }
                    if (!dom) dom = fn.doc(htmlText);
                    if (isString(dataset)) {
                        fn.gae(dataset, dom, dom).forEach(e => {
                            let check = fn.checkImgSrc(e);
                            if (check.ok) {
                                if (e.tagName == "IMG") {
                                    e.src = check.src;
                                } else if (["A", "DIV", "SPAN", "LI", "FIGURE"].some(n => n === e.tagName)) {
                                    e.style.backgroundImage = `url(${check.src})`;
                                }
                            }
                        });
                    }
                    //debug(`\nfn.getNP() > getNextPageEles() DOM\n${decodeURIComponent(url)}`, dom);
                    let eles = fn.gae(pageEle, dom, dom);
                    fragment.append(...eles);
                    let targetEle = fn.gae(pageEle).at(-1);
                    insertAfter(targetEle, fragment);
                    if (replaceElement) {
                        let currentPageEles = fn.gae(replaceElement);
                        let nextPageEles = fn.gae(replaceElement, dom, dom);
                        if (currentPageEles.length === nextPageEles.length) {
                            currentPageEles.forEach((e, i) => (e.outerHTML = nextPageEles[i].outerHTML));
                        }
                    }
                    nextlink = await getNextLink(url, dom);
                    if (nextlink) {
                        await delay(time);
                        await getNextPageEles(nextlink);
                    } else {
                        isFetching = false;
                        if (msg == 1) fn.showMsg(displayLanguage.str_15);
                        return;
                    }
                });
            };
            nextlink = await getNextLink();
            if (nextlink) {
                await delay(time);
                await getNextPageEles(nextlink);
            } else {
                isFetching = false;
                if (msg == 1) fn.showMsg(displayLanguage.str_15);
                return;
            }
        },
        //傳入免費圖片空間的連結陣列,提取圖片網址
        getImageHost: async (links = captureLinksArray) => {
            let imgsSrcArr = [];
            if (links.length > 0) {
                if (/\.\w+$/.test(links[0]) && !/\.html$/.test(links[0]) && !/\/fappic\.com\//.test(links[0]) && !/pixhost\.to\/show\//.test(links[0]) && !/^https?:\/\/imagetwist\.com\//.test(links[0])) return links;
                fn.showMsg(displayLanguage.str_01, 0);
                let xhrNum = 0;
                let resArr = links.map(async (url, i, arr) => {
                    await delay(100 * i);
                    if (/imx\.to/.test(url)) {
                        return fn.imxXHR(url).then(dom => {
                            fn.showMsg(`${displayLanguage.str_02}${xhrNum+=1}/${arr.length}`, 0);
                            let img = fn.ge("#container img", dom);
                            return img ? img.src : null;
                        });
                    } else if (/imagebam/.test(url)) {
                        return fn.imageBamXHR(url).then(dom => {
                            fn.showMsg(`${displayLanguage.str_02}${xhrNum+=1}/${arr.length}`, 0);
                            let img = fn.ge("img.main-image", dom);
                            return img ? img.src : null;
                        });
                    } else if (/postimg/.test(url)) {
                        return fn.xhr(url, {
                            responseType: "document"
                        }).then(dom => {
                            fn.showMsg(`${displayLanguage.str_02}${xhrNum+=1}/${arr.length}`, 0);
                            let a = fn.ge("a#download", dom);
                            return a ? a.href : null;
                        });
                    } else {
                        return fn.xhr(url, {
                            responseType: "document"
                        }).then(dom => {
                            fn.showMsg(`${displayLanguage.str_02}${xhrNum+=1}/${arr.length}`, 0);
                            let img = fn.ge("#imgpreview,#image,.pic.img.img-responsive,#imageid,#img.image-content,.card-body img,.image.img-fluid,img.pic[alt][title]", dom);
                            return img ? img.src : null;
                        });
                    }
                })
                await Promise.all(resArr).then(arr => (imgsSrcArr = arr.filter(item => item)));
            }
            return imgsSrcArr;
        },
        //無限滾動切換狀態
        toggleAutoPager: () => {
            let hide = siteData.autoPager?.hide;
            if (autoPagerSwitch === true) {
                autoPagerSwitch = false;
                fn.showMsg(displayLanguage.str_89);
                fn.gae(".autoPagerTitle").forEach(e => e.classList.add("off"));
                if (isString(hide)) {
                    let eles = fn.gae(hide);
                    eles.forEach(e => (e.style.display = ""));
                }
            } else {
                autoPagerSwitch = true;
                fn.showMsg(displayLanguage.str_90);
                fn.gae(".autoPagerTitle").forEach(e => e.classList.remove("off"));
                if (isString(hide)) {
                    let eles = fn.gae(hide);
                    eles.forEach(e => (e.style.display = "none"));
                }
            }
        },
        //無限滾動自動翻頁函式
        infiniteScroll: async () => {
            fn.addLoading();
            let hide = siteData.autoPager?.hide;
            let url;
            try {
                url = await fn.getNextLink(doc);
                if (!url) {
                    autoPagerSwitch = false;
                    fn.showMsg(displayLanguage.str_58, 3000);
                    fn.removeLoading();
                    if (isString(hide)) {
                        let eles = fn.gae(hide);
                        eles.forEach(e => (e.style.display = ""));
                    }
                    return;
                }
            } catch (error) {
                console.error("\n取得下一頁連結出錯\n", error);
                fn.removeLoading();
                if (isString(hide)) {
                    let eles = fn.gae(hide);
                    eles.forEach(e => (e.style.display = ""));
                }
                return;
            }
            let mode = siteData.autoPager?.mode;
            let eleSelector = siteData.autoPager.ele;
            if (isString(mode) && mode == "json") {
                siteJson = await fetch(url, {
                    cache: "no-cache"
                }).then(res => res.json());
            } else if (isNumber(mode) && mode == 1) {
                doc = await fn.iframeDoc(url, (siteData.autoPager?.waitEle || eleSelector), 30000);
            } else {
                if (httpFetchError === false) {
                    doc = await fn.fetchDoc(url, 0);
                }
                if (httpFetchError === true || !doc) {
                    doc = await fn.xhrDoc(url);
                }
            }
            //debug(`\nfn.infiniteScroll()\n${url}\n`, doc);
            debug(`\nfn.infiniteScroll()\n${url}`);
            let stop = siteData.autoPager?.stop;
            if (isFn(stop) || isString(eleSelector)) {
                let stopCheck;
                if (isFn(stop)) {
                    try {
                        stopCheck = await stop(doc);
                    } catch (error) {
                        console.error("\nsiteData.autoPager.stop() 函式錯誤\n", error);
                        stopCheck = false;
                    }
                } else if (isString(eleSelector)) {
                    stopCheck = !fn.ge(eleSelector, doc, doc); //有元素false沒有元素true
                }
                if (stopCheck) {
                    autoPagerSwitch = false;
                    fn.removeLoading();
                    fn.showMsg(displayLanguage.str_58, 3000);
                    if (isString(hide)) {
                        let eles = fn.gae(hide);
                        eles.forEach(e => (e.style.display = ""));
                    }
                    return;
                }
            }
            let history = siteData.autoPager?.history;
            if (history != 0 && mode != "json") {
                try {
                    await fn.addHistory(doc?.title ?? document.title, url);
                } catch (error) {
                    console.error(error);
                }
            }
            let wait = siteData.autoPager?.wait;
            if (isFn(wait)) {
                await wait(doc);
            }
            let script = siteData.autoPager?.script;
            if (isString(script)) {
                let scripts = fn.gae(script, doc);
                for (let i = 0; i < scripts.length; i++) {
                    if (scripts[i].src !== "") {
                        let src = scripts[i].src;
                        await fn.script(src, 1, 1);
                    } else {
                        let code = scripts[i].innerHTML;
                        await fn.script(code, 0, 1);
                    }
                }
            }
            let lazySrc = siteData.autoPager?.lazySrc;
            if (isString(lazySrc)) {
                let eles = fn.gae(lazySrc, doc, doc);
                for (let i = 0; i < eles.length; i++) {
                    let check = fn.checkDataset(eles[i]);
                    if (check.ok) {
                        if (eles[i].tagName === "IMG") {
                            eles[i].src = check.src;
                        } else if (["DIV", "A", "SPAN", "LI", "FIGURE"].some(n => n === eles[i].tagName)) {
                            eles[i].style.backgroundImage = `url("${check.src}")`;
                        }
                    }
                }
            }
            let bF = siteData.autoPager?.bF;
            if (isFn(bF)) await bF(doc);
            let re = siteData.autoPager?.re;
            if (isString(re)) {
                let currentPageEles = fn.gae(re);
                let nextPageEles = fn.gae(re, doc, doc);
                if (currentPageEles.length === nextPageEles.length) {
                    currentPageEles.forEach((e, i) => (e.outerHTML = nextPageEles[i].outerHTML));
                }
            }
            let newEles, tE;
            let pos = siteData.autoPager?.pos;
            if (isFn(eleSelector) && pos || isString(eleSelector)) {
                if (isFn(eleSelector)) {
                    newEles = await eleSelector(doc);
                } else if (isString(eleSelector)) {
                    let nextEle = fn.ge(eleSelector, doc, doc);
                    if (!nextEle) {
                        fn.removeLoading();
                        fn.showMsg(displayLanguage.str_59, 3000);
                        return;
                    }
                    tE = fn.gae(eleSelector).at(-1);
                    newEles = fn.gae(eleSelector, doc, doc);
                }
                if (siteData.autoPager?.showTitle !== 0) {
                    let add = true;
                    let titleText = null;
                    let num = siteData.autoPager?.pageNum;
                    let title = siteData.autoPager?.title;
                    if (isString(num)) {
                        titleText = `Page ${fn.gt(num, 1, doc)}`;
                    } else if (isFn(num)) {
                        titleText = `Page ${await num(doc)}`;
                    } else if (isFn(title)) {
                        try {
                            titleText = await title(mode == "json" ? siteJson : doc, frameWindow);
                            if (isObject(titleText)) {
                                titleText.ok ? titleText = titleText.text : add = false;
                            }
                        } catch (error) {
                            console.error("\nsiteData.autoPager.title() 函式錯誤\n", error);
                        }
                    }
                    if (add) {
                        if (mode == "json") {
                            url = document.URL;
                        }
                        fragment.append(fn.titleUrlEle(url, (titleText || doc?.title || document.title)));
                    }
                }
                fragment.append(...newEles);
                if (isArray(pos) && pos.length == 2 && isString(pos[0]) && isNumber(pos[1])) {
                    const [selector, p] = pos;
                    tE = fn.ge(selector);
                    if (p === 0) { //元素裡面
                        tE.append(fragment);
                    } else if (p === 1) { //元素之前
                        insertBefore(tE, fragment);
                    } else if (p === 2) { //元素之後
                        insertAfter(tE, fragment);
                    }
                } else {
                    insertAfter(tE, fragment);
                }
            } else if (isFn(eleSelector)) {
                await eleSelector(doc);
            }
            fn.removeLoading();
            let aF = siteData.autoPager?.aF;
            if (isFn(aF)) await aF(doc);
            if (siteData.category === "comic autoPager") {
                await fn.lazyload();
                let pagerTitles = fn.gae(".autoPagerTitle");
                if (pagerTitles.length > 3) {
                    let parentE = pagerTitles[0].parentNode;
                    pagerTitles[0].remove();
                    let nodes = [...parentE.childNodes];
                    for (let i = 0; i < nodes.length; i++) {
                        if (nodes[i].className === "autoPagerTitle") {
                            break;
                        }
                        nodes[i].remove();
                    }
                }
            }
            let observer = siteData.autoPager?.observer;
            if (isString(observer)) {
                await delay(siteData.autoPager?.sleep ?? 1000);
                let ele = fn.gae(observer).at(-1);
                fn.nextObserver.observe(ele);
            }
            let preloadNextPage = siteData.autoPager?.preloadNextPage;
            if (!!preloadNextPage) {
                fn.preloadNextPage(doc);
            }
        },
        //無限滾動預讀下一頁
        preloadNextPage: async (dom = document) => {
            let preloadNextPage = siteData.autoPager?.preloadNextPage;
            if (isNumber(preloadNextPage) && preloadNextPage === 1 && siteData.category === "comic autoPager") {
                let nextSelector = siteData.autoPager.next;
                let nextUrl = null;
                if (isString(nextSelector)) {
                    let nextE = fn.ge(nextSelector, dom, dom);
                    if (!!nextE) {
                        nextUrl = nextE.href;
                    }
                } else if (isFn(nextSelector)) {
                    nextUrl = await nextSelector(dom, 0);
                }
                if (!!nextUrl) {
                    let _fetch;
                    let xhr = siteData.autoPager?.preloadNextPageXHR;
                    if (!!xhr && xhr === "cors") {
                        _fetch = fn.xhrDoc(nextUrl);
                    } else {
                        _fetch = fn.fetchDoc(nextUrl);
                    }
                    _fetch.then(async nextDoc => {
                        let srcs = await siteData.getSrcs(nextDoc);
                        let text;
                        let title = siteData.autoPager?.title;
                        if (isFn(title)) {
                            text = await title(nextDoc);
                            if (isObject(text)) {
                                text = nextDoc.title;
                            }
                        } else {
                            text = nextDoc.title;
                        }
                        fn.picPreload(srcs, text, "next");
                    });
                }
            } else if (isFn(preloadNextPage)) {
                preloadNextPage(dom);
            }
        },
        //Iframe框架加載網頁返回框架的document
        iframeDoc: (url, selector = null, time = 5000, callback = null) => {
            return new Promise(async resolve => {
                let tid;
                const iframe = document.createElement("iframe");
                iframe.name = "FullPictureLoad-iframe";
                iframe.id = "FullPictureLoadIframe";
                iframe.sandbox = "allow-same-origin allow-scripts allow-popups allow-forms";
                iframe.style.cssText = "display: block; visibility: visible; float: none; clear: both; width: 100%; height: 0; background: initial; border: 0px; border-radius: 0px; margin: 0px; padding: 0px; z-index: 2147483645;content-visibility: auto;contain-intrinsic-size: auto 300px;";
                tid = setTimeout(() => resolve(null), time);
                const call = async () => {
                    clearTimeout(tid);
                    let dom = iframe.contentDocument || iframe.contentWindow.document;
                    if (!dom) resolve(fn.doc("none"));
                    dom.body.scrollTop = 9999999;
                    dom.documentElement.scrollTop = 9999999;
                    try {
                        await delay(siteData.autoPager?.loadTime || 200);
                    } catch {
                        await delay(200);
                    }
                    if (selector !== null) {
                        await fn.waitEle(selector, 600, dom);
                    }
                    if (isFn(callback)) {
                        await callback(dom, iframe.contentWindow);
                    }
                    let frameCode = siteData.frameCode;
                    if (!!frameCode) {
                        fn.script(frameCode, 0, 1, dom);
                    }
                    frameWindow = iframe.contentWindow;
                    resolve(dom);
                    iframe.remove();
                };
                iframe.onload = () => call();
                iframe.src = url;
                document.body.append(iframe);
            });
        },
        //先用Fetch API取得網頁原始碼,再傳入Iframe框架加載網頁返回框架的document
        iframeSrcDoc: (url, selector = null, time = 5000, callback = null) => {
            return new Promise(async resolve => {
                let tid;
                let resText = await fetch(url).then(async res => {
                    debug(`\nfn.iframeSrcDoc() URL`, url);
                    if (res.status >= 400) {
                        let resData = await fn.retryUrl(url, res, "fn.iframeSrcDoc()");
                        if (resData !== null) return resData;
                    }
                    return res.arrayBuffer()
                }).then(buffer => {
                    const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                    const htmlText = decoder.decode(buffer);
                    return htmlText;
                });
                const iframe = document.createElement("iframe");
                iframe.name = "FullPictureLoad-iframe";
                iframe.id = "FullPictureLoadIframe";
                iframe.sandbox = "allow-same-origin allow-scripts allow-popups allow-forms";
                //iframe.style.display = "none";
                iframe.style.cssText = "display: block; visibility: visible; float: none; clear: both; width: 100%; height: 0; background: initial; border: 0px; border-radius: 0px; margin: 0px; padding: 0px; z-index: 2147483645;content-visibility: auto;contain-intrinsic-size: auto 300px;";
                tid = setTimeout(() => resolve(null), time);
                const call = async () => {
                    clearTimeout(tid);
                    let dom = iframe.contentDocument || iframe.contentWindow.document;
                    if (!dom) resolve(fn.doc("none"));
                    dom.body.scrollTop = 9999999;
                    dom.documentElement.scrollTop = 9999999;
                    try {
                        await delay(siteData.autoPager?.loadTime || 200);
                    } catch {
                        await delay(200);
                    }
                    if (selector !== null) {
                        await fn.waitEle(selector, 600, dom);
                    }
                    if (isFn(callback)) {
                        await callback(dom, iframe.contentWindow);
                    }
                    let frameCode = siteData.frameCode;
                    if (!!frameCode) {
                        fn.script(frameCode, 0, 1, dom);
                    }
                    frameWindow = iframe.contentWindow;
                    resolve(dom);
                    iframe.remove();
                };
                iframe.onload = () => call();
                iframe.srcdoc = resText;
                document.body.append(iframe);
            });
        },
        //使用Iframe框架加載網頁,直到框架的window出現指定的環境變數,返回框架的window
        iframeVar: async (url, key, time = 1000) => {
            const iframe = document.createElement("iframe");
            iframe.id = "FullPictureLoadIframe";
            iframe.style.display = "none";
            iframe.sandbox = "allow-same-origin allow-scripts allow-popups allow-forms";
            iframe.src = url;
            document.body.append(iframe);
            await delay(time);
            await new Promise(resolve => {
                let loop = setInterval(() => {
                    let check;
                    if (isString(key)) {
                        check = (key in iframe.contentWindow);
                    } else if (isArray(key)) {
                        check = key.every(k => (k in iframe.contentWindow));
                    }
                    if (check) {
                        clearInterval(loop);
                        resolve();
                    }
                }, 100);
            });
            setTimeout(() => iframe.remove(), 1000);
            return iframe.contentWindow;
        },
        // 讓用Iframe框架加載網頁,能像fetch的寫法
        iframe: async (url, details = {}) => {
            return new Promise(async (resolve, reject) => {
                const iframe = document.createElement("iframe");
                iframe.id = "FullPictureLoadIframe";
                iframe.style.cssText = "display: block; visibility: visible; float: none; clear: both; width: 100%; height: 0; background: initial; border: 0px; border-radius: 0px; margin: 0px; padding: 0px; z-index: 2147483645;content-visibility: auto;contain-intrinsic-size: auto 300px;";
                iframe.sandbox = "allow-same-origin allow-scripts allow-popups allow-forms";
                const call = async () => {
                    const {
                        loadTime,
                        waitEle,
                        waitVar,
                        cb
                    } = details;
                    if (!!loadTime && isNumber(loadTime)) {
                        await delay(loadTime);
                    } else {
                        await delay(1000);
                    }
                    const dom = iframe.contentDocument || iframe.contentWindow.document;
                    if (!!waitEle && (isString(waitEle) || isArray(waitEle))) {
                        const e = await fn.waitEle(waitEle, 600, dom);
                        //console.log("waitEle", e);
                    }
                    if (!!waitVar) {
                        await new Promise(end => {
                            let loop = setInterval(() => {
                                let check;
                                if (isString(waitVar)) {
                                    check = (waitVar in iframe.contentWindow);
                                } else if (isArray(waitVar)) {
                                    check = waitVar.every(k => (k in iframe.contentWindow));
                                }
                                if (check) {
                                    //console.log("waitVar", waitVar);
                                    clearInterval(loop);
                                    end();
                                }
                            }, 100);
                        });
                    }
                    if (!!cb && isFn(cb)) {
                        await cb(dom, iframe.contentWindow);
                    }
                    setTimeout(() => iframe.remove(), 1000);
                    const object = {
                        dom: dom,
                        frame: iframe.contentWindow
                    };
                    //console.log("iframe dom", dom);
                    //console.log("iframe window", iframe.contentWindow);
                    resolve(object);
                };
                iframe.onload = () => call();
                iframe.error = reject;
                iframe.src = url;
                document.body.append(iframe);
            });
        },
        //無限滾動函式用來觀察元素觸發自動翻頁
        nextObserver: new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting && autoPagerSwitch) {
                    observer.unobserve(entry.target);
                    fn.infiniteScroll();
                }
            });
        }),
        //無限滾動取得下一頁連結函式
        getNextLink: async (dom) => {
            let nextSelector = siteData.autoPager.next;
            if (isFn(nextSelector)) {
                let nextCode = await nextSelector(dom);
                if (nextLink === nextCode) return null;
                nextLink = nextCode;
            } else if (isString(nextSelector)) {
                let nextEle = fn.ge(nextSelector, dom, dom);
                try {
                    if (!nextEle || (nextEle && (nextLink === nextEle.href))) return null;
                } catch (error) {
                    console.error("\nfn.getNextLink() ERROR\n", error);
                    return null;
                }
                nextLink = nextEle.href;
                const nh = nextEle.hostname;
                const lh = fn.lh;
                if (nh !== lh) nextLink = nextLink.replace(nh, lh);
            } else {
                return null;
            }
            if (!nextLink) return null;
            return nextLink;
        },
        //無限滾動創建標題函式
        titleUrlEle: (url, title) => {
            let div = document.createElement("div");
            autoPagerSwitch ? div.className = "autoPagerTitle" : div.className = "autoPagerTitle off";
            if (siteData?.autoPager?.mode === "json") {
                div.innerText = title;
            } else {
                let a = document.createElement("a");
                a.href = url;
                a.innerText = title;
                div.append(a);
            }
            div.addEventListener("click", event => fn.toggleAutoPager());
            return div;
        },
        //無限滾動創建載入中圖示函式
        addLoading: () => {
            if (siteData.autoPager?.loading === "msg") {
                fn.showMsg(displayLanguage.str_57, 0);
            } else {
                try {
                    let img = new Image();
                    img.className = "autoPagerLoading";
                    img.src = autoPagerLoading_gif;
                    let tE;
                    let pos = siteData.autoPager?.pos;
                    if (isArray(pos) && pos.length == 2 && isString(pos[0]) && isNumber(pos[1])) {
                        const [selector, p] = pos;
                        tE = fn.ge(selector);
                        if (p === 0) { //元素裡面
                            tE.append(img);
                        } else if (p === 1) { //元素之前
                            insertBefore(tE, img);
                        } else if (p === 2) { //元素之後
                            insertAfter(tE, img);
                        }
                    } else {
                        tE = fn.gae(siteData.autoPager.ele).at(-1);
                        insertAfter(tE, img);
                    }
                } catch {
                    fn.showMsg(displayLanguage.str_57, 0);
                }
            }
        },
        //無限滾動移除載入中圖示函式
        removeLoading: () => {
            if (siteData.autoPager?.loading === "msg") {
                fn.hideMsg();
            } else {
                try {
                    fn.ge(".autoPagerLoading").remove();
                } catch {
                    fn.hideMsg();
                }
            }
        },
        //無限滾動添加瀏覽器歷史紀錄函式
        addHistory: (title, url) => {
            history.pushState(null, title, url);
            document.title = title;
        },
        //修改A元素以新分頁的方式開啟連結
        openInNewTab: selector => fn.gae(selector).forEach(a => a.setAttribute("target", "_blank")),
        //傳入連結陣列使用iframe框架加載取得元素插入到當前頁面指定的位置或返回元素
        getEleF: async (links, elements, targetEle = null) => {
            if (fn.ge(".FullPictureLoadImage")) return;
            isFetching = true;
            if (!getImgFn.includes("getEleF()")) getImgFn += " > fn.getEleF()";
            fn.showMsg(displayLanguage.str_16, 0);
            if (isString(links)) {
                links = fn.gau(links);
            }
            let resArr = [];
            let fetchNum = 0;
            for (let url of links) {
                let res = await fn.iframeDoc(url, elements).then(dom => {
                    fn.clearAllTimer();
                    fn.showMsg(`${displayLanguage.str_17}${fetchNum+=1}/${links.length}`, 0);
                    let eles = fn.gae(elements, dom, dom);
                    if (targetEle === null) {
                        return eles;
                    }
                    let ele;
                    fragment.append(...eles);
                    if (isArray(targetEle)) {
                        const [selector, p] = targetEle;
                        ele = fn.ge(selector);
                        if (p == 0) ele.append(fragment);
                        else if (p == 1) insertBefore(ele, fragment);
                        else if (p == 2) insertAfter(ele, fragment);
                    }
                    return eles;
                });
                resArr.push(res);
            }
            isFetching = false;
            fn.hideMsg();
            return Promise.all(resArr).then(arr => arr.flat());
        },
        //傳入連結陣列並行請求取得元素插入到當前頁面指定的位置或返回元素
        getEle: async (links, elements, targetEle = null, removeEles = null, time = 100) => {
            if (fn.ge(".FullPictureLoadImage")) return;
            isFetching = true;
            if (!getImgFn.includes("getEle()")) getImgFn += " > fn.getEle()";
            let resArr = [];
            let xhrNum = 0;
            fn.showMsg(displayLanguage.str_16, 0);
            if (isString(links)) {
                links = fn.gau(links);
            }
            for (let i = 0; i < links.length; i++) {
                let res;
                if (time === 0) {
                    res = await fn.fetchDoc(links[i]).then(dom => {
                        debug(`\nfn.getEle() URL`, decodeURIComponent(links[i]));
                        fn.showMsg(`${displayLanguage.str_17}${xhrNum+=1}/${links.length}`, 0);
                        //debug(`fn.getEle()\n${decodeURIComponent(links[i])}\n`, dom);
                        return fn.gae(elements, dom, dom);
                    });
                } else {
                    res = fn.fetchDoc(links[i]).then(dom => {
                        debug(`\nfn.getEle() URL`, decodeURIComponent(links[i]));
                        fn.showMsg(`${displayLanguage.str_17}${xhrNum+=1}/${links.length}`, 0);
                        //debug(`fn.getEle()\n${decodeURIComponent(links[i])}\n`, dom);
                        return fn.gae(elements, dom, dom);
                    });
                }
                resArr.push(res);
                if (time !== 0 && isNumber(time)) await delay(time);
            }
            return Promise.all(resArr).then(arr => arr.flat()).then(eles => {
                isFetching = false;
                fn.hideMsg();
                if (targetEle === null) {
                    if (removeEles) fn.remove(removeEles);
                    return eles;
                }
                let ele;
                fragment.append(...eles);
                if (isArray(targetEle)) {
                    const [selector, p] = targetEle;
                    ele = fn.ge(selector);
                    if (p == 0) ele.append(fragment);
                    else if (p == 1) insertBefore(ele, fragment);
                    else if (p == 2) insertAfter(ele, fragment);
                } else if (isString(targetEle)) {
                    ele = fn.ge(targetEle);
                    ele.innerHTML = "";
                    ele.append(fragment);
                }
                if (removeEles) fn.remove(removeEles);
                fn.fetchErrorMsg();
            });
        },
        //跨域,傳入連結陣列並行請求取得元素插入到指定的位置
        getCorsEle: async (links, elements, targetEle = null, removeEles = null, time = 100) => {
            if (fn.ge(".FullPictureLoadImage")) return;
            isFetching = true;
            if (!getImgFn.includes("getCorsEle()")) getImgFn += " > fn.getCorsEle()";
            let resArr = [];
            let xhrNum = 0;
            fn.showMsg(displayLanguage.str_16, 0);
            if (isString(links)) {
                links = fn.gau(links);
            }
            for (let i = 0; i < links.length; i++) {
                let res;
                if (time === 0) {
                    res = await fn.xhrDoc(links[i]).then(dom => {
                        debug(`\nfn.getEle() URL`, decodeURIComponent(links[i]));
                        fn.showMsg(`${displayLanguage.str_17}${xhrNum+=1}/${links.length}`, 0);
                        //debug(`fn.getEle()\n${decodeURIComponent(links[i])}\n`, dom);
                        return fn.gae(elements, dom, dom);
                    });
                } else {
                    res = fn.xhrDoc(links[i]).then(dom => {
                        debug(`\nfn.getEle() URL`, decodeURIComponent(links[i]));
                        fn.showMsg(`${displayLanguage.str_17}${xhrNum+=1}/${links.length}`, 0);
                        //debug(`fn.getEle()\n${decodeURIComponent(links[i])}\n`, dom);
                        return fn.gae(elements, dom, dom);
                    });
                }
                resArr.push(res);
                if (time !== 0 && isNumber(time)) await delay(time);
            }
            return Promise.all(resArr).then(arr => arr.flat()).then(eles => {
                isFetching = false;
                fn.hideMsg();
                if (targetEle === null) {
                    if (removeEles) fn.remove(removeEles);
                    return eles;
                }
                let ele;
                fragment.append(...eles);
                if (isArray(targetEle)) {
                    const [selector, p] = targetEle;
                    ele = fn.ge(selector);
                    if (p == 0) ele.append(fragment);
                    else if (p == 1) insertBefore(ele, fragment);
                    else if (p == 2) insertAfter(ele, fragment);
                } else if (isString(targetEle)) {
                    ele = fn.ge(targetEle);
                    ele.innerHTML = "";
                    ele.append(fragment);
                }
                if (removeEles) fn.remove(removeEles);
                fn.fetchErrorMsg();
            });
        },
        //單線程背景讀取圖片IMG元素陣列的圖片網址
        singleThreadLoadImgs: async imgArr => {
            for (let i = 0; i < imgArr.length; i++) {
                if (!isValidPage) return;
                if (!imgArr[i].dataset?.src) continue;
                let loadSrc = imgArr[i].dataset.src;
                let parent = imgArr[i].parentNode;
                let temp = new Image();
                if ("referrerpolicy" in (siteData ?? {})) {
                    temp.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                await new Promise(resolve => {
                    temp.onload = () => {
                        imgArr[i].src = loadSrc;
                        resolve();
                    };
                    temp.onerror = () => {
                        if (loadSrc.includes("https://wsrv.nl/")) {
                            loadSrc = loadSrc.replace("https://wsrv.nl/?url=", ""); //wsrv.nl_CDN
                            imgArr[i].dataset.src = loadSrc;
                            if (!!parent && parent?.nodeName === "A" && !!parent?.getAttribute("data-fancybox")) {
                                parent.href = loadSrc;
                                parent.dataset.thumb = loadSrc;
                            }
                        } else if (loadSrc.includes(".wp.com/") && !document.title.endsWith("4KHD")) {
                            loadSrc = loadSrc.replace(/i\d\.wp\.com\/|\?.+$/g, ""); //WordPressCDN
                            imgArr[i].dataset.src = loadSrc;
                            if (!!parent && parent?.nodeName === "A" && !!parent?.getAttribute("data-fancybox")) {
                                parent.href = loadSrc;
                                parent.dataset.thumb = loadSrc;
                            }
                        }
                        resolve();
                    };
                    temp.src = loadSrc;
                });
            }
        },
        //單線程背景讀取圖片網址陣列的圖片網址
        singleThreadLoadSrcs: async srcArr => {
            for (let src of srcArr) {
                if (!isValidPage) return;
                const temp = new Image();
                if ("referrerpolicy" in (siteData ?? {})) {
                    temp.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                await new Promise(resolve => {
                    temp.onload = resolve;
                    temp.onerror = resolve;
                    temp.src = src;
                });
            }
        },
        //圖片預讀函式
        picPreload: async (srcArr, title = (customTitle || document.title), page = "current") => {
            const errorNumArr = new Array(srcArr.length).fill(0);
            const loadImg = async (src, index) => {
                await new Promise(resolve => {
                    const temp = new Image();
                    if ("referrerpolicy" in siteData) {
                        temp.setAttribute("referrerpolicy", siteData.referrerpolicy);
                    }
                    temp.onload = () => {
                        resolve("OK");
                    };
                    temp.onerror = error => {
                        if (!isValidPage) return;
                        const errorNum = errorNumArr[index] + 1;
                        errorNumArr[index] = errorNum;
                        if (src.includes("https://wsrv.nl/")) {
                            src = src.replace("https://wsrv.nl/?url=", ""); //wsrv.nl_CDN
                        } else if (src.includes(".wp.com/") && !document.title.endsWith("4KHD")) {
                            src = src.replace(/i\d\.wp\.com\/|\?.+$/g, ""); //WordPressCDN
                        }
                        if (/e-hentai\.org|exhentai\.org/.test(fn.lh)) {
                            resolve("OK");
                            return;
                        }
                        if (errorNum >= 10) {
                            debug(`\n圖片全載Lazyloading預讀重新載入出錯的圖片已達到10次上限:\n${src}`);
                            resolve("OK");
                            return;
                        }
                        resolve("OK");
                        setTimeout(() => {
                            if (/www\.yinghuamh\.net/.test(fn.lh)) {
                                const {
                                    Gm,
                                    media
                                } = _unsafeWindow;
                                debug(`\n圖片全載Lazyloading預讀出錯 樱花漫画 重新載入另一個圖片伺服器的圖片網址:\n${src}\nto\n${src.replace(Gm.getMediaHost(media), media)}`);
                                loadImg(src.replace(Gm.getMediaHost(media), media), index);
                            } else {
                                debug(`\n圖片全載Lazyloading預讀重新載入出錯的圖片:\n${src}\n錯誤次數:${errorNum}`);
                                loadImg(src, index);
                            }
                        }, 2000);
                    };
                    temp.src = src;
                });
            };
            page == "next" ? debug(`\n${title}\n圖片全載開始預讀下一頁`, srcArr) : debug(`\n${title}\n圖片全載Lazyloading開始預讀`);
            for (let i = 0; i < srcArr.length; i++) {
                if (!isValidPage) return;
                if (/youtube|\.mp4|\.m3u8$|\.webm$/.test(srcArr[i])) continue;
                let load = await loadImg(srcArr[i], i);
            }
            page == "next" ? debug(`\n${title}\n圖片全載下一頁預讀結束`) : debug(`\n${title}\n圖片全載Lazyloading預讀結束`);
        },
        //观察者 MutationObserver事件,根據圖片燈箱插件檢視圖片時的索引,滾動到頁面相對應的圖片位置
        MutationObserver_aff: () => {
            const openEvent = () => {
                if (fn.ge("span[data-fancybox-current-index]") !== null) {
                    slideIndex = Number(fn.gt("span[data-fancybox-current-index]")) - 1;
                } else if (fn.ge("span[data-fancybox-index]") !== null) {
                    slideIndex = Number(fn.gt("span[data-fancybox-index]")) - 1;
                } else if (fn.ge("badge.b-black.counter") !== null) {
                    slideIndex = Number(fn.gt("badge.b-black.counter").match(/\d+/)[0]) - 1;
                }
                if (isNumber(slideIndex)) {
                    console.log("open - # " + slideIndex + " slide is open!");
                }
            };
            const ContentContainer = document.body;
            const configObserver = {
                childList: true,
                subtree: true,
                attributeFilter: ["class"]
            };
            //当观察到突变时执行的回调函数
            const Callbacks = mutationsList => {
                mutationsList.forEach((item, index) => {
                    //console.log("index: ", index, " - \n", item);
                    if (item.type === "attributes") {
                        //console.log(item);
                        if (item.target.className === "fancybox-slide fancybox-slide--image fancybox-slide--current fancybox-slide--complete" || item.target.className === "fancybox__slide has-image can-zoom_in is-selected" || item.target.className === "swiper-slide swiper-slide-active") {
                            console.log(" # ", item);
                            openEvent();
                            fn.scrollEvent(slideIndex);
                        }
                    } else if (item.type === "childList") {
                        //console.log(item);
                        if (item.removedNodes.length > 1 && /fancybox|swiper/.test(item.removedNodes[1].className)) {
                            console.log(" # ", item);
                            console.log("close - # " + slideIndex + " slide is closed!");
                            //setTimeout(closeEvent, 1000);
                            fn.scrollEvent(slideIndex);
                        }
                    }
                });
            };
            //创建一个链接到回调函数的观察者实例
            const Observer = new MutationObserver(Callbacks);
            ContentContainer && Observer.observe(ContentContainer, configObserver);
        },
        //創建用來添加圖片元素的主容器
        createImgBox: (selector, pos = 0, width = null) => {
            if (fn.ge("#FullPictureLoadMainImgBox") || !isString(selector) && !isEle(selector)) return;
            let div = document.createElement("div");
            div.id = "FullPictureLoadMainImgBox";
            div.style.display = "block";
            div.style.textAlign = "center";
            div.style.margin = "0 auto";
            if (isNumber(width)) {
                div.style.maxWidth = width + "px";
            }
            let targetEle;
            if (isString(selector)) {
                targetEle = fn.ge(selector);
            } else if (isEle(selector)) {
                targetEle = selector;
            }
            if (pos == 0) targetEle.append(div);
            if (pos == 1) insertBefore(targetEle, div);
            if (pos == 2) insertAfter(targetEle, div);
            return div;
        },
        //插入圖片函式
        insertImg: (imgsArray, insertTargetEle, mode = 2) => {
            if (fn.ge(".FullPictureLoadImage") || isFetching || isDownloading) return;
            let srcArr = [];
            for (let i = 0; i < imgsArray.length; i++) {
                let check = fn.checkImgSrc(imgsArray[i]);
                check.ok ? srcArr.push(check.src) : console.error("\nfn.insertImg(imgsArray) 格式錯誤!", imgsArray[i]);
            }
            srcArr = [...new Set(srcArr)];
            let noVideoNum = srcArr.filter(src => !/youtube|\.mp4$|\.webm$/.test(src)).length;
            let buttonFn = siteData.button;
            if (isArray(buttonFn)) {
                let [, customWidth, insertBr] = buttonFn;
                let buttonDiv = document.createElement("div");
                buttonDiv.id = "FullPictureLoadOptionsButtonParentDiv";
                buttonDiv.style.width = "100%";
                //buttonDiv.style.height = "42px";
                buttonDiv.style.display = "inline-block";
                buttonDiv.style.textAlign = "center";
                if (isNumber(insertBr)) {
                    buttonDiv.style.marginTop = insertBr * 20 + "px";
                }
                let width = "24%";
                if (isString(customWidth)) width = customWidth;
                const buttonObj = [{
                    id: "FullPictureLoadOpenFavoritesBtn",
                    className: "FullPictureLoadPageButtonTop",
                    text: displayLanguage.str_128,
                    cfn: event => {
                        event.preventDefault();
                        createFavorShadowElement();
                    }
                }, {
                    id: "FullPictureLoadShadowGalleryBtn",
                    className: "FullPictureLoadPageButtonTop",
                    text: displayLanguage.str_141,
                    cfn: event => {
                        event.preventDefault();
                        createShadowGallery();
                    }
                }, {
                    id: "FullPictureLoadFastDownloadBtn",
                    className: "FullPictureLoadPageButtonTop",
                    text: hasTouchEvent ? displayLanguage.str_107 : displayLanguage.str_107 + ` | [ ${noVideoNum}P ]`,
                    cfn: event => {
                        event.preventDefault();
                        fastDownload = true;
                        DownloadFn();
                    }
                }, {
                    id: "FullPictureLoadNewTabViewBtn",
                    className: "FullPictureLoadPageButtonTop",
                    text: displayLanguage.str_106,
                    cfn: event => {
                        event.preventDefault();
                        newTabView();
                    }
                }, {
                    id: "FullPictureLoadOptionsBtn",
                    className: "FullPictureLoadPageButtonBottom",
                    text: displayLanguage.str_85,
                    cfn: event => {
                        event.preventDefault();
                        createPictureLoadOptionsShadowElement();
                    }
                }, {
                    id: "FullPictureLoadToggleImgModeBtn",
                    className: "FullPictureLoadPageButtonBottom",
                    text: displayLanguage.str_86,
                    cfn: event => {
                        event.preventDefault();
                        toggleImgMode();
                    }
                }, {
                    id: "FullPictureLoadToggleZoomeBtn",
                    className: "FullPictureLoadPageButtonBottom",
                    text: displayLanguage.str_87,
                    title: displayLanguage.str_136,
                    cfn: event => {
                        event.preventDefault();
                        fn.clearAllTimer(2);
                        reduceZoom();
                    },
                    mfn: event => {
                        if (event.button == 2) {
                            event.preventDefault();
                            increaseZoom();
                        }
                    }
                }, {
                    id: "FullPictureLoadCancelZoomBtn",
                    className: "FullPictureLoadPageButtonBottom",
                    text: displayLanguage.str_88,
                    cfn: event => {
                        event.preventDefault();
                        fn.clearAllTimer(2);
                        cancelZoom();
                    }
                }];

                if (hasTouchEvent) {
                    buttonObj[1] = {
                        id: "FullPictureLoadCopyURLBtn",
                        className: "FullPictureLoadPageButtonTop",
                        text: displayLanguage.str_105,
                        cfn: event => {
                            event.preventDefault();
                            copyImgSrcTextB();
                        }
                    };
                }

                const createButton = obj => {
                    let button = document.createElement("button");
                    button.id = obj.id;
                    button.className = obj.className;
                    button.style.width = width;
                    //button.style.height = "24px";
                    button.innerText = obj.text;
                    button.oncontextmenu = () => false;
                    if (!!obj.title) button.title = obj.title;
                    if (!!obj.cfn) button.addEventListener("click", obj.cfn);
                    if (!!obj.mfn) button.addEventListener("mousedown", obj.mfn);
                    buttonDiv.append(button);
                };
                [...buttonObj].forEach(obj => createButton(obj));
                fragment.append(buttonDiv);
            }
            let blackList = fancyboxBlackList();
            if (options.fancybox == 1 && thumbnailSrcArray.length > 0) {
                if (!/www\.24cos\.org|www\.lovecos\.net|luohuaxiu\.com|kemono\.su|coomer\.su/.test(fn.lh) || !/^data/.test(thumbnailSrcArray[0])) {
                    thumbnailSrcArray = [...new Set(thumbnailSrcArray)];
                }
            }
            debug("\nfn.insertImg()插入圖片最後確認 thumbnailSrcArray", thumbnailSrcArray);
            debug("\nfn.insertImg()插入圖片最後確認 srcArr", srcArr);
            for (let i = 0; i < srcArr.length; i++) {
                let img = new Image();
                img.alt = `no.${i + 1}`;
                img.dataset.index = i;
                img.className = "FullPictureLoadImage";
                if ("referrerpolicy" in siteData) {
                    img.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                img.dataset.errorNum = 0;
                //if (/vipr\.im/.test(srcArr[i])) img.referrerPolicy = "no-referrer";
                if (options.zoom <= 10 && options.zoom > 0 && (blackList || options.fancybox !== 1)) {
                    img.style.width = `${options.zoom * 10}%`;
                    img.style.height = "auto";
                }
                if (mode == 2 || mode == 3) {
                    img.src = loading_bak;
                    img.dataset.src = srcArr[i];
                } else {
                    img.decoding = "async";
                    img.onload = () => {
                        img.classList.remove("error");
                    };
                    img.onerror = error => {
                        const num = Number(error.target.dataset.errorNum);
                        if (num < 10) {
                            error.target.dataset.errorNum = num + 1;
                        } else {
                            return;
                        }
                        error.target.classList.add("error");
                        setTimeout(() => {
                            debug(`\nfn.insertImg()重新載入出錯的圖片:\n${error.target.src}`);
                            error.target.src = error.target.src;
                        }, 1000);
                    };
                    img.src = srcArr[i];
                }
                if (options.fancybox == 1 && !blackList) {
                    let a = document.createElement("a");
                    a.id = "imgLocationOriginal_" + i;
                    a.dataset.fancybox = "FullPictureLoadImageOriginal";
                    thumbnailSrcArray.length > 0 && thumbnailSrcArray.length == noVideoNum ? a.dataset.thumb = thumbnailSrcArray[i] : a.dataset.thumb = srcArr[i];
                    a.href = srcArr[i];
                    if (options.zoom <= 10 && options.zoom > 0) {
                        a.style.width = `${options.zoom * 10}%`;
                        a.style.height = "auto";
                    }
                    a.append(img);
                    fragment.append(a);
                } else {
                    fragment.append(img);
                }
            }
            if (videoSrcArray.length > 0) {
                debug("\nfn.insertImg()插入圖片最後確認 videoSrcArray", videoSrcArray);
                if (!hasTouchEvent && siteData.downloadVideo === true && FullPictureLoadCustomDownloadVideo == 1) {
                    let dbtn = fn.ge("#FullPictureLoadFastDownloadBtn", fragment);
                    if (dbtn) {
                        dbtn.innerText = dbtn.innerText.replace("P", `P + ${videoSrcArray.length}V`);
                    }
                }
                for (let i = 0; i < videoSrcArray.length; i++) {
                    let video = document.createElement("video");
                    video.className = "FullPictureLoadVideo";
                    video.controls = true;
                    video.loop = false;
                    video.autoplay = false;
                    video.preload = "none";
                    video.style = "height: 500px;width: 100%;max-width:100%";
                    let source = document.createElement("source");
                    source.src = videoSrcArray[i];
                    source.type = "video/mp4";
                    video.append(source);
                    fragment.append(video);
                }
            }
            let end = document.createElement("p");
            end.id = "FullPictureLoadEnd";
            if ("endColor" in siteData) {
                end.style.color = siteData.endColor;
            }
            end.innerText = `${displayLanguage.str_52}:${noVideoNum}P`;
            fragment.append(end);
            if (srcArr.length > 0 || (srcArr.length >= 0 && videoSrcArray.length > 0)) {
                const [, insertMode] = siteData.insertImg;
                if (insertMode == 2 || insertMode == 3) {
                    fn.picPreload(srcArr);
                }
                let targetEle;
                try {
                    if (isArray(insertTargetEle)) {
                        let [selector, pos, removeSelector] = insertTargetEle;
                        targetEle = fn.ge(selector);
                        if (pos == 0) {
                            targetEle.append(fragment);
                            //targetEle.style.textAlign = "center";
                            targetEle.style.display = "block";
                        } else if (pos == 1) {
                            insertBefore(targetEle, fragment);
                            //targetEle.parentNode.style.textAlign = "center";
                            targetEle.parentNode.style.display = "block";
                            targetEle = targetEle.parentNode;
                        } else if (pos == 2) {
                            insertAfter(targetEle, fragment);
                            //targetEle.parentNode.style.textAlign = "center";
                            targetEle.parentNode.style.display = "block";
                            targetEle = targetEle.parentNode;
                        }
                        if (isString(removeSelector)) fn.remove(removeSelector);
                        if (siteData.msg != 0 && siteData.category != "comic") fn.showMsg(displayLanguage.str_18);
                    } else if (isString(insertTargetEle)) {
                        targetEle = fn.ge(insertTargetEle);
                        targetEle.innerHTML = "";
                        targetEle.append(fragment);
                        //targetEle.style.textAlign = "center";
                        targetEle.style.display = "block";
                        if (siteData.msg != 0 && siteData.category != "comic") fn.showMsg(displayLanguage.str_18);
                    }
                    let insertImgAF = siteData.insertImgAF;
                    if (isFn(insertImgAF)) insertImgAF(targetEle);
                    fn.ge("#insertImgMenu")?.remove();
                } catch (error) {
                    fn.showMsg(displayLanguage.str_19, 3000);
                    console.error("\nfn.insertImg() ele參數錯誤,或用來定位插入的元素不存在。", error);
                    return;
                }
                let imgs = fn.gae("img.FullPictureLoadImage:not(.small)");
                if (mode == 2 || mode == 3) {
                    setTimeout(() => {
                        imgs.forEach(img => fn.imagesObserver.observe(img));
                    }, 1000);
                }
                let oddNumberImgs = imgs.filter((img, index) => index % 2 == 0);
                let evenNumberImgs = imgs.filter((img, index) => index % 2 != 0);
                fn.singleThreadLoadImgs(oddNumberImgs);
                fn.singleThreadLoadImgs(evenNumberImgs);
                if (TurnOffImageNavigationShortcutKeys != 1) {
                    let imgsNum = 0;
                    document.addEventListener("keydown", event => {
                        if (isOpenOptionsUI || isOpenGallery || fn.ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
                        if (event.code === "ArrowUp" || event.key === "ArrowUp") {
                            if (imgsNum > 0 && viewMode == 0) {
                                imgsNum -= 1;
                                imgs[imgsNum].scrollIntoView();
                            }
                        } else if (event.code === "ArrowDown" || event.key === "ArrowDown") {
                            event.preventDefault();
                            if (imgsNum < imgs.length && viewMode == 0) {
                                imgsNum += 1;
                                try {
                                    imgs[imgsNum].scrollIntoView();
                                } catch {
                                    imgsNum = 0;
                                    imgs[0].scrollIntoView();
                                    fn.showMsg(displayLanguage.str_94);
                                }
                            }
                        } else {
                            imgsNum = 0 - 1;
                        }
                    });
                }
                if (siteData.category === "comic") {
                    let lastImg = imgs.at(-1);
                    fn.comicNextObserver.observe(lastImg);
                }
                fn.gae("#FullPictureLoadGoToFirstImage,#FullPictureLoadGoToLastImage").forEach(e => (e.style.display = "unset"));
                if (options.fancybox == 1 && !("fancybox" in siteData) && ("Fancybox" in _unsafeWindow)) {
                    _unsafeWindow.Fancybox.bind("[data-fancybox='FullPictureLoadImageOriginal']", FancyboxOptions);
                }
                if (!/tupianwu\.com/.test(fn.lh) && !fn.ge(".umRelevant.umBox") && !fn.ge(".videoPlayerWrap") && !fn.ge("#xqbj-main") && !fn.ge(".PcHeader_rightBox")) {
                    fn.MutationObserver_aff();
                }
                if (options.viewMode == 1 || siteData.viewMode == 1) toggleImgMode();
                if (siteData.go == 1 && noGoToFirstImage != 1) goToNo1Img();
            } else {
                fn.showMsg(displayLanguage.str_20);
            }
        },
        immediateInsertImg: async (manual = "no") => {
            if (captureExclude() || ge(".FullPictureLoadImage")) return;
            if ("SPA" in siteData && isFn(siteData.SPA)) {
                let validPage = await siteData.SPA();
                if (!validPage) return;
            }
            if (options.autoInsert == 1 && manual === "no" || options.autoInsert == 0 && manual === "yes" || manual === "yes") {
                let [insertSelector, insertMode, delayTime] = siteData.insertImg;
                await fn.delay(delayTime || 0);
                let selector = siteData.imgs;
                let imgsSrcArray = await getImgs(selector);
                fn.insertImg(imgsSrcArray, insertSelector, insertMode);
            }
        },
        //返回選擇器的首個元素
        ge: (selector, contextNode = null, dom = document) => {
            if (/^\//.test(selector)) {
                return dom.evaluate(selector, (contextNode ?? document), null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
            } else {
                return (contextNode ?? document).querySelector(selector);
            }
        },
        //返回A選擇器的首個A元素的href
        gu: (selector, contextNode = null, dom = document) => fn.ge(selector, contextNode, dom)?.href,
        //返回選擇器的所有元素的陣列
        gae: (selector, contextNode = null, dom = document) => {
            if (/^\//.test(selector)) {
                let nodes = [];
                let results = dom.evaluate(selector, (contextNode ?? document), null, XPathResult.ANY_TYPE, null);
                let node = null;
                while (node = results.iterateNext()) {
                    nodes.push(node);
                }
                return nodes;
            } else {
                return [...(contextNode ?? document).querySelectorAll(selector)];
            }
        },
        //返回A選擇器的所有A元素的href的陣列並且去除重複
        gau: (selector, contextNode = null, dom = document) => [...new Set(fn.gae(selector, contextNode, dom)?.map(a => a?.href))],
        //取得網頁喧染後的元素字串
        gt: (selector, mode = 1, dom = document) => {
            try {
                if (mode == 1) return fn.ge(selector, dom, dom)?.innerText;
                if (mode == 2) return fn.ge(selector, dom, dom)?.previousElementSibling?.innerText;
                if (mode == 3) return fn.ge(selector, dom, dom)?.previousElementSibling?.previousElementSibling?.innerText;
            } catch (error) {
                console.error(`\nfn.gt() ERROR\nselector:${selector}\n`, error);
                return null;
            }
        },
        getText: (selector, dom = document) => {
            let text = "";
            if (isString(selector)) {
                let ele = fn.ge(selector, dom);
                text = ele?.innerText;
                if (!!ele && !!text && text?.length > 0) {
                    return fn.dt({
                        t: text
                    });
                }
            } else if (isArray(selector)) {
                for (let s of selector) {
                    let ele = fn.ge(s, dom);
                    text = ele?.innerText;
                    if (!!ele && !!text && text?.length > 0) {
                        return fn.dt({
                            t: text
                        });
                    }
                }
            }
            return text;
        },
        //根據關鍵字串或正則搜索符合條件的script,返回script字串
        gst: (searchValue, dom = document) => {
            try {
                return [...dom.scripts].find(script => {
                    if (isString(searchValue)) {
                        return script.textContent.includes(searchValue);
                    } else if (isRegExp(searchValue)) {
                        return script.textContent.search(searchValue) > -1;
                    }
                }).textContent;
            } catch {
                return "";
            }
        },
        //刪除指定字串返回字串
        dt: (obj = {}, dom = document) => {
            let str = dom.title;
            if ("s" in obj) {
                let selector = obj.s;
                str = fn.gt(selector, 1, dom);
            } else if ("t" in obj) {
                str = obj.t;
            }
            let dt = obj.d ?? "";
            if (isString(dt) && dt !== "" || isRegExp(dt)) {
                str = str?.replace(dt, "");
            } else if (isArray(dt)) {
                dt.forEach(r => (str = str?.replace(r, "")));
            }
            str = str?.replace(/[\/\s]?[\(\[[(【“]\d+[\w\s\\\/\.\+-/]+[\)\]])】”]|\s?\d+p[\+\s]+\d+v|\s?\d+p\+?\d+v|\s?\d+P|\(\d\)/gi, "")
                .replace(/\s\|/g, "")
                .replace(/\:/g, ":")
                .replace(/\*/g, "*")
                .replace(/\?/g, "?")
                .replace(/\"/g, "“")
                .replace(/\</g, "《")
                .replace(/\>/g, "》")
                .replace(/\|/g, "|")
                .replace(/\//g, "/")
                .replace(/\\/g, "\")
                .replace(/\s{2,3}/g, " ")
                .trim();
            return str;
        },
        //取得元素的屬性值
        attr: (selector, attr, dom = document) => fn.ge(selector, dom, dom).getAttribute(attr),
        //傳入代碼運行代碼
        run: code => new Function("return " + code)(),
        //將字串解析為document物件
        doc: str => new DOMParser().parseFromString(str, "text/html"),
        //將字串解析為XML物件
        xml: str => new DOMParser().parseFromString(str, "text/xml"),
        //根據參數返回修改後的網頁標題
        title: (str, mode = 0, dom = document) => {
            let split = dom.title.replace(/漫画|\s-\s(漫本)|\[\d+p(\d+v)?\]/gi, "").split(str);
            try {
                if (mode == 0) return dom.title.replace(str, "").trim();
                if (mode == 1) return split[0].replace(/,$/g, "").replace(/,/g, " ").trim();
                if (mode == 2) return (split[0] + str + split[1]).replace(/,$/g, "").replace(/,/g, " ").trim();
                if (mode == 3) return (split[1] + str + split[0]).replace(/,$/g, "").replace(/,/g, " ").trim();
            } catch (error) {
                console.error("\nfn.title() ERROR", error);
                return dom.title;
            }
        },
        //創建一個指定長度的陣列
        arr: (num, cb = null) => {
            if (isFn(cb)) {
                return Array.from({
                    length: Number(num)
                }, cb);
            } else {
                return Array.from({
                    length: Number(num)
                });
            }
        },
        //顯示簡短的訊息
        showMsg: (text, time = 1000) => {
            let msgE = fn.ge("#FullPictureLoadMsg");
            if (!msgE) {
                msgE = document.createElement("div");
                msgE.id = "FullPictureLoadMsg";
                document.body.append(msgE);
            }
            msgE.innerText = text;
            if (!!time && isNumber(time)) {
                setTimeout(() => fn.hideMsg(), time);
            }
        },
        //隱藏訊息
        hideMsg: () => {
            const msgE = fn.ge("#FullPictureLoadMsg");
            msgE?.remove();
        },
        //圖片元素觀察者,圖片進入可視範圍時把data-src屬性寫入src
        imagesObserver: new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    observer.unobserve(entry.target);
                    let realSrc = entry.target.dataset.src;
                    let nE = entry.target.nextElementSibling;
                    let fancyboxE = entry.target.parentNode;
                    let fancyboxA = null;
                    let fancyboxNE = null;
                    if (fancyboxE && fancyboxE?.tagName == "A" && fancyboxE.getAttribute("data-fancybox")) {
                        fancyboxA = fancyboxE;
                        fancyboxNE = fancyboxE.nextElementSibling;
                    }
                    if (realSrc) {
                        entry.target.classList.remove("lazyload");
                        entry.target.onload = () => {
                            if (!/^(data|blob)/.test(entry.target.src)) {
                                entry.target.classList.remove("error");
                            }
                        };
                        entry.target.onerror = async (error) => {
                            if (realSrc.includes("wsrv.nl/")) {
                                let newSrc = realSrc.replace("https://wsrv.nl/?url=", ""); //wsrv.nl_CDN
                                entry.target.dataset.src = newSrc;
                                if (!!fancyboxA) {
                                    fancyboxA.href = newSrc;
                                    fancyboxA.dataset.thumb = newSrc;
                                }
                            } else if (realSrc.includes(".wp.com/") && !document.title.endsWith("4KHD")) {
                                let newSrc = realSrc.replace(/i\d\.wp\.com\/|\?.+$/g, ""); //WordPressCDN
                                entry.target.dataset.src = newSrc;
                                if (!!fancyboxA) {
                                    fancyboxA.href = newSrc;
                                    fancyboxA.dataset.thumb = newSrc;
                                }
                            }
                            const errorNum = Number(entry.target.dataset?.errorNum) || 0;
                            if (errorNum < 10) {
                                entry.target.dataset.errorNum = errorNum + 1;
                            } else {
                                return;
                            }
                            if (/www\.yinghuamh\.net/.test(fn.lh)) {
                                const {
                                    Gm,
                                    media
                                } = _unsafeWindow;
                                error.target.dataset.src = error.target.dataset.src.replace(Gm.getMediaHost(media), media);
                            }
                            if (/e-hentai\.org|exhentai\.org/.test(fn.lh) && errorNum < 1) {
                                let url = error.target.dataset.loadfail ?? fn.gae(".gdtm a,.gdtl a")[error.target.dataset.index].href;
                                let newSrc = await fn.fetchDoc(url).then(async dom => {
                                    let loadfail = fn.ge("#loadfail", dom);
                                    let newUrl = url.replace(/\?nl=.+$/, "") + "?nl=" + loadfail.getAttribute("onclick").split("'")[1];
                                    error.target.dataset.loadfail = newUrl;
                                    return await fn.fetchDoc(newUrl).then(newDoc => {
                                        let src = fn.ge("#img", newDoc).src;
                                        if (fancyboxE && fancyboxE.tagName == "A") fancyboxE.href = src;
                                        return src;
                                    });
                                });
                                error.target.dataset.src = newSrc;
                            }
                            if (/civitai\.com/.test(fn.lh)) {
                                if (error.target.dataset.url) {
                                    error.target.dataset.src = error.target.dataset.url;
                                } else {
                                    error.target.dataset.src = error.target.dataset.src.replace("original=true/", "");
                                }
                            }
                            error.target.src = loading_bak;
                            error.target.classList.add("error");
                            setTimeout(() => {
                                if (/www\.yinghuamh\.net/.test(fn.lh)) {
                                    debug(`\nimagesObserver 樱花漫画圖片出錯 重新載入另一個圖片伺服器的圖片網址:\n${realSrc}\nto\n${error.target.dataset.src}`);
                                } else if (/e-hentai\.org|exhentai\.org/.test(fn.lh)) {
                                    debug(`\nimagesObserver E紳士圖片出錯 重新載入新的圖片網址:\n${realSrc}\nto\n${error.target.dataset.src}`);
                                } else {
                                    debug(`\nimagesObserver重新載入出錯圖片:\n${realSrc}\n錯誤次數:${errorNum}`);
                                }
                                error.target.src = error.target.dataset.src;
                            }, 1000);
                        };
                        entry.target.src = realSrc;
                    }
                    if (!!nE && nE.tagName == "IMG" && !!nE?.dataset?.src) nE.src = nE.dataset.src;
                    if (fancyboxNE && fancyboxNE.tagName == "A") {
                        let ele = fancyboxNE.firstElementChild;
                        if (!!ele && ele.tagName == "IMG" && !!ele?.dataset?.src) ele.src = ele.dataset.src;
                    }
                }
            });
        }),
        //看漫畫當最後一張圖進入可視範圍時,按住空白鍵前往下一話
        comicNextObserver: new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    observer.unobserve(entry.target);
                    if (!!nextLink) {
                        const comicSpaceClickNext = () => {
                            let click = 0;
                            const callback = event => {
                                if (event.code === "Space" || event.key === " ") {
                                    click += 1;
                                    if (click >= 5) {
                                        document.removeEventListener("keydown", callback);
                                        fn.showMsg(displayLanguage.str_34);
                                        location.href = nextLink;
                                    }
                                }
                            };
                            document.addEventListener("keydown", callback);
                        };
                        comicSpaceClickNext();
                    }
                }
            });
        }),
        //創建style元素
        css: (css, id = null) => {
            if (isString(id)) {
                if (document.getElementById(id)) return;
            }
            let style = document.createElement("style");
            style.type = "text/css";
            if (isString(id)) style.id = id;
            style.className = "FullPictureLoadStyle";
            style.innerHTML = css;
            document.head.append(style);
        },
        //創建script元素
        //fn.script("code"),返回script
        //fn.script("code",0,1),script插入到document.body
        //fn.script("srcUrl",1,1),script插入到document.body
        script: async (code, src = 0, pos = 0, dom = document) => {
            let script = dom.createElement("script");
            script.className = "FullPictureLoadScript";
            if (src == 0) {
                script.type = "text/javascript";
                script.innerHTML = code;
            }
            if (src == 0 && pos == 0) {
                return script;
            } else if (pos == 1) {
                if (src == 1) {
                    await new Promise(resolve => {
                        script.onload = () => {
                            resolve();
                        };
                        script.src = code;
                        dom.body.append(script);
                    });
                } else {
                    dom.body.append(script);
                }
            }
            if (siteData.category === "comic autoPager") {
                script.remove();
            }
        },
        //延遲
        delay: (time, msg = 1) => {
            if (time > 200 && msg == 1) fn.showMsg(`${displayLanguage.str_21}${time}${displayLanguage.str_22}...`, time);
            return new Promise(resolve => setTimeout(resolve, time));
        },
        //等待函式寫法
        wait: (callback, num = 300) => {
            if (!isFn(callback)) return;
            debug("fn.wait()等待中...", String(callback));
            let loopNum = 0;
            return new Promise(resolve => {
                const loopFn = async () => {
                    let check = await callback(document, _unsafeWindow);
                    if (!!check) {
                        debug("fn.wait()等待結束。");
                        resolve(true);
                        return;
                    }
                    if (loopNum >= num) {
                        debug("fn.wait()達循環上限。");
                        resolve(false);
                        return;
                    }
                    if (!check) {
                        loopNum += 1;
                        await delay(100);
                        return loopFn();
                    }
                };
                loopFn();
            });
        },
        //等待元素
        waitEle: (selector, max = 200, dom = document) => {
            let loopNum = 0;
            if (selector !== "body") {
                debug("fn.waitEle()等待中...", selector);
            }
            return new Promise(resolve => {
                let loop = setInterval(() => {
                    loopNum += 1;
                    let check;
                    let ele;
                    if (isString(selector)) {
                        ele = fn.ge(selector, dom, dom);
                        check = isEle(ele);
                    } else if (isArray(selector)) {
                        check = selector.every(s => isEle(fn.ge(s, dom, dom)));
                        ele = selector.map(s => fn.gae(s, dom, dom));
                        ele = ele.flat();
                    }
                    if (check) {
                        if (selector !== "body") {
                            debug("fn.waitEle()等待結束。");
                        }
                        clearInterval(loop);
                        resolve(ele);
                    }
                    if (loopNum >= max) {
                        clearInterval(loop);
                        debug(`fn.waitEle()達循環上限,沒有出現"${selector}"元素。`);
                        resolve(null);
                    }
                }, 100);
            });
        },
        //等待window環境變數
        waitVar: (key, max = 200) => {
            let loopNum = 0;
            debug("fn.waitVar()等待中...", key);
            return new Promise(resolve => {
                let loop = setInterval(() => {
                    loopNum += 1;
                    let check;
                    if (isString(key)) {
                        check = (key in _unsafeWindow);
                    } else if (isArray(key)) {
                        check = key.every(k => (k in _unsafeWindow));
                    }
                    if (check) {
                        debug("fn.waitVar()等待結束。");
                        clearInterval(loop);
                        resolve(true);
                    }
                    if (loopNum >= max) {
                        clearInterval(loop);
                        debug(`fn.waitVar()達循環上限,沒有出現"${key}"屬性。`);
                        resolve(false);
                    }
                }, 100);
            });
        },
        //攔截創建IMG元素時的src
        HTMLImageElementSrcHook: callback => {
            const originalSrcDescriptor = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, "src");
            Object.defineProperty(HTMLImageElement.prototype, "src", {
                set: function(value) {
                    if (isFn(callback)) {
                        callback(value);
                    }
                    originalSrcDescriptor.set.call(this, value);
                }
            });
        },
        //確認圖片狀態返回圖片寬高
        checkImgStatus: (src, msg = 1) => {
            if (isString(msg)) {
                fn.showMsg(msg, 0);
            } else if (msg === 1) {
                fn.showMsg(displayLanguage.str_56, 0);
            }
            return new Promise(resolve => {
                const temp = new Image();
                temp.onload = () => {
                    if (isString(msg)) fn.hideMsg();
                    resolve({
                        ok: true,
                        src: src,
                        width: temp.width,
                        height: temp.height
                    });
                };
                temp.onerror = () => {
                    if (isString(msg)) fn.hideMsg();
                    resolve({
                        ok: false,
                        src: src
                    });
                };
                temp.src = src;
            });
        },
        //確認目前下載線程
        checkDownloadThread: () => {
            let threading;
            if (options.threading > 32) {
                threading = 32;
            } else if (options.threading < 1) {
                threading = 1;
            } else {
                threading = options.threading;
            }
            return new Promise(resolve => {
                let loop = setInterval(() => {
                    if (currentDownloadThread <= threading) {
                        clearInterval(loop);
                        resolve();
                    }
                }, 50);
            });
        },
        //產生隨機字串
        generateRandomString: (num, mode = 0) => {
            let characters;
            if (mode === 0) {
                characters = "0123456789";
            } else {
                characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            }
            let string = "";
            let charactersLength = characters.length;
            for (let i = 0; i < num; i++) {
                string += characters.charAt(Math.floor(Math.random() * charactersLength));
            }
            return string;
        },
        //取得代碼並創建script注入到當前頁面
        getCode: (url, obj = {}) => {
            const {
                mode,
                cors,
                key
            } = obj;
            if (mode == "dom" && (isString(key) || isRegExp(key))) {
                let xhr;
                if (cors == true) {
                    xhr = fn.xhrDoc(url);
                } else {
                    xhr = fn.fetchDoc(url);
                }
                return xhr.then(dom => {
                    let code = fn.gst(key, dom);
                    _GM_addElement(document.body, "script", {
                        textContent: code
                    });
                });
            } else {
                let xhr;
                if (cors == true) {
                    xhr = fn.xhr(url);
                } else {
                    xhr = fetch(url).then(res => res.text());
                }
                return xhr.then(text => {
                    _GM_addElement(document.body, "script", {
                        textContent: text
                    });
                });
            }
        },
        //用Promise封裝GM_xmlhttpRequest
        xhr: (url, details = {}) => {
            return new Promise((resolve, reject) => {
                _GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    responseType: "text",
                    headers: {
                        "Referer": _unsafeWindow.location.href,
                        "User-Agent": _unsafeWindow.navigator.userAgent
                    },
                    onload: data => {
                        if (data.status > 400) debug(`\nfn.xhr()連線錯誤碼:${data.status}\n`, url);
                        resolve(data.response);
                    },
                    onerror: error => {
                        console.error("fn.xhr()ERROR", error);
                        reject(error)
                    },
                    ...details
                });
            });
        },
        //用Promise封裝GM_xmlhttpRequest
        xhrHEAD: (url, details = {}) => {
            return new Promise(resolve => {
                _GM_xmlhttpRequest({
                    method: "HEAD",
                    url: url,
                    headers: {
                        "Referer": _unsafeWindow.location.href,
                        "User-Agent": _unsafeWindow.navigator.userAgent
                    },
                    timeout: 20000,
                    onload: data => {
                        resolve(data);
                    },
                    onerror: error => {
                        console.log(`fn.xhrHEAD() ERROR\n${url}`, error);
                        resolve({
                            status: 403
                        });
                    },
                    ontimeout: error => {
                        console.log(`fn.xhrHEAD() Timeout\n${url}`, error);
                        resolve({
                            status: 524
                        });
                    },
                    ...details
                });
            });
        },
        //用Promise封裝GM_xmlhttpRequest
        imxXHR: url => {
            return new Promise((resolve, reject) => {
                _GM_xmlhttpRequest({
                    method: "POST",
                    url: url,
                    responseType: "document",
                    headers: {
                        "content-type": "application/x-www-form-urlencoded"
                    },
                    data: "imgContinue=Continue+to+image+...+",
                    onload: data => {
                        resolve(data.response);
                    },
                    onerror: error => {
                        reject(error);
                    }
                });
            });
        },
        //用Promise封裝GM_xmlhttpRequest
        imageBamXHR: url => {
            return new Promise((resolve, reject) => {
                _GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    responseType: "document",
                    headers: {
                        "referrer": url,
                        "referrerPolicy": "strict-origin-when-cross-origin"
                    },
                    onload: data => {
                        resolve(data.response);
                    },
                    onerror: error => {
                        reject(error);
                    }
                });
            });
        },
        //用Promise封裝GM_xmlhttpRequest,返回經過文字編碼的document物件
        xhrDoc: (url, details = {}) => {
            if ("xhrOptions" in siteData) {
                details = siteData.xhrOptions
            }
            return new Promise(resolve => {
                _GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    responseType: "arraybuffer",
                    headers: {
                        "Referer": _unsafeWindow.location.href,
                        "User-Agent": _unsafeWindow.navigator.userAgent
                    },
                    onload: data => {
                        let decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                        let htmlText = decoder.decode(data.response);
                        let dom = fn.doc(htmlText);
                        if (data.status >= 400) {
                            console.error(`\nfn.xhrDoc()連線錯誤碼:${data.status}\n`, url, data, dom);
                            let obj = {
                                fn: "fn.xhrDoc()",
                                url: url,
                                status: data.status
                            };
                            fetchErrorArray.push(obj);
                        }
                        resolve(dom);
                    },
                    onerror: error => {
                        console.error(`\nfn.xhrDoc()出錯:\n${decodeURIComponent(url)}`, error);
                        resolve(null);
                    },
                    ...details
                });
            });
        },
        //用Fetc API,返回經過文字編碼的document物件
        fetchDoc: (url, details = {}, retry = 40) => {
            if ("xhrOptions" in siteData) {
                details = siteData.xhrOptions
            }
            return new Promise(async resolve => {
                fetch(url, {
                    ...details
                }).then(async res => {
                    if (res.status >= 400 && retry > 0) {
                        let resData = await fn.retryUrl(url, res, "fn.fetchDoc()", retry);
                        if (resData !== null) return resData;
                    }
                    return res.arrayBuffer();
                }).then(buffer => {
                    const decoder = new TextDecoder(document.characterSet || document.charset || document.inputEncoding);
                    const htmlText = decoder.decode(buffer);
                    resolve(fn.doc(htmlText));
                }).catch(error => {
                    console.error(`\nfn.fetchDoc()出錯:\n${decodeURIComponent(url)}`, error);
                    httpFetchError = true;
                    resolve(null);
                });
            });
        },
        //IMHentai網站用的取得圖片網址
        getImhentaiSrc: async () => {
            await fn.waitVar("g_th");
            const findServer = cId => {
                if (cId > 0 && cId <= 274825) return "m1.imhentai.xxx";
                if (cId > 274825 && cId <= 403818) return "m2.imhentai.xxx";
                if (cId > 403818 && cId <= 527143) return "m3.imhentai.xxx";
                if (cId > 527143 && cId <= 632481) return "m4.imhentai.xxx";
                if (cId > 632481 && cId <= 816010) return "m5.imhentai.xxx";
                if (cId > 816010 && cId <= 970098) return "m6.imhentai.xxx";
                if (cId > 970098 && cId <= 1121113) return "m7.imhentai.xxx";
                if (cId > 1121113 && cId <= 1259410) return "m8.imhentai.xxx";
                return "m9.imhentai.xxx";
            };
            const galleryId = fn.ge(".gview>#gallery_id,#load_id").value;
            const imageDir = fn.ge("#image_dir,#load_dir").value;
            const num = fn.ge("#pages,#load_pages").value ?? "";
            const cId = Number(fn.ge("#u_id,#load_dir+#gallery_id").value ?? "");
            const randomServer = _unsafeWindow.random_server ?? findServer(cId);
            return fn.arr(num, (v, i) => `//${randomServer}/${imageDir}/${galleryId}/${(i + 1)}.${fn.ex(_unsafeWindow.g_th[i + 1][0])}`);
        },
        //漫漫聚和KuKu动漫取得圖片網址的函式
        getKukudmSrc: async (url = siteUrl, dom = document, msg = 1) => {
            if (url === null) return;
            if (fn.ge("//title[contains(text(),'404')]", dom, dom)) return [];
            if (!getImgFn.includes("getKukudmSrc")) getImgFn += " > fn.getKukudmSrc()";
            let timeId = setTimeout(() => msg === 1 ? location.reload() : null, 20000);
            if (msg == 1) fn.showMsg(displayLanguage.str_05, 0);
            let max;
            fn.ge("//td[input]", dom, dom) ? max = fn.gt("//td[input]", 1, dom).match(/共(\d+)/)[1] : max = fn.gt(".bottom .subNav", 1, dom).match(/\/(\d+)/)[1];
            url = url.replace(fn.ls, "").replace(/1\.htm$/, "");
            let links = fn.arr(max, (v, i) => url + (i + 1) + ".htm");
            let xhrNum = 0;
            let resArr = links.map(url => {
                return fn.xhrDoc(url).then(dom => {
                    if (msg == 1) fn.showMsg(`${displayLanguage.str_06}${xhrNum+=1}/${links.length}`, 0);
                    let script = fn.gst("document.write", dom);
                    let htmlCode = script.replace("document.write(", "").replace(");", "");
                    let htmlText = fn.run(`(${htmlCode}).toString()`);
                    let tempDom = fn.doc(htmlText);
                    let imgs = [...tempDom.images];
                    if (imgs.length > 1) {
                        return {
                            src1: decodeURIComponent(imgs[0].src),
                            src2: decodeURIComponent(imgs[1].src)
                        };
                    } else if (imgs.length > 0) {
                        return decodeURIComponent(imgs[0].src);
                    } else {
                        return null;
                    }
                });
            });
            let allSrc = await Promise.all(resArr).then(arr => {
                clearTimeout(timeId);
                if (msg == 1) fn.hideMsg();
                return arr;
            });
            try {
                const [first] = allSrc;
                if (isString(first)) {
                    return allSrc;
                } else {
                    msg == 1 ? fn.showMsg(displayLanguage.str_56, 0) : null;
                    let status = await fn.xhrHEAD(first.src1).then(res => res.status);
                    return status == 200 ? allSrc.map(e => e.src1) : allSrc.map(e => e.src2);
                }
            } catch {
                return [];
            }
        },
        //移除元素
        remove: async (obj, time = 0) => {
            if (isString(obj)) {
                await delay(time);
                let selector = obj;
                fn.gae(selector).forEach(e => e.remove());
            } else if (isArray(obj)) {
                let selectors = obj;
                await delay(time);
                selectors.forEach(selector => fn.gae(selector).forEach(e => e.remove()));
            }
        },
        //創建A元素
        addUrlHtml: (url, selector, pos = 0, text = "點選進入下一話", css = 0) => {
            let _pos;
            switch (pos) {
                case 0:
                    _pos = "beforebegin"; //在元素之前。
                    break;
                case 1:
                    _pos = "afterend"; //在元素之後。
                    break;
                case 2:
                    _pos = "beforeend"; //在元素裡面,最後一個子元素之後。
                    break;
                case 3:
                    _pos = "afterbegin"; //在元素裡面,第一個子元素之前。
                    break;
            }
            let html = `<div class="addUrl" style="padding: 20px 0; text-align: center;"><a href="${url}"style="font-size: 26px;line-height: 50px;height: 50px;text-align: center;">${text}</a></div>`;
            if (isEle(selector)) {
                selector.insertAdjacentHTML(_pos, html);
            } else if (isString(selector)) {
                fn.ge(selector).insertAdjacentHTML(_pos, html);
            } else {
                return console.error("fn.addUrlHtml() 參數selector錯誤", selector);
            }
            switch (css) {
                case 1:
                    fn.css(".addUrl>a{text-decoration:none;color:rgb(255 255 255);background-color:rgb(137 5 188);border:solid #bbb;border-radius:0.25rem;font-weight:700;padding:.5rem 2rem}");
                    break;
                case 2:
                    fn.css(".addUrl>a{text-decoration:none;color:rgb(50 50 50);background-color:rgb(200 200 200);border-radius:0.25rem;padding:.5rem 2rem}");
                    break;
                case 3:
                    fn.css(".addUrl>a{text-decoration:none;color:#6c757d;background-color:#fff;border:solid #6c757d;border-radius:0.25rem;padding:.5rem 2rem;transition:background-color .2s,color .2s;&:hover{color:#fff;background-color:#6c757d}}");
                    break;
                case 4:
                    fn.css(".addUrl>a{text-decoration:none;color:#003366;background-color:#fff;border:solid #6c757d;border-radius:0.25rem;padding:.5rem 2rem}");
                    break;
                case 5:
                    fn.css(".addUrl>a{text-decoration:none;color:rgb(255 255 255);background-color:rgb(77 147 255);border:solid #bbb;border-radius:0.25rem;font-weight:700;padding:.5rem 2rem}");
                    break;
            }
        },
        dataURLtoBlobURL: dataurl => {
            try {
                if (dataurl.startsWith("data:image/svg+xml")) {
                    try {
                        dataurl = decodeURIComponent(dataurl);
                    } catch {}
                    let svg = dataurl.split(",")[1].replaceAll("&quot;", '"').replaceAll('\\"', '"');;
                    //console.log(svg);
                    return URL.createObjectURL(new Blob([svg], {
                        type: "image/svg+xml"
                    }));
                }
                let arr = dataurl.split(","),
                    mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]),
                    n = bstr.length,
                    u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                return URL.createObjectURL(new Blob([u8arr], {
                    type: mime
                }));
            } catch (error) {
                console.error(dataurl);
                console.error(error);
                return dataurl;
            }
        },
        blobURLtoDataURL: bloburl => fetch(bloburl).then(res => res.blob()).then(blob => fn.blobToDataURL(blob)),
        imgSrcToDataURL: (src, type = "image/jpeg", cros = 0) => {
            return new Promise((resolve, reject) => {
                const img = new Image();
                if (cros == 1) {
                    img.setAttribute("crossOrigin", "");
                }
                img.onload = () => {
                    let canvas = document.createElement("canvas");
                    canvas.height = img.naturalWidth;
                    canvas.width = img.naturalHeight;
                    canvas.getContext("2d").drawImage(img, 0, 0);
                    URL.revokeObjectURL(img.src);
                    let dataURL = canvas.toDataURL(type);
                    resolve(dataURL);
                };
                img.onerror = error => {
                    reject(error);
                }
                img.src = src;
            });
        },
        imgSrcToBlobURL: (src, type = "image/jpeg", cros = 0) => {
            return new Promise((resolve, reject) => {
                const img = new Image();
                if (cros == 1) {
                    img.setAttribute("crossOrigin", "");
                }
                img.onload = () => {
                    const canvas = new OffscreenCanvas(img.naturalWidth, img.naturalHeight);
                    canvas.getContext("2d").drawImage(img, 0, 0);
                    URL.revokeObjectURL(img.src);
                    canvas.convertToBlob({
                        type: type,
                        quality: 1
                    }).then(blob => {
                        let blobURL = URL.createObjectURL(blob);
                        resolve(blobURL);
                    });
                };
                img.onerror = error => {
                    reject(error);
                }
                img.src = src;
            });
        },
        imgToBlobURL: (img, type = "image/jpeg", quality = 1) => {
            const canvas = new OffscreenCanvas(img.naturalWidth, img.naturalHeight);
            canvas.getContext("2d").drawImage(img, 0, 0);
            return canvas.convertToBlob({
                type: type,
                quality: quality
            }).then(blob => URL.createObjectURL(blob));
        },
        imgBlobUrlArr: async (selector, type = "image/jpeg", quality = 1) => {
            fn.showMsg(displayLanguage.str_53, 0);
            await delay(200);
            let num = 0;
            let imgs = await fn.gae(selector).map(async (img, index, arr) => {
                let blobUrl = await fn.imgToBlobURL(img, type, quality);
                fn.showMsg(`DrawImage ${num += 1}/${arr.length}`, 0);
                return blobUrl;
            });
            fn.hideMsg();
            return imgs;
        },
        blobToDataURL: blob => {
            return new Promise(resolve => {
                const reader = new FileReader();
                reader.onload = () => {
                    resolve(reader.result);
                };
                reader.readAsDataURL(blob);
            });
        },
        convertImage: async (blob, type = "image/jpeg") => {
            const img = new Image();
            await new Promise((resolve, reject) => {
                img.onload = resolve;
                img.onerror = reject;
                img.src = URL.createObjectURL(blob);
            });
            const canvas = new OffscreenCanvas(img.naturalWidth, img.naturalHeight);
            canvas.getContext("2d").drawImage(img, 0, 0);
            URL.revokeObjectURL(img.src);
            return canvas.convertToBlob({
                type: type,
                quality: 0.9
            });
        },
        //自動滾動元素
        scrollEles: async (ele, time = 100, top = 1) => {
            if (isAutoScrolling) return;
            isAutoScrolling = true;
            let eles = fn.gae(ele);
            for (let e of eles) {
                if (isEsc) {
                    isAutoScrolling = false;
                    _unsafeWindow.scrollTo({
                        top: 0
                    });
                    return;
                }
                e.scrollIntoView({
                    behavior: "smooth",
                    block: "end"
                });
                await delay(time);
            }
            if (top === 1) {
                _unsafeWindow.scrollTo({
                    top: 0
                });
            }
            isAutoScrolling = false;
        },
        //自動滾動元素
        aotoScrollEles: async (selector, callback, time = 5000, top = 1) => {
            if (isAutoScrolling) return;
            isAutoScrolling = true;
            let n = 0;
            let timeout = false;
            let imgs = fn.gae(selector);
            let imgNum = imgs.length;
            const autoScrollIntoView = async (arr, num) => {
                for (let i = 0; i < arr.length; i++) {
                    if (isEsc) {
                        fn.hideMsg();
                        isAutoScrolling = false;
                        _unsafeWindow.scrollTo({
                            top: 0
                        });
                        return;
                    }
                    fn.showMsg(`AutoScroll ${n += 1}/${num}`, 0);
                    await new Promise(resolve => {
                        let timeId = setTimeout(() => {
                            timeout = true;
                            clearInterval(loop);
                            resolve();
                        }, time);
                        let loop = setInterval(async () => {
                            if (isEsc) {
                                clearTimeout(timeId);
                                clearInterval(loop);
                                fn.hideMsg();
                                isAutoScrolling = false;
                                _unsafeWindow.scrollTo({
                                    top: 0
                                });
                                resolve();
                                return;
                            }
                            arr[i].scrollIntoView();
                            if (await callback(arr[i])) {
                                clearTimeout(timeId);
                                clearInterval(loop);
                                resolve();
                            }
                        }, 50);
                    });
                    if (timeout) break;
                }
                fn.hideMsg();
                if (timeout) fn.showMsg("Timeout");
                let newImgs = fn.gae(selector);
                let newImgNum = newImgs.length;
                if (imgNum < newImgNum) {
                    newImgs = newImgs.slice(imgNum);
                    imgNum = newImgNum;
                    await autoScrollIntoView(newImgs, newImgNum);
                }
            };
            await autoScrollIntoView(imgs, imgNum);
            if (top === 1) {
                _unsafeWindow.scrollTo({
                    top: 0
                });
            }
            isAutoScrolling = false;
        },
        openInTab: (url, target = "_blank") => {
            let a = document.createElement("a");
            a.href = url;
            a.target = target;
            a.style = "display: none;";
            document.body.append(a);
            a.click();
            a.remove();
        },
        addMutationObserver: (callback, node = document.body, config = MutationObserverConfig) => {
            callback();
            new MutationObserver(callback).observe(node, config);
        },
        scrollEvent: slideIndex => {
            if (!isNumber(slideIndex)) return;
            let modeName = "Samll";
            switch (viewMode) {
                case 0:
                    modeName = "Original";
                    break;
                case 1:
                    modeName = "Samll";
                    break;
                default:
                    console.error("模式错误");
                    break;
            }
            debug(`\nfn.scrollEvent() > imgLocation${modeName}_` + slideIndex);
            let elementById = document.getElementById(`imgLocation${modeName}_` + slideIndex);
            let [sa, sb, sc] = [
                ".FullPictureLoadImage",
                "#FullPictureLoadImgBox:not([style*=none]) .FullPictureLoadImage.small",
                ".FullPictureLoadImage:not(.small)"
            ];
            if (!!elementById) {
                elementById.scrollIntoView();
            } else if (fn.ge(".swiper-slide.swiper-slide-active") && fn.ge(sa)) {
                smoothScrollIntoView(fn.gae(sa)[slideIndex]);
            } else if (fn.ge(sb)) {
                smoothScrollIntoView(fn.gae(sb)[slideIndex]);
            } else if (fn.ge(sc)) {
                smoothScrollIntoView(fn.gae(sc)[slideIndex]);
            } else {
                console.error(" # ", "未定位id!");
            }
        },
        //清除定時器
        clearAllTimer: (mode = 0) => {
            let debuggerStr = `
            if ((() => {}).constructor === Function) {
                Function.prototype.constructor = () => {};
            }
            `;
            if (mode == 0 || mode == 1) new Function(debuggerStr)();
            let endTidStr = `
            let endTid = setTimeout(() => {});
            for (let i = 0; i <= endTid; i++) {
                clearTimeout(i);
            }
            `;
            if (mode == 0 || mode == 2) {
                new Function(endTidStr)();
                let endTid = setTimeout(() => {});
                for (let i = 0; i <= endTid; i++) {
                    clearTimeout(i);
                }
            }
            let endIidStr = `
            let endIid = setInterval(() => {});
            for (let i = 1; i <= endIid; i++) {
                clearInterval(i);
            }
            `;
            if (mode == 0 || mode == 3) {
                new Function(endIidStr)();
                let endIid = setInterval(() => {});
                for (let i = 1; i <= endIid; i++) {
                    clearInterval(i);
                }
            }
        },
        //清除定時器
        clearSetTimeout: () => {
            let endTid = setTimeout(() => {});
            for (let i = 0; i <= endTid; i++) {
                clearTimeout(i);
            }
        },
        //清除元素事件
        clearElementEvent: () => {
            return fn.fetchDoc(document.URL).then(dom => {
                let newDocumentElement = document.importNode(dom.documentElement, true);
                let oldDocumentElement = document.documentElement;
                document.replaceChild(newDocumentElement, oldDocumentElement);
                debug("網站元素事件已清除");
            });
        },
        //創建IMG元素陣列
        createImgArray: (srcs) => {
            return srcs.map((src, i) => {
                let img = new Image();
                img.className = "FullPictureLoadImage lazyload";
                img.src = loading_bak;
                img.dataset.src = src;
                return img;
            });
        },
        //傳入選擇器參數為頁面圖片添加Fancybox5功能
        setFancybox: (selector) => {
            fn.showMsg(displayLanguage.str_137);
            const loadSrcs = (srcArr) => {
                const oddNumberSrcs = srcArr.filter((img, index) => index % 2 == 0);
                const evenNumberSrcs = srcArr.filter((img, index) => index % 2 != 0);
                fn.singleThreadLoadSrcs(oddNumberSrcs);
                fn.singleThreadLoadSrcs(evenNumberSrcs);
            };
            fn.gae(selector).forEach(e => {
                let check = fn.checkImgSrc(e);
                if (e.nodeName === "IMG") {
                    let pE = e.parentNode;
                    if (pE.nodeName === "A") {
                        let src = check.ok ? check.src : e.src;
                        pE.dataset.fancybox = "gallery";
                        pE.href = src;
                        pE.dataset.thumb = src;
                        pE.removeAttribute("title");
                    } else {
                        let a = document.createElement("a");
                        let src = check.ok ? check.src : e.src;
                        a.href = src;
                        a.dataset.fancybox = "gallery";
                        a.dataset.thumb = src;
                        insertBefore(e, a);
                        a.append(e);
                    }
                } else if (e.nodeName === "A") {
                    let img = e.querySelector("img");
                    let check = fn.checkImgSrc(img);
                    let src = check.ok ? check.src : img.src;
                    e.dataset.fancybox = "gallery";
                    e.dataset.thumb = src;
                }
            });
            let srcs = fn.getImgSrcArr(selector);
            loadSrcs(srcs);
            if (siteData.fancybox?.v === 3) {
                return;
            }
            let gallery = fn.gae("[data-fancybox]");
            let FancyboxOptions;
            if (hasTouchEvent) {
                FancyboxOptions = {
                    Hash: false,
                    idle: false,
                    showClass: false,
                    hideClass: false,
                    Images: {
                        Panzoom: {
                            maxScale: 2
                        },
                        zoom: false,
                    },
                    Slideshow: {
                        timeout: FancyboxSlideshowTimeoutNum,
                    },
                    Carousel: {
                        transition: FancyboxSlideshowTransition
                    },
                    Thumbs: {
                        showOnStart: false
                    },
                    Toolbar: {
                        display: {
                            left: ["infobar"],
                            middle: ["flipX", "flipY"],
                            right: ["iterateZoom", "slideshow", "thumbs", "close"]
                        }
                    },
                    on: {
                        done: (fancybox, slide) => {
                            isOpenFancybox = true;
                            if (fancybox.isCurrentSlide(slide)) {
                                smoothScrollIntoView(gallery[slide.index]);
                            } else {
                                smoothScrollIntoView(gallery[fancybox.getSlide().index]);
                            }
                        },
                        close: () => {
                            setTimeout(() => {
                                isOpenFancybox = false;
                            }, 100);
                        }
                    }
                };
            } else {
                FancyboxOptions = {
                    Hash: false,
                    idle: false,
                    showClass: false,
                    hideClass: false,
                    wheel: FancyboxWheel,
                    Images: {
                        Panzoom: {
                            maxScale: 2
                        },
                        zoom: false
                    },
                    Slideshow: {
                        timeout: FancyboxSlideshowTimeoutNum,
                    },
                    Carousel: {
                        transition: FancyboxSlideshowTransition
                    },
                    Thumbs: {
                        showOnStart: false
                    },
                    Toolbar: {
                        display: {
                            left: ["infobar"],
                            middle: ["zoomIn", "zoomOut", "iterateZoom", "toggle1to1", "rotateCCW", "rotateCW", "flipX", "flipY", "fitX", "fitY", "reset"],
                            right: ["slideshow", "fullscreen", "thumbs", "close"]
                        }
                    },
                    on: {
                        done: (fancybox, slide) => {
                            isOpenFancybox = true;
                            if (fancybox.isCurrentSlide(slide)) {
                                smoothScrollIntoView(gallery[slide.index]);
                            } else {
                                smoothScrollIntoView(gallery[fancybox.getSlide().index]);
                            }
                        }
                    },
                    close: () => {
                        setTimeout(() => {
                            isOpenFancybox = false;
                        }, 100);
                    }
                };
            }
            _unsafeWindow.Fancybox.bind("[data-fancybox]", FancyboxOptions);
        },
        lazyload: async () => {
            let check = !!fn.ge("img.FullPictureLoadImage.lazyload");
            if (check) {
                let lazyload = siteData?.autoPager?.lazyload;
                let imgs = fn.gae("img.FullPictureLoadImage.lazyload");
                if (lazyload != 0) {
                    let oddNumberImgs = imgs.filter((img, index) => index % 2 == 0);
                    let evenNumberImgs = imgs.filter((img, index) => index % 2 != 0);
                    fn.singleThreadLoadImgs(oddNumberImgs);
                    fn.singleThreadLoadImgs(evenNumberImgs);
                    await delay(1000);
                    imgs.forEach(img => fn.imagesObserver.observe(img));
                } else {
                    await delay(1000);
                    imgs.forEach((img, i) => {
                        setTimeout(() => {
                            img.src = img.dataset.src;
                            img.classList.remove("lazyload");
                            fn.imagesObserver.observe(img);
                        }, i * 200);
                    });
                }
            }
        },
        setStyleSheet: () => {
            for (const sheet of document.styleSheets) {
                if (sheet.href) {
                    for (const rule of sheet.rules) {
                        if (rule.selectorText === "textarea") {
                            //rule.style.removeProperty("height");
                            rule.style.setProperty("height", "auto");
                            return;
                        }
                    }
                }
            }
        },
        copymangaUI: () => {
            let lastScrollTop = 0;
            document.addEventListener("scroll", event => {
                let st = event.srcElement.scrollingElement.scrollTop;
                if (st > lastScrollTop) {
                    fn.ge("h4.header").setAttribute("style", "top: -30px;");
                    fn.ge("div.footer").setAttribute("style", "bottom: -41px;");
                    lastScrollTop = st;
                } else if (st < lastScrollTop - 20) {
                    fn.ge("h4.header").removeAttribute("style");
                    fn.ge("div.footer").removeAttribute("style");
                    lastScrollTop = st;
                }
            });
            fn.run("$(document).off();");
        },
        copymanga_M_UI: (c, h) => {
            let s = siteUrl.split("/").slice(-2);
            let url = `https://${fn.lh}/h5/details/comic/${s[0]}`;
            let html = `
<div class="comicControlBottom van-popup van-popup--bottom hide" style="z-index: 2024;">
    <div class="comicControlBottomBottom">
        <a href="${c}">
            <span class="comicControlBottomBottomItem">
                <span class="comicControlBottomBottomItemIcon iconfont iconRead_btn_nor_Catalog"></span>
                <span class="comicControlBottomBottomItemText">目錄</span>
            </span>
        </a>
        <a href="${h}">
            <span class="comicControlBottomBottomItem">
                <span class="comicControlBottomBottomItemIcon iconfont iconRead_btn_nor_home"></span>
                <span class="comicControlBottomBottomItemText">首頁</span>
            </span>
        </a>
    </div>
</div>
`;
            document.querySelector(".comicContentPopup").insertAdjacentHTML("beforeend", html);
            document.addEventListener("click", (e) => {
                if (e.target.nodeName === "IMG") {
                    let b = fn.ge(".comicControlBottom");
                    if (b.classList.contains("hide")) {
                        b.classList.remove("hide");
                    } else {
                        b.classList.add("hide");
                    }
                }
            });
        },
        MangabzUI: () => {
            let lastScrollTop = 0;
            document.addEventListener("scroll", event => {
                let st = event.srcElement.scrollingElement.scrollTop;
                if (st > lastScrollTop) {
                    fn.ge(".top-bar").setAttribute("style", "top: -74px;");
                    lastScrollTop = st;
                } else if (st < lastScrollTop - 20) {
                    fn.ge(".top-bar").removeAttribute("style");
                    lastScrollTop = st;
                }
            });
        },
        XmanhuaUI: () => {
            const clickToggleToolbar = () => {
                if (isOpenGallery) return;
                let ht = fn.ge(".header.toolbar");
                let h = fn.ge(".header");
                if (ht) {
                    h.classList.remove("toolbar");
                    h.removeAttribute("style");
                } else {
                    h.classList.add("toolbar");
                    h.setAttribute("style", "top: -64px;")
                }
                let bt = fn.ge(".reader-bottom.toolbar");
                let b = fn.ge(".reader-bottom");
                if (bt) {
                    b.classList.remove("toolbar");
                    b.removeAttribute("style");
                } else {
                    b.classList.add("toolbar");
                    b.setAttribute("style", "bottom: -50px;");
                }
            };
            document.addEventListener("click", clickToggleToolbar);
            let lastScrollTop = 0;
            document.addEventListener("scroll", event => {
                let st = event.srcElement.scrollingElement.scrollTop;
                if (st > lastScrollTop) {
                    fn.ge(".header").classList.add("toolbar");
                    fn.ge(".header").setAttribute("style", "top: -64px;");
                    fn.ge(".reader-bottom").classList.add("toolbar");
                    fn.ge(".reader-bottom").setAttribute("style", "bottom: -50px;");
                    lastScrollTop = st;
                } else if (st < lastScrollTop - 20) {
                    fn.ge(".header").classList.remove("toolbar");
                    fn.ge(".header").removeAttribute("style");
                    fn.ge(".reader-bottom").classList.remove("toolbar");
                    fn.ge(".reader-bottom").removeAttribute("style");
                    lastScrollTop = st;
                }
            });
        },
        cartoonmadUI: () => {
            fn.run("document.onkeydown=null;");
            fn.remove("//td[div[@id='sidebar-follow']] | //td[ins[@class='adsbygoogle']] | //tr[td[script]] | //select");
            let ele = fn.ge("//tr[td[@bgcolor='#EAEAEA']]");
            if (ele) ele.parentNode.append(ele.cloneNode(true));
            let eleM = fn.ge("//tr[td[table[@bgcolor='#CCCCCC']]]");
            if (eleM) {
                let x = eleM.parentNode.lastElementChild.previousElementSibling;
                insertBefore(x, eleM.cloneNode(true));
            }
        },
        cm_decrypt: (raw) => {
            function initCypto() {
                const c = [];

                function r(i) {
                    if (c[i]) return c[i].exports;
                    c[i] = {
                        i,
                        l: false,
                        exports: {}
                    };
                    const e = c[i];
                    const wj = _unsafeWindow.webpackJsonp;
                    wj[0][1][i].call(e.exports, e, e.exports, r);
                    e.l = true;
                    return e.exports;
                }
                return r(6);
            }
            const decrypt = (raw) => {
                const dio = "xxxmanga.woo.key";
                const cypto = initCypto();
                const str = raw;
                const header = str.substring(0, 16);
                const body = str.substring(16, str.length);
                const dioEn = cypto.enc.Utf8.parse(dio);
                const headerEn = cypto.enc.Utf8.parse(header);
                const bHex = cypto.enc.Hex.parse(body);
                const b64 = cypto.enc.Base64.stringify(bHex);
                return cypto.AES.decrypt(b64, dioEn, {
                    iv: headerEn,
                    mode: cypto.mode.CBC,
                    padding: cypto.pad.Pkcs7
                }).toString(cypto.enc.Utf8).toString();
            };
            return JSON.parse(decrypt(raw));
        }
    };

    function simpleLoadImg(img) {
        return new Promise((resolve) => {
            if (!img) {
                resolve();
            }
            let loadSrc = img.dataset.src;
            const temp = new Image();
            if ("referrerpolicy" in siteData) {
                temp.setAttribute("referrerpolicy", siteData.referrerpolicy);
            }
            temp.onload = () => {
                img.dataset.width = temp.naturalWidth;
                img.dataset.height = temp.naturalHeight;
                img.classList.add("loaded");
                img.src = loadSrc;
                resolve();
            };
            temp.onerror = async () => {
                if (loadSrc.includes("https://wsrv.nl/")) {
                    loadSrc = loadSrc.replace("https://wsrv.nl/?url=", ""); //wsrv.nl_CDN
                } else if (loadSrc.includes(".wp.com/") && !document.title.endsWith("4KHD")) {
                    loadSrc = loadSrc.replace(/i\d\.wp\.com\/|\?.+$/g, ""); //WordPressCDN
                }
                let check = await fn.checkImgStatus(loadSrc, 0);
                if (check.ok) {
                    img.dataset.width = check.width;
                    img.dataset.height = check.height;
                    img.classList.add("loaded");
                    img.dataset.src = loadSrc;
                    img.src = loadSrc;
                    resolve();
                } else {
                    img.classList.add("loadError");
                    img.dataset.src = loadSrc;
                    img.src = loadSrc;
                    resolve();
                }
            };
            temp.src = loadSrc;
        });
    }

    //用JS实现多个任务并行执行的队列
    //https://juejin.cn/post/6844903961728647181
    class Queue {
        constructor(workerLen) {
            this.workerLen = workerLen ?? 4;
            this.list = [];
            this.worker = new Array(this.workerLen);
        }

        * executionFunc(index, func, ...args) {
            const _this = this;
            yield func.call(...args).then(() => {
                _this.worker[index] = undefined;
                _this.run();
            });
        }

        addList(list) {
            for (const item of list) {
                this.list.unshift(item);
            }
        }

        run() {
            if (isOpenGallery || isOpenFilter) {
                const runIndex = [];
                for (let i = 0; i < this.workerLen; i++) {
                    const len = this.list.length;
                    if (!this.worker[i] && len > 0) {
                        this.worker[i] = this.executionFunc(i, ...this.list[len - 1]);
                        runIndex.push(i);
                        this.list.pop();
                    }
                }
                for (const index of runIndex) {
                    this.worker[index].next();
                }
            }
        }
    }

    //CSS取得元素返回元素
    //const ge = (selector) => document.querySelector(selector);

    function ge(selector, node = null) {
        return (node || document).querySelector(selector);
    }

    //延遲
    function delay(time = 1000) {
        return new Promise(resolve => setTimeout(resolve, time));
    }

    //等待直至回調函式返回有效物件
    function wait(callback) {
        return new Promise(ending => {
            const loopFn = async () => {
                const check = await callback();
                if (!!check) {
                    ending();
                    return;
                } else {
                    await delay(100);
                    return loopFn();
                }
            };
            loopFn();
        });
    }

    //CSS取得所有元素返回元素陣列
    const gae = (selector, node = null) => [...(node || document).querySelectorAll(selector)];
    //Xpath取得元素返回元素
    const gx = (xpath) => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    //Xpath取得所有元素返回元素陣列
    const gax = (xpath) => {
        let nodes = [];
        let results = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
        let node;
        while (node = results.iterateNext()) {
            nodes.push(node);
        }
        return nodes;
    };

    //元素插入在節點之前
    const insertBefore = (targetNode, newNode) => {
        if ([targetNode, newNode].every(e => isEle(e))) {
            targetNode.parentNode.insertBefore(newNode, targetNode);
        } else {
            console.error("insertBefore參數錯誤\n", targetNode, getType(targetNode), newNode, getType(newNode));
        }
    };

    //元素插入在節點之後
    const insertAfter = (targetNode, newNode) => {
        if ([targetNode, newNode].every(e => isEle(e))) {
            targetNode.parentNode.insertBefore(newNode, targetNode.nextSibling);
        } else {
            console.error("insertAfter參數錯誤\n", targetNode, getType(targetNode), newNode, getType(newNode));
        }
    };

    //創建Style
    const createStyle = css => {
        const style = document.createElement("style");
        style.type = "text/css";
        style.innerHTML = css;
        return style;
    };

    //平滑滾動至元素位置
    function smoothScrollIntoView(element) {
        element.scrollIntoView(smoothOptions);
    }

    //立即滾動至元素位置
    function instantScrollIntoView(element) {
        element.scrollIntoView(instantOptions);
    }

    //數字字串補0
    const getNum = (i, pad = 4) => String(i + 1).padStart(pad, "0");

    const getDataMsg = (text, picNum, imgsNum) => {
        if (isStopDownload) return;
        if (picNum != "none") fn.showMsg(`${displayLanguage.str_23}${downloadNum += 1}/${imgsNum}${displayLanguage.str_24}${text}`, 0);
    };

    //取得參照頁
    const getReferer = (srcUrl) => {
        let referer;
        if (isString(siteData.referer) && siteData.referer == "url") {
            referer = document.URL;
        } else if (/vipr\.im|imagetwist\.com|imgspice\.com/.test(srcUrl) || siteData.referer == "src") {
            referer = srcUrl;
        } else if (/imgtaxi\.com/.test(srcUrl)) {
            referer = "https://imgtaxi.com/";
        } else if (/saint2\.su/.test(srcUrl)) {
            referer = "https://saint2.su/";
        } else if (/bunkr/.test(srcUrl)) {
            referer = "https://bunkr.fi/";
        } else if (/mitaku\.net/.test(srcUrl)) {
            referer = "https://mitaku.net/";
        } else if (isString(siteData.referer) || siteData.referer == "") {
            referer = siteData.referer;
        } else {
            referer = fn.lo + "/";
        }
        return referer;
    };

    let v2ph_cookie = _GM_getValue("v2ph_cookie", "");

    //取得cookie
    const getCookie = () => {
        if (fn.lh.includes(".v2ph.")) {
            return v2ph_cookie;
        }
        return "";
    };

    //Fetch API下載圖片
    const Fetch_API_Download = (srcUrl, picNum = "none", imgsNum = "none") => {
        currentDownloadThread++;
        return new Promise(resolve => {
            fetch(srcUrl, {
                headers: {
                    "accept": "*/*",
                    //"accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
                    //"cache-control": "no-cache",
                    "upgrade-insecure-requests": "1"
                },
                referrer: getReferer(srcUrl),
                referrerPolicy: "strict-origin-when-cross-origin",
                /***同域請求攜帶cookie***/
                //credentials: "same-origin"
            }).then(async res => {
                return {
                    data: res,
                    blob: await res.blob()
                }
            }).then(obj => {
                currentDownloadThread--;
                if (isStopDownload) {
                    resolve("stop");
                    return;
                }
                if (obj.blob.size < 100) {
                    getDataMsg(displayLanguage.str_26, picNum, imgsNum);
                    resolve({
                        error: "下載錯誤",
                        data: obj.data,
                        picNum: picNum,
                        src: srcUrl,
                        get: "Fetch API"
                    });
                } else {
                    getDataMsg(displayLanguage.str_25, picNum, imgsNum);
                    resolve({
                        load: "下載成功",
                        blob: obj.blob,
                        picNum: picNum,
                        src: srcUrl,
                        finalUrl: obj.data?.url,
                        get: "Fetch API"
                    });
                }
            }).catch(error => {
                currentDownloadThread--;
                getDataMsg(displayLanguage.str_26, picNum, imgsNum);
                resolve({
                    error: "下載錯誤",
                    picNum: picNum,
                    src: srcUrl,
                    errorLog: error,
                    get: "Fetch API"
                });
                console.error("Fetch_API_Download() Error: ", error);
            });
        })
    };

    //GM_xmlhttpRequest下載圖片
    const GM_XHR_Download = (srcUrl, picNum = "none", imgsNum = "none") => {
        currentDownloadThread++;
        return new Promise(resolve => {
            _GM_xmlhttpRequest({
                method: "GET",
                url: srcUrl,
                responseType: "blob",
                headers: {
                    origin: fn.lo,
                    referer: getReferer(srcUrl),
                    accept: "*/*",
                    "upgrade-insecure-requests": "1"
                },
                cookie: getCookie(),
                onload: async data => {
                    currentDownloadThread--;
                    if (isStopDownload) {
                        resolve("stop");
                        return;
                    }
                    let blob = data.response;
                    //debug("GM blob", blob);
                    //XBrowser Blob的type是""
                    if (/\/octet-stream/.test(blob.type) && blob.size > 1024 || hasTouchEvent && blob.type == "" && blob.size > 1024) {
                        resolve({
                            load: "下載成功",
                            blob: blob,
                            picNum: picNum,
                            src: srcUrl,
                            finalUrl: data.finalUrl,
                            get: "GM_xmlhttpRequest"
                        });
                        getDataMsg(displayLanguage.str_25, picNum, imgsNum);
                    } else if (/^image|^video|text\/base64\.jpg/.test(blob.type)) {
                        resolve({
                            load: "下載成功",
                            blob: blob,
                            picNum: picNum,
                            src: srcUrl,
                            finalUrl: data.finalUrl,
                            get: "GM_xmlhttpRequest"
                        });
                        getDataMsg(displayLanguage.str_25, picNum, imgsNum);
                    } else {
                        let htmlText = "none";
                        if (/text\/html/.test(blob.type)) {
                            htmlText = blob.text();
                        }
                        resolve({
                            htmlText: htmlText,
                            blob: blob,
                            error: "下載錯誤",
                            picNum: picNum,
                            src: srcUrl,
                            finalUrl: data.finalUrl,
                            data: data,
                            get: "GM_xmlhttpRequest"
                        });
                        getDataMsg(displayLanguage.str_26, picNum, imgsNum);
                    }
                },
                onerror: error => {
                    currentDownloadThread--;
                    resolve({
                        error: "下載錯誤",
                        picNum: picNum,
                        src: srcUrl,
                        errorLog: error,
                        get: "GM_xmlhttpRequest"
                    });
                    getDataMsg(displayLanguage.str_26, picNum, imgsNum);
                    console.error("GM_XHR_Download() Error: ", error);
                }
            });
        });
    };

    //下載儲存
    const saveData = (blob, fileName) => {
        let objURL = URL.createObjectURL(blob);
        let a = document.createElement("a");
        a.href = objURL;
        a.download = fileName;
        document.body.append(a);
        a.click();
        a.remove();
        setTimeout(() => URL.revokeObjectURL(objURL), 1000);
    };

    const captureExclude = () => (isChangeNum || isOpenOptionsUI || isOpenGallery || isOpenFancybox || isOpenFilter || isFetching || isDownloading);

    const checkGeting = () => {
        if (isDownloading) {
            alert(displayLanguage.str_48);
            return true;
        }
        if (isFetching) {
            alert(displayLanguage.str_49);
            return true;
        }
        return false;
    };

    //取得圖片主函式
    const getImgs = async selector => {
        isFetching = true;
        let imgs = null;
        if (!("SPA" in siteData) && !("capture" in siteData) && siteData.repeat != 1 && globalImgArray.length > 0) {
            isFetching = false;
            imgs = globalImgArray;
            return imgs;
        } else if (ge(".FullPictureLoadImage,.FullPictureLoadVideo") && siteData.repeat != 1) {
            imgs = gae(".FullPictureLoadImage:not(.small)");
        } else if (isFn(selector)) {
            imgs = await selector();
            if (isSet(imgs)) {
                imgs = [...imgs];
            }
            if (getImgFn == "" && !getImgFn.includes("專用Fn")) {
                getImgFn += " > " + siteData.name + "專用Fn";
            }
        } else if (isSet(selector)) {
            imgs = [...selector];
        } else if (!selector || selector === "") {
            fn.showMsg(displayLanguage.str_41);
            return;
        } else if (selector.length < 3) {
            fn.showMsg(displayLanguage.str_42);
            return;
        } else if (/^\//.test(selector)) {
            imgs = gax(selector);
            if (siteData.category != "lazyLoad" && !getImgFn.includes("gax(selector)")) {
                getImgFn += " > gax(selector)";
            }
        } else {
            imgs = gae(selector);
            if (siteData.category != "lazyLoad" && !getImgFn.includes("gae(selector)")) {
                getImgFn += " > gae(selector)";
            }
        }
        if (!isArray(imgs)) {
            isFetching = false;
            alert("getImgs() Error! ImageList Not Array");
            return [];
        }
        if (isPromise(imgs[0])) {
            imgs = await Promise.all(imgs); //取出new Promise的值
        }
        fn.hideMsg();
        imgs = imgs.filter(item => item).flat(); //去除空、無用
        let imgsSrcArr = imgs.map(img => {
            let check = fn.checkImgSrc(img);
            if (check.ok) {
                return check.src;
            } else {
                console.error("\ngetImgs() imgs 格式錯誤!", img);
                return null;
            }
        }).filter(item => item);
        if (siteData.category !== "lazyLoad" && globalImgArray.length === 0 && imgs.length !== 0) {
            debug(`\ngetImgs()${getImgFn} 所有圖片網址:`, imgsSrcArr);
        }
        if (siteData.category !== "lazyLoad" && globalImgArray.length === 0 && imgs.length !== 0) {
            debug(`\ngetImgs()${getImgFn} 去重複後的圖片網址:`, [...new Set(imgsSrcArr)]);
        }
        imgsSrcArr = [...new Set(imgsSrcArr)];
        globalImgArray = imgsSrcArr;
        let thums = siteData.thums;
        if (isString(thums)) {
            thumbnailSrcArray = fn.getImgSrcArr(thums);
        }
        isFetching = false;
        return imgsSrcArr;
    };

    //自動下載函式
    const startAutoDownload = async () => {
        let autoDownload = siteData.autoDownload;
        if (!autoDownload) return;
        let [start, time] = autoDownload;
        let next = siteData.next;
        let ele;
        isFn(next) ? ele = await next() : ele = fn.ge(next);
        if (!!ele && start == 1 || !!ele && options.autoDownload == 1) {
            isCountdowning = true;
            let max = time || options.autoDownloadCountdown;
            let countdownNum = Number(max);
            fn.showMsg(`${displayLanguage.str_32}${max}${displayLanguage.str_33}`, 0);
            for (let i = 1; i <= Number(max); i++) {
                await delay(1000);
                if (isStopDownload) return;
                fn.showMsg(`${displayLanguage.str_32}${countdownNum-=1}${displayLanguage.str_33}`, 0);
            }
            await delay(500);
            if (isStopDownload) return;
            if (isFn(next) && isString(ele)) {
                fn.showMsg(displayLanguage.str_34);
                location.href = ele;
            } else if (isEle(ele)) {
                fn.showMsg(displayLanguage.str_35);
                EClick(ele);
            }
        } else if (!ele && start == 1 || !ele && options.autoDownload == 1) {
            fn.showMsg(displayLanguage.str_36, 0);
            options.autoDownload = 0;
            let jsonStr = JSON.stringify(options);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
        }
    };

    const checkURL = (obj) => {
        if (isArray(obj)) {
            return obj.filter(url => isURL(url));
        } else if (isString(obj)) {
            if (isURL(obj)) {
                return obj;
            }
        }
        return null;
    };

    const checkDownloadCondition = () => {
        if (fn.lh.includes(".v2ph.")) {
            const cookie = v2ph_cookie;
            if (!!cookie) {
                return true;
            } else {
                alert("微圖坊下載需先填入cookie。");
                v2ph_cookie = prompt("Set Cookie", v2ph_cookie || "");
                if (!!v2ph_cookie) {
                    _GM_setValue("v2ph_cookie", v2ph_cookie);
                }
                return false;
            }
        }
        return true;
    };

    //圖片影片下載函式
    const DownloadFn = async (array = null, text = null) => {
        if (checkGeting() || isOpenOptionsUI) return;

        const checkDC = checkDownloadCondition();
        if (!checkDC) return;

        isStopDownload = false;
        currentDownloadThread = 0;
        downloadNum = 0;
        promiseBlobArray = [];
        let selector, titleText;
        let autoDownload = siteData.autoDownload;
        let start;
        if (isArray(autoDownload)) {
            [start] = autoDownload;
        }
        let titleReplace = fn.dt({
            s: "title"
        });
        if (fastDownload && array === null) {
            selector = siteData.imgs;
            titleText = (customTitle || titleReplace);
        } else if (array === null) {
            if (!autoDownload || !!autoDownload && start != 1 && options.autoDownload != 1) {
                selector = siteData.imgs;
                titleText = await prompt(displayLanguage.str_51, (customTitle || titleReplace));
                if (titleText === null) {
                    fn.showMsg(displayLanguage.str_41);
                    return;
                }
            } else if (!!autoDownload) {
                if (start == 1 || options.autoDownload == 1) {
                    selector = siteData.imgs;
                    titleText = (customTitle || titleReplace);
                } else {
                    debug("未開啟自動下載");
                    return;
                }
            }
        }
        isDownloading = true;
        if (isString(text)) titleText = text;
        let imgsSrcArr = isArray(array) ? array : await getImgs(selector);
        videoSrcArray = checkURL(videoSrcArray);
        if (imgsSrcArr.length > 0 && titleText != null && titleText != "" || videoSrcArray.length > 0) {
            fn.showMsg(displayLanguage.str_55, 0);
            let loopMsg;
            const imgsNum = imgsSrcArr.length;
            let title = titleText;
            const zip = new JSZip();
            let zipFolder;
            let videosNum;
            if (videoSrcArray.length > 0 && siteData.downloadVideo && siteData.downloadVideo == true && FullPictureLoadCustomDownloadVideo == 1) {
                videosNum = videoSrcArray.length;
                zipFolder = zip.folder(`${title} [${imgsNum}P + ${videosNum}V]`);
            } else {
                zipFolder = zip.folder(`${title} [${imgsNum}P]`);
            }
            if (imgsSrcArr.length > 0) {
                const pad = String(imgsSrcArr.length).length;
                for (let [i, src] of imgsSrcArr.entries()) {
                    let picNum = getNum(i, pad);
                    let promiseBlob;
                    await fn.checkDownloadThread();
                    if (isStopDownload) return (promiseBlobArray = []);
                    siteData.fetch == 1 ? promiseBlob = Fetch_API_Download(src, picNum, imgsNum) : promiseBlob = GM_XHR_Download(src, picNum, imgsNum);
                    promiseBlobArray.push(promiseBlob);
                }
            }
            if (videoSrcArray.length > 0 && siteData.downloadVideo === true && FullPictureLoadCustomDownloadVideo == 1 && !hasTouchEvent) {
                const pad = String(videosNum).length;
                loopMsg = setInterval(() => {
                    fn.showMsg("Video Downloading...", 0);
                }, 2000);
                for (let [i, src] of videoSrcArray.entries()) {
                    let videoNum = getNum(i, pad);
                    let promiseBlob;
                    await fn.checkDownloadThread();
                    if (isStopDownload) {
                        clearInterval(loopMsg);
                        promiseBlobArray = [];
                        return;
                    }
                    siteData.fetch == 1 ? promiseBlob = Fetch_API_Download(src, videoNum, imgsNum + videosNum) : promiseBlob = GM_XHR_Download(src, videoNum, imgsNum + videosNum);
                    promiseBlobArray.push(promiseBlob);
                }
            }
            debug("\nPromiseBlobArray:", promiseBlobArray);
            Promise.all(promiseBlobArray).then(async data => {
                try {
                    clearInterval(loopMsg);
                } catch {}
                if (isStopDownload) {
                    data = null;
                    promiseBlobArray = [];
                    return;
                }
                debug("\nPromiseAllData:", data);
                let blobDataArray = data.filter(item => item.load); //成功下載
                let errorDataArray = data.filter(item => item.error); //下載錯誤
                debug("\nNewDataArray:", blobDataArray);
                debug("\nErrorDataArray:", errorDataArray);
                if (errorDataArray.length > 0) {
                    fn.hideMsg();
                    options.autoDownload = 0;
                    let jsonStr = JSON.stringify(options);
                    localStorage.setItem("FullPictureLoadOptions", jsonStr);
                    downloadNum = 0;
                    isDownloading = false;
                    let yes = await confirm(`${displayLanguage.str_27}${errorDataArray.length}${displayLanguage.str_28}${displayLanguage.str_29}`);
                    if (!yes) {
                        promiseBlobArray = [];
                        blobDataArray = null;
                        errorDataArray = null;
                        return;
                    }
                }
                if (blobDataArray.length > 0) {
                    let total = blobDataArray.length;
                    for (let [i, data] of blobDataArray.entries()) {
                        let ex;
                        let blobData = data.blob;
                        let type = blobData.type;
                        try {
                            if (/octet-stream/.test(type) || hasTouchEvent && type === "") {
                                let url = URL.createObjectURL(blobData);
                                let check = await fn.checkImgStatus(url, 0);
                                URL.revokeObjectURL(url);
                                if (check.ok) {
                                    if (/\.webp/i.test(data.src) && convertWebpToJpg != 1) {
                                        blobData = await fn.convertImage(blobData, "image/webp");
                                        ex = "webp";
                                    } else {
                                        blobData = await fn.convertImage(blobData);
                                        ex = "jpg";
                                    }
                                    if (type === "") {
                                        fn.showMsg(`unknown type to ${ex} ${(i+ 1)}/${total}`, 0);
                                    } else {
                                        fn.showMsg(`octet-stream to ${ex} ${(i+ 1)}/${total}`, 0);
                                    }
                                } else {
                                    console.error("\nDownloadFn() PromiseAll blob資料格式錯誤", data);
                                    fn.showMsg(displayLanguage.str_30, 0);
                                    return;
                                }
                            } else if ((/webp/i.test(type) || /\.webp/i.test(data.finalUrl)) && !type.includes("image/jpeg") && convertWebpToJpg == 1) {
                                blobData = await fn.convertImage(blobData);
                                ex = "jpg";
                                fn.showMsg(`${displayLanguage.str_102} to ${ex} ${(i+ 1)}/${total}`, 0);
                            } else if (/^text\/base64\.jpg/.test(type)) {
                                ex = "jpg";
                            } else {
                                [ex] = type.split("/")[1].match(/\w+/);
                            }
                        } catch {
                            if (/^image/.test(type)) {
                                ex = "jpg";
                            } else if (type === "") {
                                let url = URL.createObjectURL(blobData);
                                let check = await fn.checkImgStatus(url, 0);
                                URL.revokeObjectURL(url);
                                if (check.ok) {
                                    if (/\.webp/i.test(data.src) && convertWebpToJpg != 1) {
                                        ex = "webp";
                                        fn.showMsg(`unknown type to ${ex} ${(i+ 1)}/${total}`, 0);
                                        blobData = await fn.convertImage(blobData, "image/webp");
                                    } else {
                                        ex = "jpg";
                                        fn.showMsg(`unknown type to ${ex} ${(i+ 1)}/${total}`, 0);
                                        blobData = await fn.convertImage(blobData);
                                    }
                                } else {
                                    console.error("\nDownloadFn() PromiseAll blob資料格式錯誤", data);
                                    fn.showMsg(displayLanguage.str_30, 0);
                                    return;
                                }
                            } else {
                                console.error("\nDownloadFn() PromiseAll blob資料格式錯誤", data);
                                fn.showMsg(displayLanguage.str_30, 0);
                                return;
                            }
                        }
                        let fileName;
                        ["mp4", "webm", "mov"].includes(ex) ? fileName = `${data.picNum}V.${(ex)}` : fileName = `${data.picNum}P.${(siteData.ex || ex)}`;
                        if (options.zip == 1) {
                            //console.log(`第${n}/${total}張,檔案名:${fileName},大小:${parseInt(data.blob.size / 1024, 10)} Kb`);
                            zipFolder.file(fileName, blobData, {
                                binary: true
                            });
                        } else {
                            saveData(blobData, title + "_" + fileName);
                            await delay(200);
                            if (i === total - 1) {
                                fn.hideMsg();
                                promiseBlobArray = [];
                                downloadNum = 0;
                                isDownloading = false;
                                startAutoDownload();
                            }
                        }
                    }
                    if (options.zip == 1) {
                        zip.generateAsync({
                            type: "blob"
                        }, (metadata) => {
                            fn.showMsg(displayLanguage.str_31 + metadata.percent.toFixed(2) + " %", 0);
                        }).then(async data => {
                            fn.hideMsg();
                            debug("\nZIP壓縮檔數據:", data);
                            let fileName;
                            if (videoSrcArray.length > 0 && siteData.downloadVideo == true && FullPictureLoadCustomDownloadVideo == 1) {
                                fileName = `${title} [${imgsNum}P + ${videosNum}V].${options.file_extension}`;
                            } else {
                                fileName = `${title} [${imgsNum}P].${options.file_extension}`;
                            }
                            saveData(data, fileName);
                            promiseBlobArray = [];
                            downloadNum = 0;
                            isDownloading = false;
                            startAutoDownload();
                        });
                    }
                } else {
                    promiseBlobArray = [];
                    downloadNum = 0;
                    isDownloading = false;
                    fn.showMsg(displayLanguage.str_43);
                    return;
                }
            });
        } else {
            isDownloading = false;
            fn.showMsg(displayLanguage.str_41);
            return;
        }
    };

    //匯出網址
    const exportImgSrcText = async (array = null) => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = isArray(array) ? array : await getImgs(selector);
        if (srcArr.length == 0 && videoSrcArray.length == 0) return fn.showMsg(displayLanguage.str_44);
        let picNum = srcArr.length;
        let titleText = (customTitle || document.title);
        let fileName = `${titleText}[${picNum}P]_MediaURLs.txt`;
        if (videoSrcArray.length > 0) {
            srcArr = srcArr.concat(videoSrcArray);
            fileName = `${titleText}[${picNum}P + ${videoSrcArray.length}V]_MediaURLs.txt`;
        }
        if (fileUrlArray.length > 0) {
            srcArr = srcArr.concat(fileUrlArray);
            fileName = `${titleText}[${picNum}P`;
            if (videoSrcArray.length > 0) {
                fileName += ` + ${videoSrcArray.length}V`;
            }
            fileName += ` + ${fileUrlArray.length} Files]_MediaURLs.txt`;
        }
        let str = srcArr.join("\n");
        let blob = new Blob([str], {
            type: "text/plain",
            endings: "native"
        });
        saveData(blob, fileName);
        fn.showMsg(`${displayLanguage.str_101}`);
    };

    //複製網址或手動模式的插入圖片
    const copyImgSrcText = async () => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = await getImgs(selector);
        siteData.insertImg ? debug("手動插入圖片") : debug("複製網址");
        if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
        if ((!fn.ge(".FullPictureLoadImage") && !!siteData.insertImg) || siteData.repeat == 1 && !!siteData.insertImg) {
            const [insertTargetEle, insertMode] = siteData.insertImg;
            return fn.insertImg(srcArr, insertTargetEle, insertMode);
        }
        if (videoSrcArray.length > 0) srcArr = srcArr.concat(videoSrcArray);
        if (fileUrlArray.length > 0) srcArr = srcArr.concat(fileUrlArray);
        let textArr = [customTitle || document.title].concat(srcArr);
        let str = textArr.join("\n");
        console.log(str);
        copyToClipboard(str);
        fn.showMsg(`${displayLanguage.str_45}(${textArr.length - 1})`);
    };

    //複製網址
    const copyImgSrcTextB = async (array = null) => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = isArray(array) ? array : await getImgs(selector);
        if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
        if (videoSrcArray.length > 0) srcArr = srcArr.concat(videoSrcArray);
        if (fileUrlArray.length > 0) srcArr = srcArr.concat(fileUrlArray);
        let textArr = [customTitle || document.title].concat(srcArr);
        let str = textArr.join("\n");
        console.log(str);
        copyToClipboard(str);
        fn.showMsg(`${displayLanguage.str_45}(${textArr.length - 1})`);
    };

    //匯出為JSON格式
    const exportJsonFormat = async (array = null) => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = isArray(array) ? array : await getImgs(selector);
        if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
        let object = {
            url: siteUrl,
            title: (customTitle || document.title),
            images: srcArr,
        }
        if (videoSrcArray.length > 0) {
            Reflect.set(object, "videos", videoSrcArray);
        };
        let fileName = (customTitle || document.title) + ".json";
        let blob = new Blob([JSON.stringify(object, null, 4)], {
            type: "application/json"
        });
        saveData(blob, fileName);
        fn.showMsg(displayLanguage.str_175);
    };

    //匯出為Markdown格式
    const exportMarkdownFormat = async (array = null) => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = isArray(array) ? array : await getImgs(selector);
        if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
        let title = "## " + (customTitle || document.title);
        let post = `Post Link:[${siteUrl}](${siteUrl})`;
        let imagesTitle = "## Images";
        let images = srcArr.map(async (src, i) => {
            if (src.startsWith("blob")) {
                src = await fn.blobURLtoDataURL(src);
            }
            return `![${(customTitle || document.title)}${(i + 1)}P](${src})`;
        });
        images = await Promise.all(images);
        let textArr = [title, post, imagesTitle].concat(images);
        if (videoSrcArray.length > 0) {
            let videosTitle = "## Videos";
            textArr.push(videosTitle);
            let videos = videoSrcArray.map(src => "    " + src);
            textArr = textArr.concat(videos);
        };
        let str = textArr.join("\n");
        let fileName = (customTitle || document.title) + ".md";
        let blob = new Blob([str], {
            type: "text/markdown",
            endings: "native"
        });
        saveData(blob, fileName);
        fn.showMsg(displayLanguage.str_177);
    };

    //複製為Markdown格式
    const copyMarkdownFormat = async (array = null) => {
        if (checkGeting() || isOpenOptionsUI) return;
        let selector = siteData.imgs;
        let srcArr = isArray(array) ? array : await getImgs(selector);
        if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
        let title = "## " + (customTitle || document.title);
        let post = `Post Link:[${siteUrl}](${siteUrl})`;
        let imagesTitle = "## Images";
        let images = srcArr.map(async (src, i) => {
            if (src.startsWith("blob")) {
                src = await fn.blobURLtoDataURL(src);
            }
            return `![${(customTitle || document.title)}${(i + 1)}P](${src})`;
        });
        images = await Promise.all(images);
        let textArr = [title, post, imagesTitle].concat(images);
        if (videoSrcArray.length > 0) {
            let videosTitle = "## Videos";
            textArr.push(videosTitle);
            let videos = videoSrcArray.map(src => "    " + src);
            textArr = textArr.concat(videos);
        };
        let str = textArr.join("\n");
        console.log(str);
        copyToClipboard(str);
        fn.showMsg(displayLanguage.str_179);
    };

    const copyToClipboard = text => {
        if (!!_unsafeWindow.navigator.clipboard && _unsafeWindow.isSecureContext) {
            return _unsafeWindow.navigator.clipboard.writeText(text);
        } else {
            let textArea = document.createElement("textarea");
            textArea.value = text;
            textArea.style.position = "absolute";
            textArea.style.opacity = 0;
            textArea.style.left = "-999999px";
            textArea.style.top = "-999999px";
            document.body.append(textArea);
            textArea.focus();
            textArea.select();
            return new Promise((res, rej) => {
                document.execCommand("copy") ? res() : rej();
                textArea.remove();
            });
        }
    };

    //滾動至首張圖片(動畫效果)
    const goToNo1Img = (time = 1000) => {
        let ele;
        ge("#FullPictureLoadImgBox:not([style*=none])") ? ele = ge(".FullPictureLoadImage.small") : ele = ge(".FullPictureLoadImage");
        if (ele) {
            if (time != 0) fn.showMsg(displayLanguage.str_46);
            setTimeout(() => {
                ele.scrollIntoView({
                    behavior: "smooth"
                });
            }, time);
        }
    };

    //滾動至首尾圖片
    const goToImg = img => {
        let ele = null;
        if (ge("#FullPictureLoadImgBox:not([style*=none])") && img == "first") {
            ele = ge(".FullPictureLoadImage.small");
        } else if (img == "first") {
            ele = ge(".FullPictureLoadImage:not(.small)");
        }
        if (ge("#FullPictureLoadImgBox:not([style*=none])") && img == "last") {
            ele = gae(".FullPictureLoadImage.small").at(-1);
        } else if (img == "last") {
            ele = gae(".FullPictureLoadImage:not(.small)").at(-1);
        }
        if (ele) ele.scrollIntoView();
    };

    //自動滾動元素
    const autoScrollEles = () => {
        if (isOpenOptionsUI) return;
        let scrollEle = siteData.scrollEle;
        if (isFn(scrollEle)) {
            scrollEle();
        } else if (isArray(scrollEle)) {
            const [selector, time] = scrollEle;
            fn.scrollEles(selector, time);
        }
    };

    //減少圖片縮放級別
    const reduceZoom = () => {
        if (isFetching || !siteData.insertImg || isOpenOptionsUI) return;
        if (options.zoom <= 10 && ge(".FullPictureLoadImage:not(.small)")) {
            options.zoom == 0 ? options.zoom = 10 : options.zoom = options.zoom -= 1;
            if (options.zoom == 0) cancelZoom();
            let jsonStr = JSON.stringify(options);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
            if (options.zoom > 0) {
                gae(".FullPictureLoadImage:not(.small)").forEach(img => {
                    if (fancyboxBlackList() || options.fancybox !== 1) {
                        img.style.width = `${options.zoom * 10}%`;
                    } else {
                        let pE = img.parentNode;
                        if (pE.nodeName === "A") {
                            pE.style.width = `${options.zoom * 10}%`;
                        }
                    }
                });
                fn.showMsg(`${displayLanguage.str_60} ${options.zoom * 10}%`);
            }
        }
    };

    //增加圖片縮放級別
    const increaseZoom = () => {
        if (isFetching || !siteData.insertImg || isOpenOptionsUI) return;
        if (options.zoom > 1 && options.zoom <= 10 && ge(".FullPictureLoadImage:not(.small)")) {
            options.zoom = options.zoom += 1;
            if (options.zoom > 10) cancelZoom();
            let jsonStr = JSON.stringify(options);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
            if (options.zoom > 0 && options.zoom <= 10) {
                gae(".FullPictureLoadImage:not(.small)").forEach(img => {
                    if (fancyboxBlackList() || options.fancybox !== 1) {
                        img.style.width = `${options.zoom * 10}%`;
                    } else {
                        let pE = img.parentNode;
                        if (pE.nodeName === "A") {
                            pE.style.width = `${options.zoom * 10}%`;
                        }
                    }
                });
                fn.showMsg(`${displayLanguage.str_60} ${options.zoom * 10}%`);
            }
        }
    };

    let viewMode = 0;

    //切換圖片檢視模式
    const toggleImgMode = async () => {
        if (isFetching || !siteData.insertImg || isOpenOptionsUI) return;
        let column;
        if (gae(".FullPictureLoadImage").length < 1) {
            fn.showMsg("沒有圖片或只有影片");
            return;
        }
        if (ge(".FullPictureLoadImage:not(.small):not([style*=none])")) {
            if (ge("#FullPictureLoadImgBox")) {
                ge("#FullPictureLoadImgBox").style.display = "block";
                gae(".FullPictureLoadImage:not(.small),#FullPictureLoadEnd").forEach(e => {
                    if (e.tagName == "IMG") {
                        e.setAttribute("style", "display:none!important;");
                        if (options.zoom > 0) e.style.width = `${options.zoom * 10}%`;
                    } else {
                        e.setAttribute("style", "display:none!important;");
                    }
                });
                viewMode = 1;
                fn.showMsg(displayLanguage.str_93);
                return;
            }
            let width;
            if (options.column == 2 || siteData.category == "comic") {
                width = "48.8%";
                column = 2;
            } else if (options.column == 3) {
                width = "32%";
                column = 3;
            } else if (options.column == 5) {
                width = "19.2%";
                column = 5;
            } else if (options.column == 6) {
                width = "16%";
                column = 6;
            } else {
                column = 4;
                hasTouchEvent ? width = "24%" : width = "24.4%";
            }
            let imgBox = document.createElement("div");
            imgBox.id = "FullPictureLoadImgBox";
            imgBox.style.width = "100%";
            imgBox.style.maxWidth = "1400px";
            imgBox.style.backgroundColor = "#F6F6F6";
            imgBox.style.textAlign = "center";
            imgBox.style.display = "block";
            let srcArr = gae(".FullPictureLoadImage:not(.small)").map(e => e.dataset.src ?? e.src);
            //單雙對換
            //let srcArr2 = srcArr.map((item, index, arr) => { //圖片網址陣列單雙對換用於漫畫式閱讀
            //if (index % 2 == 0) { //圖片網址陣列裡的單數張
            //if ((index + 1) == arr.length) {
            //return arr[index]; //最後一張是單數張則返回此圖片網址
            //} else {
            //return arr[index + 1]; //是單數則返回後一個
            //}
            //} else { //圖片網址陣列裡的雙數張
            //return arr[index - 1]; //是雙數則返回前一個
            //}
            //});
            if (siteData.category == "comic" || (options.column == 2 && siteData.category == "hcomic")) {
                imgBox.style.direction = "rtl";
            }
            let blackList = fancyboxBlackList();
            srcArr.forEach((src, i) => {
                let a = document.createElement("a");
                if (options.fancybox == 1 && !blackList) {
                    a.id = "imgLocationSamll_" + i;
                    a.dataset.fancybox = "FullPictureLoadImageSmall";
                    thumbnailSrcArray.length > 0 && thumbnailSrcArray.length == srcArr.length ? a.dataset.thumb = thumbnailSrcArray[i] : a.dataset.thumb = src;
                    a.href = src;
                }
                let img = new Image();
                img.alt = `no.${i + 1}`;
                img.dataset.index = i;
                img.className = "FullPictureLoadImage small";
                if ("referrerpolicy" in siteData) {
                    img.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                img.dataset.errorNum = 0;
                if ([2, 3].some(n => siteData.insertImg[1] == n)) {
                    img.src = loading_bak;
                    img.dataset.src = src;
                } else {
                    img.decoding = "async";
                    img.onload = () => {
                        img.classList.remove("error");
                    };
                    img.onerror = error => {
                        const num = Number(error.target.dataset.errorNum);
                        if (num < 10) {
                            error.target.dataset.errorNum = num + 1;
                        } else {
                            return;
                        }
                        error.target.classList.add("error");
                        setTimeout(() => {
                            error.target.src = error.target.src;
                        }, 1000);
                    };
                    img.src = src;
                }
                let item = document.createElement("div");
                item.style.width = width;
                //item.style.height = "auto";
                //item.style.float = "left";
                item.style.display = "inline-block";
                if (siteData.category == "comic" || (options.column == 2 && siteData.category == "hcomic")) {
                    item.style.verticalAlign = "middle"
                } else {
                    item.style.verticalAlign = "top"
                }
                item.style.padding = "0.1%";
                item.style.border = "1px solid #a0a0a0";
                if (options.fancybox == 1 && !blackList) {
                    a.append(img);
                    item.append(a);
                    imgBox.append(item);
                } else {
                    item.append(img);
                    imgBox.append(item);
                }
            });
            fragment.append(imgBox);
            let tE = ge("#FullPictureLoadEnd");
            insertBefore(tE, fragment);
            if (ge(".FullPictureLoadVideo")) {
                gae(".FullPictureLoadVideo").forEach(e => insertBefore(tE, e));
            }
            if (options.fancybox == 1 && !("fancybox" in siteData) && ("Fancybox" in _unsafeWindow)) {
                _unsafeWindow.Fancybox.bind("[data-fancybox='FullPictureLoadImageSmall']", FancyboxOptions);
            }
            //tE.parentNode.style.textAlign = "center";
            tE.parentNode.style.display = "block";
            gae(".FullPictureLoadImage:not(.small),#FullPictureLoadEnd").forEach(e => {
                if (e.tagName == "IMG") {
                    e.setAttribute("style", "display:none!important;");
                    if (options.zoom > 0) e.style.width = `${options.zoom * 10}%`;
                } else {
                    e.setAttribute("style", "display:none!important;");
                }
            });
            viewMode = 1;
            fn.showMsg(displayLanguage.str_93);
            let smallImgs = gae("img.FullPictureLoadImage.small");
            setTimeout(() => {
                smallImgs.forEach(img => fn.imagesObserver.observe(img));
            }, 1000);
            let imgDivs = gae("#FullPictureLoadImgBox>div");
            if (siteData.category == "comic") {
                let lastImg = imgDivs.at(-1);
                fn.comicNextObserver.observe(lastImg);
            }
            let imgsNum = 0;
            if (imgDivs[0].nextSibling && siteData.category == "comic") {
                await fn.checkImgStatus(imgDivs[0].nextSibling.querySelector("img").dataset.src, "Wait Loading...");
                if (imgDivs[0].offsetHeight < imgDivs[0].nextSibling.offsetHeight) {
                    imgDivs[0].style.height = (imgDivs[0].nextSibling.offsetHeight) + "px";
                    let img = imgDivs[0].querySelector("img");
                    await fn.checkImgStatus(img.dataset.src, "Wait Loading...");
                    let num = (imgDivs[0].offsetHeight - img.height) / 2;
                    img.style.marginTop = `${num}px`;
                }
                await delay(1200);
                instantScrollIntoView(imgDivs[0]);
            }
            if (TurnOffImageNavigationShortcutKeys != 1) {
                document.addEventListener("keydown", async event => {
                    if (isOpenOptionsUI || isOpenGallery || ge(".fancybox-container,#FullPictureLoadFavorSites") || ["F11", "F12"].some(k => event.code === k || event.key === k)) return;
                    if (event.code === "ArrowUp" || event.key === "ArrowUp") {
                        event.preventDefault();
                        if (imgsNum > 0 && viewMode == 1) {
                            imgsNum -= column;
                            instantScrollIntoView(imgDivs[imgsNum]);
                        }
                    } else if (event.code === "ArrowDown" || event.key === "ArrowDown") {
                        event.preventDefault();
                        if (imgsNum < imgDivs.length && imgsNum != imgDivs.length && viewMode == 1) {
                            imgsNum += column;
                            try {
                                if (imgDivs[imgsNum].nextSibling && siteData.category === "comic") {
                                    debug(`\n第${imgsNum + 1}張(左)高:${imgDivs[imgsNum].offsetHeight}\n第${imgsNum + 2}張(右)高:${imgDivs[imgsNum].nextSibling.offsetHeight}`);
                                    await fn.checkImgStatus(imgDivs[imgsNum].nextSibling.querySelector("img").dataset.src, "Wait Loading...");
                                    if (imgDivs[imgsNum].offsetHeight < imgDivs[imgsNum].nextSibling.offsetHeight) {
                                        imgDivs[imgsNum].style.height = (imgDivs[imgsNum].nextSibling.offsetHeight) + "px";
                                        let img = imgDivs[imgsNum].querySelector("img");
                                        await fn.checkImgStatus(img.dataset.src, "Wait Loading...");
                                        let num = (imgDivs[imgsNum].offsetHeight - img.height) / 2;
                                        debug(`\n修改了之後\n第${imgsNum + 1}張(左)高:${imgDivs[imgsNum].offsetHeight}\n第${imgsNum + 2}張(右)高:${imgDivs[imgsNum].nextSibling.offsetHeight}`);
                                        img.style.marginTop = `${num}px`;
                                    }
                                } else if (siteData.category === "comic") {
                                    imgDivs[imgsNum].src = imgDivs[imgsNum].dataset.src;
                                    await fn.checkImgStatus(imgDivs[imgsNum].dataset.src, "Wait Loading...");
                                }
                                instantScrollIntoView(imgDivs[imgsNum]);
                                await delay(200);
                                instantScrollIntoView(imgDivs[imgsNum]);
                            } catch {
                                if (siteData.category === "comic" && siteData.next && siteData.insertImg) {
                                    if (isString(siteData.next)) {
                                        let next = fn.ge(siteData.next);
                                        if (next) {
                                            fn.showMsg(displayLanguage.str_95, 3000);
                                            EClick(next);
                                        } else {
                                            imgsNum = 0 - column;
                                            fn.showMsg(displayLanguage.str_96, 3000);
                                        }
                                    } else if (isFn(siteData.next)) {
                                        let next = await siteData.next();
                                        if (next) {
                                            fn.showMsg(displayLanguage.str_95, 3000);
                                            location.href = next;
                                        } else {
                                            imgsNum = 0;
                                            fn.showMsg(displayLanguage.str_96, 3000);
                                        }
                                    }
                                } else {
                                    imgsNum = 0;
                                    instantScrollIntoView(imgDivs[0]);
                                    fn.showMsg(displayLanguage.str_94);
                                }
                            }
                        }
                    } else if (event.code === "Delete" && (siteData.category === "comic" || (options.column == 2 && siteData.category === "hcomic"))) {
                        if (imgDivs[0].style.display === "none") {
                            imgDivs[0].style.display = "inline-block";
                        } else {
                            imgDivs[0].style.display = "none";
                        }
                    } else {
                        imgsNum = 0 - column;
                    }
                });
            }
        } else if (ge(".FullPictureLoadImage.small")) {
            ge("#FullPictureLoadImgBox").style.display = "none";
            gae(".FullPictureLoadImage:not(.small),#FullPictureLoadEnd").forEach(e => e.removeAttribute("style"));
            if (options.zoom > 0) {
                gae(".FullPictureLoadImage:not(.small)").forEach(img => (img.style.width = `${options.zoom * 10}%`));
            }
            viewMode = 0;
            fn.showMsg(displayLanguage.str_92);
        }
    };

    const newTabViewLightGallery = localStorage.getItem("newTabViewLightGallery") ?? 0;

    const getConfig = () => {
        const default_Config = {
            ViewMode: 0,
            webtoonWidth: 800,
            shadowGalleryWheel: 0,
            jumpNum: 100,
            behavior: "instant",
            threading: 2,
            backgroundColor: "l",
            showSize: 0,
            noSize: 0,
            move: 0
        };
        let newWindowData = localStorage.getItem("newWindowData");
        if (newWindowData == null) {
            localStorage.setItem("newWindowData", JSON.stringify(default_Config));
            newWindowData = {};
        } else if (isString(newWindowData)) {
            newWindowData = JSON.parse(newWindowData);
        }
        const config = Object.assign(default_Config, newWindowData);
        return config;
    };

    const saveConfig = (config = getConfig()) => {
        localStorage.setItem("newWindowData", JSON.stringify(config));
    };

    const setDefault = () => {
        const keys = [
            "newTabViewLightGallery",
            "newWindowData",
            "FullPictureLoadComicInfiniteScrollMode",
            "FullPictureLoadOptions",
            "FullPictureLoadCustomDownloadVideo",
            "FullPictureLoadShowEye"
        ];
        for (const key of keys) {
            if (!!localStorage.getItem(key)) {
                localStorage.removeItem(key);
            }
        }
        _GM_setValue("FullPictureLoadMsgPos", 0);
        _GM_setValue("ShowFullPictureLoadFixedMenu", 1);
        _GM_setValue("FavorOpenInNewTab", 0);
        _GM_setValue("convertWebpToJpg", 0);
        _GM_setValue("FancyboxSlideshowTimeout", 3);
        _GM_setValue("FancyboxWheel", 1);
        _GM_setValue("FancyboxSlideshowTransition", "fade");
    };

    //新分頁空白頁檢視圖片
    const newTabView = async () => {

        if (checkGeting() || isDragging || "eye" in siteData && siteData.eye === 0) return;

        const config = getConfig();

        let imgSrcs;
        if ("SPA" in siteData) {
            let selector = siteData.capture ?? siteData.imgs;
            imgSrcs = await getImgs(selector);
        } else if (!("capture" in siteData)) {
            globalImgArray.length > 0 ? imgSrcs = globalImgArray : imgSrcs = await getImgs(siteData.imgs);
        } else {
            captureSrcArray.length > 0 ? imgSrcs = captureSrcArray : imgSrcs = await getImgs(siteData.imgs);
        }

        if (!!imgSrcs?.length && imgSrcs.length > 0) {

            let newWindow;
            let dom;
            try {
                newWindow = _unsafeWindow.open("about:blank", "_blank");
                dom = newWindow.document;
            } catch {
                alert("An error occurred\nUnable to use window.open()");
                return;
            }
            dom.write(`
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, shrink-to-fit=no">
        <title>${displayLanguage.str_106.replace(/\(.\)/, "")}:${customTitle ?? document.title}</title>
    </head>
    <body style="text-align: center;">
        <div id="imgBox"></div>
    </body>
</html>
            `);
            newWindow.siteData = siteData;
            newWindow.fn = fn;
            newWindow.hasTouchEvent = hasTouchEvent;
            newWindow.config = config;
            newWindow.lightGallery = newTabViewLightGallery
            newWindow.totalNumberOfElements = 0;
            newWindow.currentReferenceElement = null;
            newWindow.imgViewIndex = -1;
            newWindow.webtoonWidth = config.webtoonWidth;
            newWindow.category = siteData.category;
            newWindow.newImgs = imgSrcs;
            newWindow.thumbnailSrcArray = thumbnailSrcArray;
            newWindow.menuLanguage = displayLanguage.galleryMenu;
            newWindow.isOpenFancybox = false;
            newWindow.l10n = Fancyboxl10nV5();
            newWindow.smoothOptions = smoothOptions;
            newWindow.instantOptions = instantOptions;
            newWindow.smoothScrollIntoView = smoothScrollIntoView;
            newWindow.instantScrollIntoView = instantScrollIntoView;

            let newWindowStyleCss = `
body {
    background-color: #333;
    display: block;
    margin: 0px;
}
#FixedMenu {
    text-align: center;
    font-family: Arial, sans-serif;
    font-size: 14px;
    color: #000000;
    width: ${hasTouchEvent ? "102px" : "132px"};
    height: auto;
    padding: 5px 5px 2px 5px;
    position: fixed;
    left: ${hasTouchEvent ? "0px" : "-138px"};
    bottom: 0px;
    border: #ccc 1px solid;
    border-radius: 3px;
    background-color: #fff;
    z-index: 2;
    &:hover {
        left: 0px;
    }
}
.FixedMenuitem {
    width: ${hasTouchEvent ? "90px" : "120px"};
    height: 24px;
    line-height: 24px;
    overflow: hidden;
    font-size: 14px;
    border: #ccc 1px solid;
    background-color: #f6f6f6;
    padding: 0 5px 0 5px;
    margin: 0 2px 3px 0;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
.FixedMenuitem.active {
    color: #fff;
    background: #1790E6;
}
img.default {
    vertical-align: middle;
    width: auto;
    height: auto;
    object-fit: contain;
    border: solid #fff;
    background-color: #fff;
}
img.single {
    width: auto;
    height: auto;
    max-width: ${isFirefox ? "calc(100% - 6px)" : "calc(100% - 4px)"};
    max-height: 99vh;
    display: block;
    margin: 0 auto;
    border: solid #fff;
}
img.webtoon {
    width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
    border: unset !important;
}
img.small {
    display: inline-block;
    vertical-align: middle;
    width: auto;
    height: auto;
    max-width: 31.8%;
    max-height: 33vh;
    border: solid #fff;
}
.viewer-backdrop {
    background-color: rgba(0, 0, 0, .94) !important;
}
`;
            if (_GM_getValue("FancyboxSlideshowTransition") === "no") {
                newWindowStyleCss += `
.fancybox__container .to-next>.fancybox__content,
.fancybox__container .to-prev>.fancybox__content {
    display: none !important;
}
                `;
            }

            //添加主要CSS
            _GM_addElement(dom.head, "style", {
                textContent: newWindowStyleCss
            });

            //添加FancyboxCSS
            _GM_addElement(dom.head, "style", {
                textContent: FancyboxV5Css
            });

            //添加ViewerJsCSS
            _GM_addElement(dom.head, "style", {
                textContent: ViewerJsCss
            });

            //引入Fancybox
            _GM_addElement(dom.head, "script", {
                textContent: JqueryJS + FancyboxV5JS + `
var FancyboxOptions = {};

if (hasTouchEvent) {
    FancyboxOptions = {
        Hash: false,
        idle: false,
        showClass: false,
        hideClass: false,
        Images: {
            Panzoom: {
                maxScale: 2
            },
            zoom: false
        },
        Slideshow: {
            timeout: ${FancyboxSlideshowTimeoutNum},
        },
        Carousel: {
            transition: "${FancyboxSlideshowTransition}"
        },
        Thumbs: {
            showOnStart: false
        },
        Toolbar: {
            display: {
                left: ["infobar"],
                middle: ["flipX", "flipY"],
                right: ["iterateZoom", "slideshow", "thumbs", "close"]
            }
        },
        on: {
            done: (fancybox, slide) => {
                isOpenFancybox = true;
                let slideIndex = slide.index;
                let imgs = [...document.images];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                }
                if (fancybox.isCurrentSlide(slide)) {
                    imgViewIndex = slideIndex;
                    if (config.ViewMode != 4) {
                        imgs[slideIndex].style.border = "solid #32a1ce";
                    }
                    smoothScrollIntoView(imgs[slideIndex]);
                } else {
                    imgViewIndex = fancybox.getSlide().index;
                    if (config.ViewMode != 4) {
                        imgs[slideIndex].style.border = "solid #32a1ce";
                    }
                    smoothScrollIntoView(imgs[fancybox.getSlide().index]);
                }
            },
            close: fancybox => {
                document.body.classList.remove("hide-scrollbar");
                let slideIndex = fancybox.getSlide().index;
                imgViewIndex = slideIndex;
                let imgs = [...document.images];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    imgs[slideIndex].style.border = "solid #32a1ce";
                }
                smoothScrollIntoView(imgs[slideIndex]);
                setTimeout(() => {
                    isOpenFancybox = false;
                }, 200);
            }
        }
    }
} else {
    FancyboxOptions = {
        Hash: false,
        idle: false,
        showClass: false,
        hideClass: false,
        wheel: "${FancyboxWheel}",
        Images: {
            Panzoom: {
                maxScale: 2
            },
            zoom: false
        },
        Slideshow: {
            timeout: ${FancyboxSlideshowTimeoutNum},
        },
        Carousel: {
            transition: "${FancyboxSlideshowTransition}"
        },
        Thumbs: {
            showOnStart: false
        },
        Toolbar: {
            display: {
                left: ["infobar"],
                middle: ["zoomIn", "zoomOut", "iterateZoom", "toggle1to1", "rotateCCW", "rotateCW", "flipX", "flipY", "fitX", "fitY", "reset"],
                right: ["slideshow", "fullscreen", "thumbs", "close"]
            }
        },
        on: {
            done: (fancybox, slide) => {
                isOpenFancybox = true;
                let slideIndex = slide.index;
                let imgs = [...document.images];
                imgs.forEach(e => (e.style.border = ""));
                if (fancybox.isCurrentSlide(slide)) {
                    imgViewIndex = slideIndex;
                    let img = imgs[imgViewIndex];
                    currentReferenceElement = img;
                    img.style.border = "solid #32a1ce";
                    smoothScrollIntoView(img);
                } else {
                    imgViewIndex = fancybox.getSlide().index;
                    let img = imgs[imgViewIndex];
                    currentReferenceElement = img;
                    img.style.border = "solid #32a1ce";
                    smoothScrollIntoView(img);
                }
            },
            close: fancybox => {
                document.body.classList.remove("hide-scrollbar");
                let slideIndex = fancybox.getSlide().index;
                imgViewIndex = slideIndex;
                let imgs = [...document.images];
                imgs.forEach(e => (e.style.border = ""));
                let img = imgs[imgViewIndex];
                currentReferenceElement = img;
                img.style.border = "solid #32a1ce";
                smoothScrollIntoView(img);
                setTimeout(() => {
                    isOpenFancybox = false;
                }, 200);
            }
        }
    }
}

if (l10n !== "EN") {
    Fancybox.defaults.l10n = l10n;
}
`
            });

            //引入ViewerJs
            _GM_addElement(dom.head, "script", {
                textContent: ViewerJs
            });

            const newWindowScriptCode = `
const fragment = new DocumentFragment();

if (lightGallery == 1) {
    var ViewerJsInstance = new Viewer(document.querySelector("#imgBox"), {
        navbar: false,
        title: false,
        initialCoverage: 0.99,
        interval: ${FancyboxSlideshowTimeoutNum},
        url: "data-src",
        viewed: event => {
            let slideIndex = event.detail.index;
            let imgs = [...document.images];
            imgViewIndex = slideIndex;
            let img = event.detail.originalImage;
            currentReferenceElement = img;
            if (config.ViewMode != 4) {
                imgs.forEach(e => (e.style.border = ""));
                img.style.border = "solid #32a1ce";
            }
            smoothScrollIntoView(img);
        }
    });
}

function setFancybox() {
    Fancybox.bind("[data-fancybox]", FancyboxOptions);
}

function addFixedMenu() {
    let menuDiv = document.createElement("div");
    menuDiv.id = "FixedMenu";
    const menuObj = [{
        id: "MenuWebtoonItem",
        text: menuLanguage.webtoon,
        cfn: () => webtoonImageLayout()
    }, {
        id: "MenuRTLItem",
        text: menuLanguage.rtl,
        cfn: () => rtlImageLayout()
    }, {
        id: "MenuSmallItem",
        text: menuLanguage.small,
        cfn: () => smallImageLayout()
    }, {
        id: "MenuSinglePageItem",
        text: menuLanguage.single,
        cfn: () => singleImageLayout()
    }, {
        id: "MenuDefaultItem",
        text: menuLanguage.default,
        cfn: () => defaultImageLayout()
    }];
    const createMenu = obj => {
        let item = document.createElement("div");
        item.id = obj.id;
        item.className = "FixedMenuitem";
        item.innerText = obj.text;
        item.oncontextmenu = () => false;
        if (!!obj.cfn) item.addEventListener("click", obj.cfn);
        menuDiv.append(item);
    };
    menuObj.forEach(obj => createMenu(obj));
    fragment.append(menuDiv);
    document.body.append(fragment);
}
addFixedMenu();

if (hasTouchEvent) {
    let menu = document.querySelector("#FixedMenu");
    menu.style.display = "none";
    let lastScrollTop = 0;
    let scroll = "";
    document.addEventListener("scroll", event => {
        if (isOpenFancybox || document.querySelector(".viewer-container .viewer-canvas>img")) return;
        let st = event.srcElement.scrollingElement.scrollTop;
        if (st > lastScrollTop) {
            scroll = "down";
            menu.style.display = "none";
            lastScrollTop = st;
        } else if (st < lastScrollTop - 20) {
            scroll = "up";
            menu.style.display = "";
            lastScrollTop = st;
        }
    });
}

document.addEventListener("keydown", event => {
    if (isOpenFancybox || document.querySelector(".viewer-container .viewer-canvas>img")) return;
    if (event.code === "Numpad0" || event.key === "0") return defaultImageLayout();
    if (event.code === "Numpad1" || event.key === "1") return singleImageLayout();
    if (event.code === "Numpad2" || event.key === "2") return smallImageLayout();
    if (event.code === "Numpad3" || event.key === "3") return rtlImageLayout();
    if (event.code === "Numpad4" || event.key === "4") return webtoonImageLayout();
});

document.addEventListener("keydown", event => {
    if (isOpenFancybox || document.querySelector(".viewer-container .viewer-canvas>img") || ["F11", "F12"].some(k => event.code === k || event.key === k)) return;
    const imgs = [...document.images];
    if (event.code === "Numpad0" || event.code === "Digit0" || event.key === "0") return defaultImageLayout();
    if (event.code === "Numpad1" || event.code === "Digit1" || event.key === "1") return singleImageLayout();
    if (event.code === "Numpad2" || event.code === "Digit2" || event.key === "2") return smallImageLayout();
    if (event.code === "Numpad3" || event.code === "Digit3" || event.key === "3") return rtlImageLayout();
    if (event.code === "Numpad4" || event.code === "Digit4" || event.key === "4") return webtoonImageLayout();
    if ((event.code === "Home" || event.key === "Home") || (event.code === "End" || event.key === "End")) {
        event.preventDefault();
        if (event.code === "Home" || event.key === "Home") {
            imgViewIndex = 0;
        } else {
            imgViewIndex = imgs.length - 1;
        }
        const img = imgs[imgViewIndex];
        if (config.ViewMode != 4) {
            imgs.forEach(e => (e.style.border = ""));
            img.style.border = "solid #32a1ce";
        }
        currentReferenceElement = img;
        return instantScrollIntoView(img);
    }
    if (config.ViewMode == 4 && (["NumpadAdd", "Equal"].some(k => event.code === k) || ["+", "="].some(k => event.code === k))) {
        return increaseWidth();
    }
    if (config.ViewMode == 4 && (["NumpadSubtract", "Minus"].some(k => event.code === k) || ["-", "_"].some(k => event.key === k))) {
        return reduceWidth();
    }
    if ((event.code === "KeyR" || event.key === "r" || event.key === "R") && [0, 2, 3].some(m => config.ViewMode == m)) {
        let box = document.querySelector("#imgBox");
        if (box.style.direction == "rtl") {
            return (box.style.direction = "ltr");
        } else {
            return (box.style.direction = "rtl");
        }
    }
    if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex < 0) {
        if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
        event.preventDefault();
        imgViewIndex = imgs.length - 1;
        const img = imgs[imgViewIndex];
        if (config.ViewMode != 4) {
            imgs.forEach(e => (e.style.border = ""));
            img.style.border = "solid #32a1ce";
        }
        currentReferenceElement = img;
        return instantScrollIntoView(img);
    } else if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex >= 0) {
        if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
        event.preventDefault();
        imgViewIndex--;
        let img = imgs[imgViewIndex];
        if (img === undefined) {
            imgViewIndex = imgs.length - 1;
            img = imgs[imgViewIndex];
        }
        if (config.ViewMode != 4) {
            imgs.forEach(e => (e.style.border = ""));
            if (img !== undefined) {
                img.style.border = "solid #32a1ce";
            }
        }
        currentReferenceElement = img;
        return instantScrollIntoView(img);
    } else if ((["KeyS", "KeyD", "ArrowDown", "ArrowRight"].some(k => event.code === k) || ["s", "S", "d", "D", "ArrowDown", "ArrowRight"].some(k => event.key === k)) && imgViewIndex <= imgs.length - 1) {
        if (config.ViewMode == 4 && (event.code === "ArrowDown" || event.key === "ArrowDown")) return;
        event.preventDefault();
        imgViewIndex++;
        let img = imgs[imgViewIndex];
        if (imgViewIndex > imgs.length - 1 && category === "comic") {
            return window.close();
        } else if (imgViewIndex > imgs.length - 1) {
            imgViewIndex = 0;
        }
        if (config.ViewMode != 4) {
            imgs.forEach(e => (e.style.border = ""));
            if (img !== undefined) {
                img.style.border = "solid #32a1ce";
            }
        }
        if (img === undefined) {
            imgViewIndex = 0;
            img = imgs[imgViewIndex];
        }
        currentReferenceElement = img;
        return instantScrollIntoView(img);
    } else if ((event.code === "Delete" || event.key === "Delete")) {
        const hideE = [...document.querySelectorAll("#imgBox>*")][imgViewIndex];
        if (hideE !== undefined) {
            hideE.style.display = "none";
        }
    } else if ((event.code === "Enter" || event.key === "Enter")) {
        [...document.querySelectorAll("#imgBox>*")].forEach(e => (e.style.display = ""));
    } else if (!["KeyR", "NumpadAdd", "Equal", "NumpadSubtract", "Minus"].some(k => event.code === k) || !["r", "R", "-", "+", "=", "_"].some(k => event.key === k)) {
        imgViewIndex = -1;
    }
});

document.addEventListener("wheel", (event) => {
    if (!isOpenFancybox && !document.querySelector(".viewer-container .viewer-canvas>img") && config.ViewMode == 4 && (event.ctrlKey || event.altKey || event.shiftKey)) {
        event.preventDefault();
        event.stopPropagation();
        if (event.deltaY < 0) {
            increaseWidth();
        }
        if (event.deltaY > 0) {
            reduceWidth();
        }
    }
}, {
    passive: false
});

document.addEventListener("wheel", (event) => {
    if (!isOpenFancybox && !document.querySelector(".viewer-container .viewer-canvas>img") && [0, 1, 3].some(m => config.ViewMode == m) && [1, 2].some(m => config.shadowGalleryWheel == m) && !event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
        event.preventDefault();
        event.stopPropagation();
        const imgs = [...document.images];
        if (config.shadowGalleryWheel == 1) {
            if (event.deltaY < 0 && imgViewIndex < 0) {
                imgViewIndex = imgs.length - 1;
                imgs[imgViewIndex].style.border = "solid #32a1ce";
                return instantScrollIntoView(imgs[imgViewIndex]);
            } else if (event.deltaY < 0 && imgViewIndex >= 0) {
                imgViewIndex--;
                if (imgViewIndex < 0) imgViewIndex = imgs.length - 1;
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (imgs[imgViewIndex] !== undefined) {
                        imgs[imgViewIndex].style.border = "solid #32a1ce";
                    }
                }
                return instantScrollIntoView(imgs[imgViewIndex]);
            } else if (event.deltaY > 0 && imgViewIndex <= imgs.length - 1) {
                imgViewIndex++;
                if (imgs[imgViewIndex] === undefined) {
                    imgViewIndex = 0;
                }
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (imgs[imgViewIndex] !== undefined) {
                        imgs[imgViewIndex].style.border = "solid #32a1ce";
                    }
                }
                return instantScrollIntoView(imgs[imgViewIndex]);
            } else {
                imgViewIndex = -1;
            }
        }
        if (config.shadowGalleryWheel == 2) {
            if (event.deltaY < 0) {
                if (Number(currentReferenceElement?.dataset?.index) <= 0) return;
                imgs.forEach(e => (e.style.border = ""));
                return instantScrollIntoView(getPrevRowElement());
            }
            if (event.deltaY > 0) {
                if (Number(currentReferenceElement?.dataset?.index) >= totalNumberOfElements - 1) return;
                imgs.forEach(e => (e.style.border = ""));
                return instantScrollIntoView(getNextRowElement());
            }
        }
    }
}, {
    passive: false
});

function loadImgs() {
    const imgs = [...document.images];
    const oddNumberImgs = imgs.filter((img, index) => index % 2 == 0);
    const evenNumberImgs = imgs.filter((img, index) => index % 2 != 0);
    fn.singleThreadLoadImgs(oddNumberImgs);
    fn.singleThreadLoadImgs(evenNumberImgs);
}

function aspectRatio() {
    const verticalScreen = window.innerHeight / window.innerWidth > 1;
    const imgs = [...document.images];
    imgs.forEach(img => {
        if (verticalScreen && img.className === "default") {
            img.style.minWidth = "98vw";
            img.style.maxWidth = "98vw";
            img.style.minHeight = "";
            img.style.maxHeight = "";
        } else if (img.className === "default") {
            img.style.minHeight = "calc(100vh - 4px)";
            img.style.maxHeight = "calc(100vh - 4px)";
            img.style.minWidth = "";
            img.style.maxWidth = "98vw";
        }
    });
    if (imgs[imgViewIndex] !== undefined && config.ViewMode != 4 && !hasTouchEvent) {
        imgs.forEach(e => (e.style.border = ""));
        imgs[imgViewIndex].style.border = "solid #32a1ce";
        setTimeout(() => instantScrollIntoView(imgs[imgViewIndex]), 100);
    }
}

if (hasTouchEvent) {
    window.addEventListener("deviceorientation", () => {
        aspectRatio();
    });
} else {
    window.addEventListener("resize", () => {
        aspectRatio();
    });
}

function increaseWidth() {
    let imgs = [...document.images];
    if (webtoonWidth < 1900 && webtoonWidth < window.innerWidth) {
        webtoonWidth = (Number(webtoonWidth) + 50);
        config.webtoonWidth = webtoonWidth;
        saveConfig();
        imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
    } else {
        webtoonWidth = 800;
        config.webtoonWidth = 800;
        saveConfig();
        imgs.forEach(e => (e.style.maxWidth = "800px"));
    }
}

function reduceWidth() {
    let imgs = [...document.images];
    if (webtoonWidth > 100) {
        webtoonWidth = (Number(webtoonWidth) - 50);
        config.webtoonWidth = webtoonWidth;
        saveConfig();
        imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
    } else {
        webtoonWidth = 800;
        config.webtoonWidth = 800;
        saveConfig();
        imgs.forEach(e => (e.style.maxWidth = "800px"));
    }
}

function getNextRowElement() {
    const eles = [...document.images];
    const index = Number(currentReferenceElement.dataset.index);
    if (index >= eles.length - 1) {
        imgViewIndex = index;
        return eles.at(-1);
    }
    for (let i = index + 1; i < eles.length; i++) {
        if (eles[i].offsetTop > currentReferenceElement.offsetTop) {
            currentReferenceElement = eles[i];
            imgViewIndex = i;
            return eles[i];
        }
    }
    imgViewIndex = eles.length - 1;
    return eles.at(-1);
}

function getPrevRowElement() {
    const eles = [...document.images];
    const index = Number(currentReferenceElement.dataset.index);
    if (index <= 0) {
        imgViewIndex = 0;
        return eles.at(0);
    }
    for (let i = index - 1; i >= 0; i--) {
        if (eles[i].offsetTop < currentReferenceElement.offsetTop) {
            currentReferenceElement = eles[i];
            imgViewIndex = i;
            return eles[i];
        }
    }
    imgViewIndex = 0;
    return eles.at(0);
}

function createImgElement(mode) {
    window.scrollTo({
        top: 0
    });
    if (config.ViewMode == 3) {
        document.querySelector("#imgBox").style.direction = "rtl";
    } else {
        document.querySelector("#imgBox").style.direction = "";
    }
    imgViewIndex = -1;
    [...document.querySelectorAll(".FixedMenuitem")].forEach(item => item.classList.remove("active"));
    document.querySelector("#imgBox").innerHTML = "";
    const imgElements = newImgs.map((src, i) => {
        let img = document.createElement("img");
        img.className = mode;
        img.dataset.index = i;
        img.dataset.fancybox = "gallery";
        if ("referrerpolicy" in siteData) {
            img.setAttribute("referrerpolicy", siteData.referrerpolicy);
        }
        img.src = "${loading_bak}";
        img.dataset.src = src;
        if (thumbnailSrcArray.length > 0) {
            img.dataset.thumb = thumbnailSrcArray[i];
        } else {
            img.dataset.thumb = src;
        }
        if (config.ViewMode == 4) {
            img.style.maxWidth = webtoonWidth + "px";
        }
        return img;
    });
    fragment.append(...imgElements);
    document.querySelector("#imgBox").append(fragment);
    if (lightGallery == 1) {
        ViewerJsInstance.update();
    } else {
        setFancybox();
    }
    loadImgs();
    aspectRatio();
    currentReferenceElement = imgElements.at(0);
    totalNumberOfElements = imgElements.length;
    fn.wait(() => imgElements.at(-1)?.offsetHeight > 100).then(() => {
        setTimeout(() => {
            aspectRatio();
            [...document.images].forEach(img => fn.imagesObserver.observe(img));
        }, 1000);
    });
}

function saveConfig() {
    localStorage.setItem("newWindowData", JSON.stringify(config));
}

function defaultImageLayout() {
    config.ViewMode = 0;
    saveConfig();
    createImgElement("default");
    document.querySelector("#MenuDefaultItem").classList.add("active");
}

function singleImageLayout() {
    config.ViewMode = 1;
    saveConfig();
    createImgElement("single");
    document.querySelector("#MenuSinglePageItem").classList.add("active");
}

function smallImageLayout() {
    config.ViewMode = 2;
    saveConfig();
    createImgElement("small");
    document.querySelector("#MenuSmallItem").classList.add("active");
}

function rtlImageLayout() {
    config.ViewMode = 3;
    saveConfig();
    createImgElement("default");
    document.querySelector("#MenuRTLItem").classList.add("active");
}

function webtoonImageLayout() {
    config.ViewMode = 4;
    saveConfig();
    createImgElement("webtoon");
    document.querySelector("#MenuWebtoonItem").classList.add("active");
}

if (config.ViewMode == 1) {
    singleImageLayout();
} else if (config.ViewMode == 2) {
    smallImageLayout();
} else if (config.ViewMode == 3) {
    rtlImageLayout();
} else if (config.ViewMode == 4) {
    webtoonImageLayout();
} else {
    defaultImageLayout();
}
`;

            //注入主要代碼
            _GM_addElement(dom.head, "script", {
                textContent: newWindowScriptCode
            });

        } else {
            alert("No Image.");
            return;
        }
    };

    //創建影子畫廊
    const createShadowGallery = async () => {

        if (("fancybox" in siteData) || ("gallery" in siteData && siteData.gallery == 1)) {
            return createIframeGallery();
        }

        if (checkGeting() || hasTouchEvent || isOpenGallery || isOpenOptionsUI) return;

        isOpenGallery = true;

        let srcs;
        if ("SPA" in siteData) {
            let selector = siteData.capture ?? siteData.imgs;
            srcs = await getImgs(selector);
        } else if (!("capture" in siteData)) {
            globalImgArray.length > 0 ? srcs = globalImgArray : srcs = await getImgs(siteData.imgs);
        } else {
            captureSrcArray.length > 0 ? srcs = captureSrcArray : srcs = await getImgs(siteData.imgs);
        }
        if (srcs.length < 1) return (isOpenGallery = false);

        fn.hideMsg();

        const config = getConfig();
        let webtoonWidth = config.webtoonWidth;
        let totalNumberOfElements = 0;
        let imgViewIndex = -1;
        let currentReferenceElement;
        let nextButtonIsShown = false;
        let dNum = 0;

        const mainHtml = '<div id="FullPictureLoadShadowGallery" style="overflow: clip !important;display: initial !important;position: fixed !important;z-index: 2147483647 !important;"></div>';
        document.body.insertAdjacentHTML("beforeend", mainHtml);

        const FullPictureLoadShadowGallery = ge("#FullPictureLoadShadowGallery");
        const shadow = FullPictureLoadShadowGallery.attachShadow({
            mode: "closed"
        });

        const hideSelector = "body>*:not(script,[id^=Full],[class^=Full],#comicRead,#toast,#fab,#ehvp-base,[id^='pagetual'],[class^='pagetual'],[id^='pv-'],[class^='pv-gallery'],[id^=Autopage])";
        gae(hideSelector).forEach(e => (e.style.display = "none"));

        const increaseWidth = () => {
            let imgs = gae("img", shadow);
            if (webtoonWidth < 1900 && webtoonWidth < _unsafeWindow.innerWidth) {
                webtoonWidth = (Number(webtoonWidth) + 50);
                config.webtoonWidth = webtoonWidth;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
            } else {
                webtoonWidth = 800;
                config.webtoonWidth = 800;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = "800px"));
            }
        };

        const reduceWidth = () => {
            let imgs = gae("img", shadow);
            if (webtoonWidth > 100) {
                webtoonWidth = (Number(webtoonWidth) - 50);
                config.webtoonWidth = webtoonWidth;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
            } else {
                webtoonWidth = 800;
                config.webtoonWidth = 800;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = "800px"));
            }
        };

        const closeGallery = () => {
            _unsafeWindow.removeEventListener("resize", aspectRatio);
            _unsafeWindow.removeEventListener("keydown", kEvent);
            gae(hideSelector).forEach(e => (e.style.display = ""));
            fn.remove("#overflowYHidden");
            FullPictureLoadShadowGallery?.remove();
            isOpenGallery = false;
            if (isCaptureMode && ge("#FullPictureLoadCaptureNum")?.innerText == 0) {
                ge("#FullPictureLoadCaptureNum").innerText = srcs.length;
            }
            if ("focus" in siteData) {
                let selector = siteData.focus;
                let ele;
                if (isString(selector)) {
                    if (selector.startsWith("last:")) {
                        selector = selector.slice(5);
                        ele = fn.gae(selector).at(-1);
                    } else {
                        ele = ge(selector);
                    }
                } else if (isFn(selector)) {
                    ele = selector();
                }
                if (!isEle(ele)) return;
                setTimeout(() => instantScrollIntoView(ele), 100);
            }
            if (("closeAF" in siteData) && isFn(siteData.closeAF)) {
                siteData.closeAF();
            }
        };

        const toggleWidthEvent = (event) => {
            if (!isOpenFancybox && config.ViewMode == 4 && (event.ctrlKey || event.altKey || event.shiftKey)) {
                event.preventDefault();
                event.stopPropagation();
                if (event.deltaY < 0) {
                    increaseWidth();
                }
                if (event.deltaY > 0) {
                    reduceWidth();
                }
            }
        };

        FullPictureLoadShadowGallery.addEventListener("wheel", toggleWidthEvent, {
            passive: false
        });

        const getNextRowElement = () => {
            const eles = gae("img,#next", shadow);
            const index = Number(currentReferenceElement.dataset.index);
            if (index >= eles.length - 1) {
                imgViewIndex = index;
                return eles.at(-1);
            }
            for (let i = index + 1; i < eles.length; i++) {
                if (eles[i].offsetTop > currentReferenceElement.offsetTop) {
                    currentReferenceElement = eles[i];
                    imgViewIndex = i;
                    return eles[i];
                }
            }
            imgViewIndex = eles.length - 1;
            return eles.at(-1);
        };

        const getPrevRowElement = () => {
            const eles = gae("img,#next", shadow);
            const index = Number(currentReferenceElement.dataset.index);
            if (index <= 0) {
                imgViewIndex = 0;
                return eles.at(0);
            }
            for (let i = index - 1; i >= 0; i--) {
                if (eles[i].offsetTop < currentReferenceElement.offsetTop) {
                    currentReferenceElement = eles[i];
                    imgViewIndex = i;
                    return eles[i];
                }
            }
            imgViewIndex = 0;
            return eles.at(0);
        };

        const toggleImage = (event) => {
            if (!isOpenFancybox && [0, 1, 3].some(m => config.ViewMode == m) && [1, 2].some(m => config.shadowGalleryWheel == m) && !event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
                event.preventDefault();
                event.stopPropagation();
                const imgs = gae("img", shadow);
                const next = ge("#next", shadow);
                if (config.shadowGalleryWheel == 1) {
                    if (event.deltaY < 0 && imgViewIndex < 0) {
                        nextButtonIsShown = false;
                        imgViewIndex = imgs.length - 1;
                        imgs[imgViewIndex].style.border = "solid #32a1ce";
                        return instantScrollIntoView(imgs[imgViewIndex]);
                    } else if (event.deltaY < 0 && imgViewIndex >= 0) {
                        nextButtonIsShown = false;
                        imgViewIndex--;
                        if (imgViewIndex < 0) imgViewIndex = imgs.length - 1;
                        if (config.ViewMode != 4) {
                            imgs.forEach(e => (e.style.border = ""));
                            if (imgs[imgViewIndex] !== undefined) {
                                imgs[imgViewIndex].style.border = "solid #32a1ce";
                            }
                        }
                        return instantScrollIntoView(imgs[imgViewIndex]);
                    } else if (event.deltaY > 0 && nextButtonIsShown) {
                        next.style.backgroundColor = "gray";
                        return setTimeout(() => (location.href = nextLink), 500);
                    } else if (event.deltaY > 0 && imgViewIndex <= imgs.length - 1) {
                        imgViewIndex++;
                        if (imgs[imgViewIndex] === undefined && next && !nextButtonIsShown) {
                            nextButtonIsShown = true;
                            next.style.border = "solid #32a1ce";
                            return instantScrollIntoView(next);
                        } else if (imgs[imgViewIndex] === undefined) {
                            imgViewIndex = 0;
                        }
                        if (config.ViewMode != 4) {
                            imgs.forEach(e => (e.style.border = ""));
                            if (imgs[imgViewIndex] !== undefined) {
                                imgs[imgViewIndex].style.border = "solid #32a1ce";
                            }
                        }
                        if (imgs[imgViewIndex] !== undefined) {
                            return instantScrollIntoView(imgs[imgViewIndex]);
                        }
                    } else {
                        imgViewIndex = -1;
                    }
                }
                if (config.shadowGalleryWheel == 2) {
                    if (event.deltaY < 0) {
                        nextButtonIsShown = false;
                        if (Number(currentReferenceElement?.dataset?.index) <= 0) return;
                        imgs.forEach(e => (e.style.border = ""));
                        return instantScrollIntoView(getPrevRowElement());
                    }
                    if (event.deltaY > 0) {
                        if (Number(currentReferenceElement?.dataset?.index) >= totalNumberOfElements - 1) return;
                        imgs.forEach(e => (e.style.border = ""));
                        return instantScrollIntoView(getNextRowElement());
                    }
                }
            }
        };

        FullPictureLoadShadowGallery.addEventListener("wheel", toggleImage, {
            passive: false
        });

        const aspectRatio = () => {
            const verticalScreen = _unsafeWindow.innerHeight / _unsafeWindow.innerWidth > 1;
            const imgs = gae("img", shadow);
            imgs.forEach(img => {
                if (verticalScreen && img.className === "default") {
                    img.style.maxWidth = "96vw";
                    img.style.maxHeight = "";
                    img.style.minWidth = "96vw";
                    img.style.minHeight = "";
                } else if (img.className === "default") {
                    img.style.maxHeight = "calc(100vh - 6px)";
                    img.style.maxWidth = "100%";
                    img.style.minHeight = "calc(100vh - 6px)";
                    img.style.minWidth = "";
                }
            });
            if (imgs[imgViewIndex] !== undefined && config.ViewMode != 4) {
                imgs.forEach(e => (e.style.border = ""));
                imgs[imgViewIndex].style.border = "solid #32a1ce";
                setTimeout(() => instantScrollIntoView(imgs[imgViewIndex]), 100);
            }
        };
        _unsafeWindow.addEventListener("resize", aspectRatio);

        const kEvent = (event) => {
            if (isOpenFancybox || ["F11", "F12"].some(k => event.code === k || event.key === k)) return;
            const imgs = gae("img", shadow);
            const next = ge("#next", shadow);
            if (event.code === "Escape" || event.key === "Escape") return closeGallery();
            if (event.code === "Numpad0" || event.code === "Digit0" || event.key === "0") return defaultImageLayout();
            if (event.code === "Numpad1" || event.code === "Digit1" || event.key === "1") return singleImageLayout();
            if (event.code === "Numpad2" || event.code === "Digit2" || event.key === "2") return smallImageLayout();
            if (event.code === "Numpad3" || event.code === "Digit3" || event.key === "3") return rtlImageLayout();
            if (event.code === "Numpad4" || event.code === "Digit4" || event.key === "4") return webtoonImageLayout();
            if ((event.code === "Home" || event.key === "Home") || (event.code === "End" || event.key === "End")) {
                event.preventDefault();
                nextButtonIsShown = false;
                dNum = 0;
                if (event.code === "Home" || event.key === "Home") {
                    imgViewIndex = 0;
                } else {
                    imgViewIndex = imgs.length - 1;
                }
                const img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    img.style.border = "solid #32a1ce";
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            }
            if (event.code === "KeyN" || event.key === "n" || event.key === "N") {
                if (next) {
                    next.style.backgroundColor = "gray";
                    return (location.href = nextLink);
                }
            }
            if ((["Space", "PageDown"].some(k => event.code === k) || [" ", "PageDown"].some(k => event.key === k)) && nextButtonIsShown) {
                dNum++;
                if (dNum > 2) {
                    next.style.backgroundColor = "gray";
                    return (location.href = nextLink);
                }
            }
            if (event.code === "KeyJ" || event.key === "j" || event.key === "J") {
                let num;
                if (config.jumpNum == 0) {
                    if (_unsafeWindow.devicePixelRatio > 1 && [0, 1, 3].some(m => config.ViewMode == m)) {
                        num = mainElement.scrollTop + imgs[0].offsetHeight;
                    } else {
                        num = mainElement.scrollTop + _unsafeWindow.innerHeight;
                    }
                } else {
                    num = mainElement.scrollTop + Number(config.jumpNum);
                }
                let lastTop = mainElement.scrollHeight - _unsafeWindow.innerHeight;
                if (num >= lastTop) {
                    num = lastTop;
                }
                return mainElement.scrollTo({
                    top: num,
                    behavior: config.behavior
                });
            }
            if (event.code === "KeyK" || event.key === "k" || event.key === "K") {
                let num;
                if (config.jumpNum == 0) {
                    if (_unsafeWindow.devicePixelRatio > 1 && [0, 1, 3].some(m => config.ViewMode == m)) {
                        num = mainElement.scrollTop - imgs[0].offsetHeight;
                    } else {
                        num = mainElement.scrollTop - _unsafeWindow.innerHeight;
                    }
                } else {
                    num = mainElement.scrollTop - Number(config.jumpNum);
                }
                if (num <= 0) {
                    num = 0;
                }
                return mainElement.scrollTo({
                    top: num,
                    behavior: config.behavior
                });
            }
            if (config.ViewMode == 4 && (["NumpadAdd", "Equal"].some(k => event.code === k) || ["+", "="].some(k => event.code === k))) {
                return increaseWidth();
            }
            if (config.ViewMode == 4 && (["NumpadSubtract", "Minus"].some(k => event.code === k) || ["-", "_"].some(k => event.key === k))) {
                return reduceWidth();
            }
            if ((event.code === "KeyR" || event.key === "r" || event.key === "R") && [0, 2, 3].some(m => config.ViewMode == m)) {
                let box = ge("#imgBox", shadow);
                if (box.style.direction == "rtl") {
                    return (box.style.direction = "ltr");
                } else {
                    return (box.style.direction = "rtl");
                }
            }
            if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex < 0) {
                if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
                event.preventDefault();
                nextButtonIsShown = false;
                imgViewIndex = imgs.length - 1;
                const img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    img.style.border = "solid #32a1ce";
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex >= 0) {
                if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
                event.preventDefault();
                nextButtonIsShown = false;
                imgViewIndex--;
                let img = imgs[imgViewIndex];
                if (img === undefined) {
                    imgViewIndex = imgs.length - 1;
                    img = imgs[imgViewIndex];
                }
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (img !== undefined) {
                        img.style.border = "solid #32a1ce";
                    }
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((["KeyS", "KeyD", "ArrowDown", "ArrowRight"].some(k => event.code === k) || ["s", "S", "d", "D", "ArrowDown", "ArrowRight"].some(k => event.key === k)) && nextButtonIsShown) {
                if (config.ViewMode == 4 && (event.code === "ArrowDown" || event.key === "ArrowDown")) return;
                next.style.backgroundColor = "gray";
                return setTimeout(() => (location.href = nextLink), 500);
            } else if ((["KeyS", "KeyD", "ArrowDown", "ArrowRight"].some(k => event.code === k) || ["s", "S", "d", "D", "ArrowDown", "ArrowRight"].some(k => event.key === k)) && imgViewIndex <= imgs.length - 1) {
                if (config.ViewMode == 4 && (event.code === "ArrowDown" || event.key === "ArrowDown")) return;
                event.preventDefault();
                imgViewIndex++;
                let img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (img !== undefined) {
                        img.style.border = "solid #32a1ce";
                    }
                }
                if (img === undefined && next && !nextButtonIsShown) {
                    nextButtonIsShown = true;
                    next.style.border = "solid #32a1ce";
                    currentReferenceElement = next;
                    return instantScrollIntoView(next);
                } else if (img === undefined) {
                    imgViewIndex = 0;
                    img = imgs[imgViewIndex];
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((event.code === "Delete" || event.key === "Delete")) {
                const hideE = gae("img", shadow)[imgViewIndex];
                if (hideE !== undefined) {
                    hideE.style.display = "none";
                }
            } else if ((event.code === "Enter" || event.key === "Enter")) {
                gae("img", shadow).forEach(e => (e.style.display = ""));
            } else if (!["KeyR", "NumpadAdd", "Equal", "NumpadSubtract", "Minus"].some(k => event.code === k) || !["r", "R", "-", "+", "=", "_"].some(k => event.key === k)) {
                imgViewIndex = -1;
            }
        };
        _unsafeWindow.addEventListener("keydown", kEvent);
        //選單淡入淡出
        //transform: translate(0);
        //transition: all .8s ease-in-out;
        //    &:hover {
        //        transform: translate(138px);
        //        transition: all .2s ease-in-out;
        //    }
        fn.css(`
html,body {
    overflow-y: hidden !important;
}
        `, "overflowYHidden");

        const style = createStyle(`
p#imgBox {
    display: block;
    min-height: calc(100vh - 70px);
    padding: 0;
    margin: 0;
}
#FixedMenu {
    text-align: center;
    font-family: Arial, sans-serif;
    font-size: 14px;
    color: #000000;
    width: 132px;
    height: auto;
    padding: 5px 5px 2px 5px;
    position: fixed;
    left: -138px;
    bottom: 0px;
    border: #ccc 1px solid;
    border-radius: 3px;
    background-color: #fff;
    z-index: 2147483647;
    &:hover {
        left: 0px;
    }
}
.FixedMenuitem {
    width: 120px;
    height: 24px;
    line-height: 24px;
    overflow: hidden;
    font-size: 14px;
    border: #ccc 1px solid;
    background-color: #f6f6f6;
    padding: 0 5px 0 5px;
    margin: 0 2px 3px 0;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
#MenuJumpItem {
    width: 130px;
    padding: 0px;
}
.FixedMenuitem.active {
    color: #fff;
    background: #1790e6;
}
img.default {
    vertical-align: middle;
    width: auto;
    height: auto;
    object-fit: contain;
    border: solid #fff;
    background-color: #fff;
}
img.single {
    width: auto;
    height: auto;
    max-width: calc(100% - 6px);
    max-height: calc(100vh - 6px);
    display: block;
    margin: 0 auto;
    border: solid #fff;
}
img.webtoon {
    width: 100%;
    height: auto;
    max-width: 800px;
    display: block;
    margin: 0 auto;
    border: unset;
}
img.small {
    display: inline-block;
    vertical-align: middle;
    width: auto;
    height: auto;
    max-width: 31.8%;
    max-height: 33vh;
    border: solid #fff;
}
#next {
    display: block;
    text-align: center;
    padding: 10px 0;
    border: solid #fff;
    color: rgb(0, 0, 0);
    background-color: antiquewhite;
    font-size: 26px;
    line-height: 50px;
    height: 50px;
    text-decoration: unset;
    cursor: pointer;
}
#FixedMenu select {
    text-align: center;
    background-color: #f6f6f6;
    border: none;
    width: 100%;
    height: 100%;
    padding: 0 auto;
}
#FixedMenu select option {
    text-align: center;
}
#behaviorInput {
    vertical-align: middle;
    width: 16px;
    height: 16px;
    margin-top: ${isFirefox ? "2px" : "0px"};
}
        `);
        shadow.appendChild(style);

        const mainElement = document.createElement("div");
        mainElement.id = "shadowGallery";
        mainElement.tabIndex = "-1";

        Object.assign(mainElement.style, {
            left: "0",
            right: "0",
            top: "0",
            bottom: "0",
            width: "100vw",
            height: "100vh",
            margin: "auto",
            padding: "0",
            position: "fixed",
            opacity: "1",
            zIndex: "2147483647",
            backgroundColor: "#333",
            color: "#222",
            fontSize: "14px",
            overflowY: "scroll",
            overflowX: "hidden",
            textAlign: "center"
        });
        shadow.appendChild(mainElement);

        function loadImgs(imgs) {
            const loadImgList = imgs.map(img => [simpleLoadImg, null, img]);
            const queue = new Queue(Number(config.threading));
            queue.addList(loadImgList);
            queue.run();
        }

        async function createGalleryElement(mode) {
            mainElement.scrollTo({
                top: 0
            });
            mainElement.focus();
            imgViewIndex = -1;
            gae(".FixedMenuitem", shadow).forEach(item => item.classList.remove("active"));
            mainElement.innerHTML = "";
            const imgElements = srcs.map((src, i) => {
                let img = new Image();
                img.className = mode;
                img.dataset.index = i;
                img.dataset.fancybox = "gallery";
                if ("referrerpolicy" in siteData) {
                    img.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                img.src = loading_bak;
                img.dataset.src = src;
                if (thumbnailSrcArray.length > 0) {
                    img.dataset.thumb = thumbnailSrcArray[i];
                } else {
                    img.dataset.thumb = src;
                }
                if (mode === "webtoon") {
                    img.style.maxWidth = webtoonWidth + "px";
                }
                return img;
            });
            const p = document.createElement("p");
            p.id = "imgBox";
            if (config.ViewMode == 3) {
                p.style.direction = "rtl";
            }
            if (siteData.category.includes("comic") && config.ViewMode != 4) {
                if (_unsafeWindow.devicePixelRatio > 1) {
                    p.style.padding = "2px 6% 0";
                } else {
                    p.style.padding = "0 6%";
                }
                p.style.margin = "0 auto";
            } else if (_unsafeWindow.devicePixelRatio > 1) {
                p.style.paddingTop = "1px";
            }
            p.append(...imgElements);
            fragment.append(p);
            mainElement.append(fragment);
            loadImgs(imgElements);
            aspectRatio();
            currentReferenceElement = imgElements.at(0);
            totalNumberOfElements = imgElements.length;
            await fn.wait(() => imgElements.at(-1)?.offsetHeight > 100).then(() => {
                setTimeout(() => {
                    aspectRatio();
                    gae("img", shadow).forEach(img => fn.imagesObserver.observe(img));
                }, 1000);
            });
            if (options.fancybox != 1) {
                imgElements.forEach(img => {
                    img.onclick = (event) => {
                        imgViewIndex = Number(img.dataset.index);
                        currentReferenceElement = event.target;
                        if (config.ViewMode != 4) {
                            if (event?.target?.style?.border === "") {
                                imgElements.forEach(e => (e.style.border = ""));
                                event.target.style.border = "solid #32a1ce";
                            } else {
                                imgElements.forEach(e => (e.style.border = ""));
                            }
                        }
                    }
                });
            }
            if (options.fancybox == 1 && isFn(_unsafeWindow.Fancybox)) {
                _unsafeWindow.Fancybox.bind(mainElement, "[data-fancybox]", {
                    Hash: false,
                    idle: false,
                    showClass: false,
                    hideClass: false,
                    wheel: FancyboxWheel,
                    Images: {
                        Panzoom: {
                            maxScale: 2
                        },
                        zoom: false
                    },
                    Slideshow: {
                        timeout: FancyboxSlideshowTimeoutNum,
                    },
                    Carousel: {
                        transition: FancyboxSlideshowTransition
                    },
                    Thumbs: {
                        showOnStart: false
                    },
                    Toolbar: {
                        display: {
                            left: ["infobar"],
                            middle: ["zoomIn", "zoomOut", "iterateZoom", "toggle1to1", "rotateCCW", "rotateCW", "flipX", "flipY", "fitX", "fitY", "reset"],
                            right: ["slideshow", "fullscreen", "thumbs", "close"]
                        }
                    },
                    on: {
                        done: (fancybox, slide) => {
                            isOpenFancybox = true;
                            let slideIndex = slide.index;
                            let imgs = gae("img", mainElement);
                            imgs.forEach(e => (e.style.border = ""));
                            if (fancybox.isCurrentSlide(slide)) {
                                imgViewIndex = slideIndex;
                                let img = imgs[slideIndex];
                                currentReferenceElement = img;
                                img.style.border = "solid #32a1ce";
                                instantScrollIntoView(img);
                            } else {
                                imgViewIndex = fancybox.getSlide().index;
                                let img = imgs[imgViewIndex];
                                currentReferenceElement = img;
                                img.style.border = "solid #32a1ce";
                                instantScrollIntoView(img);
                            }
                        },
                        close: fancybox => {
                            document.body.classList.remove("hide-scrollbar");
                            let slideIndex = fancybox.getSlide().index;
                            imgViewIndex = slideIndex;
                            let imgs = gae("img", mainElement);
                            imgs.forEach(e => (e.style.border = ""));
                            let img = imgs[imgViewIndex];
                            currentReferenceElement = img;
                            img.style.border = "solid #32a1ce";
                            instantScrollIntoView(img);
                            setTimeout(() => {
                                isOpenFancybox = false;
                            }, 100);
                        }
                    }
                });
            }
            if (isString(nextLink)) {
                totalNumberOfElements = totalNumberOfElements + 1;
                const next = document.createElement("div");
                next.id = "next";
                next.dataset.index = imgElements.length;
                next.innerText = `${siteData.category?.includes("comic") ? displayLanguage.str_143 : displayLanguage.str_144}( N )`;
                mainElement.append(next);
                next.addEventListener("click", () => {
                    next.style.backgroundColor = "gray";
                    return setTimeout(() => (location.href = nextLink), 200);
                });
                if (config.shadowGalleryWheel != 1 && [0, 1, 3].some(m => config.ViewMode == m) || [2, 4].some(m => config.ViewMode == m)) {
                    let isEventAdded = false;
                    const nextObserver = new IntersectionObserver((entries, observer) => {
                        entries.forEach(entry => {
                            if (entry.isIntersecting) {
                                nextButtonIsShown = true;
                                next.style.border = "solid #32a1ce";
                                if (!isEventAdded) {
                                    isEventAdded = true;
                                    FullPictureLoadShadowGallery.addEventListener("wheel", (event) => {
                                        if (isOpenFancybox || event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) return;
                                        if (event.deltaY < 0) {
                                            dNum = 0;
                                            next.style.border = "";
                                            nextButtonIsShown = false;
                                        } else if (event.deltaY > 0 && nextButtonIsShown) {
                                            dNum++;
                                            if (dNum > 2) {
                                                next.style.backgroundColor = "gray";
                                                return setTimeout(() => (location.href = nextLink), 500);
                                            }
                                        }
                                    }, {
                                        passive: true
                                    });
                                }
                            } else {
                                dNum = 0;
                                next.style.border = "";
                                nextButtonIsShown = false;
                            }
                        });
                    }, {
                        threshold: 0.9,
                    });
                    setTimeout(() => {
                        nextObserver.observe(next);
                    }, 1000);
                }
            }
        }

        function addFixedMenu() {
            let menuDiv = document.createElement("div");
            menuDiv.id = "FixedMenu";
            const menuObj = [{
                id: "MenuCancelItem",
                text: displayLanguage.str_142,
                cfn: () => closeGallery()
            }, {
                id: "MenuThreadingItem"
            }, {
                id: "MenuBehaviorItem"
            }, {
                id: "MenuJumpItem",
            }, {
                id: "MenuWebtoonItem",
                text: displayLanguage.galleryMenu.webtoon,
                cfn: () => webtoonImageLayout()
            }, {
                id: "MenuRTLItem",
                text: displayLanguage.galleryMenu.rtl,
                cfn: () => rtlImageLayout()
            }, {
                id: "MenuSmallItem",
                text: displayLanguage.galleryMenu.small,
                cfn: () => smallImageLayout()
            }, {
                id: "MenuSinglePageItem",
                text: displayLanguage.galleryMenu.single,
                cfn: () => singleImageLayout()
            }, {
                id: "MenuDefaultItem",
                text: displayLanguage.galleryMenu.default,
                cfn: () => defaultImageLayout()
            }];
            const createMenu = obj => {
                let item = document.createElement("div");
                item.id = obj.id;
                item.className = "FixedMenuitem";
                if (!!obj.text) item.innerText = obj.text;
                item.oncontextmenu = () => false;
                if (!!obj.cfn) item.addEventListener("click", obj.cfn);
                menuDiv.append(item);
            };
            menuObj.forEach(obj => createMenu(obj));

            let threadingSelect = document.createElement("select");
            for (let i = 1; i <= 32; i++) {
                let option = document.createElement("option");
                option.value = i;
                option.innerText = displayLanguage.str_162 + i;
                threadingSelect.append(option);
            }
            ge("#MenuThreadingItem", menuDiv).append(threadingSelect);

            let jumpSelect = document.createElement("select");
            for (let i = 0; i <= 100; i++) {
                let option = document.createElement("option");
                if (i === 0) {
                    option.value = i;
                    option.innerText = `${displayLanguage.str_150}${displayLanguage.str_152}`;
                } else {
                    option.value = i * 100;
                    option.innerText = `${displayLanguage.str_150}${i * 100}px`;
                }
                jumpSelect.append(option);
            }
            ge("#MenuJumpItem", menuDiv).append(jumpSelect);

            let behaviorDiv = ge("#MenuBehaviorItem", menuDiv);
            let behaviorInput = document.createElement("input");
            behaviorInput.id = "behaviorInput";
            behaviorInput.type = "checkbox";
            behaviorDiv.append(behaviorInput);
            let behaviorLabel = document.createElement("label");
            behaviorLabel.innerText = displayLanguage.str_151;
            behaviorDiv.append(behaviorLabel);

            shadow.append(menuDiv);

            threadingSelect.value = config.threading;
            threadingSelect.addEventListener("change", () => {
                config.threading = Number(threadingSelect.value);
                saveConfig(config);
                mainElement.focus();
            });
            jumpSelect.value = config.jumpNum;
            jumpSelect.addEventListener("change", () => {
                config.jumpNum = jumpSelect.value;
                saveConfig(config);
                mainElement.focus();
            });

            behaviorInput.checked = config.behavior == "smooth" ? true : false;
            behaviorInput.addEventListener("change", () => {
                config.behavior = behaviorInput.checked == true ? "smooth" : "instant";
                saveConfig(config);
                mainElement.focus();
            });
        }
        addFixedMenu();

        function defaultImageLayout() {
            config.ViewMode = 0;
            saveConfig(config);
            createGalleryElement("default");
            ge("#MenuDefaultItem", shadow).classList.add("active");
        }

        function singleImageLayout() {
            config.ViewMode = 1;
            saveConfig(config);
            createGalleryElement("single");
            ge("#MenuSinglePageItem", shadow).classList.add("active");
        }

        function smallImageLayout() {
            config.ViewMode = 2;
            saveConfig(config);
            createGalleryElement("small");
            ge("#MenuSmallItem", shadow).classList.add("active");
        }

        function rtlImageLayout() {
            config.ViewMode = 3;
            saveConfig(config);
            createGalleryElement("default");
            ge("#MenuRTLItem", shadow).classList.add("active");
        }

        function webtoonImageLayout() {
            config.ViewMode = 4;
            saveConfig(config);
            createGalleryElement("webtoon");
            ge("#MenuWebtoonItem", shadow).classList.add("active");
        }

        if (config.ViewMode == 1) {
            singleImageLayout();
        } else if (config.ViewMode == 2) {
            smallImageLayout();
        } else if (config.ViewMode == 3) {
            rtlImageLayout();
        } else if (config.ViewMode == 4) {
            webtoonImageLayout();
        } else {
            defaultImageLayout();
        }

    };

    //創建框架畫廊
    const createIframeGallery = async () => {

        if (checkGeting() || hasTouchEvent || isOpenGallery || isOpenOptionsUI) return;

        isOpenGallery = true;

        let srcs;
        if ("SPA" in siteData) {
            let selector = siteData.capture ?? siteData.imgs;
            srcs = await getImgs(selector);
        } else if (!("capture" in siteData)) {
            globalImgArray.length > 0 ? srcs = globalImgArray : srcs = await getImgs(siteData.imgs);
        } else {
            captureSrcArray.length > 0 ? srcs = captureSrcArray : srcs = await getImgs(siteData.imgs);
        }
        if (srcs.length < 1) return (isOpenGallery = false);

        fn.hideMsg();

        const config = getConfig();
        let webtoonWidth = config.webtoonWidth;
        let totalNumberOfElements = 0;
        let imgViewIndex = -1;
        let currentReferenceElement;
        let nextButtonIsShown = false;
        let dNum = 0;

        const iframe = document.createElement("iframe");
        iframe.id = "FullPictureLoadIframeGallery";
        Object.assign(iframe.style, {
            left: "0",
            right: "0",
            top: "0",
            bottom: "0",
            width: "100vw",
            height: "100vh",
            minWidth: "100vw",
            minHeight: "100vh",
            maxWidth: "100vw",
            maxHeight: "100vh",
            margin: "auto",
            padding: "0",
            position: "fixed",
            opacity: "1",
            zIndex: "2147483646",
            backgroundColor: "#333",
            color: "#222"
        });
        document.body.append(iframe);

        await new Promise((resolve) => {
            iframe.onload = resolve;
            iframe.src = "about:blank";
        });

        const win = iframe.contentWindow;
        const dom = iframe.contentDocument;

        _GM_addElement(dom.body, "script", {
            textContent: FancyboxV5JS
        });
        _GM_addElement(dom.head, "style", {
            textContent: FancyboxV5Css + `
.fancybox__container {
    z-index: 2147483647 !important;
}
            `
        });

        const hideSelector = "body>*:not(script,[id^=Full],[class^=Full],#comicRead,#toast,#fab,#ehvp-base,[id^='pagetual'],[class^='pagetual'],[id^='pv-'],[class^='pv-gallery'],[id^=Autopage])";
        gae(hideSelector).forEach(e => (e.style.display = "none"));

        const increaseWidth = () => {
            let imgs = gae("img", mainElement);
            if (webtoonWidth < 1900 && webtoonWidth < win.innerWidth) {
                webtoonWidth = (Number(webtoonWidth) + 50);
                config.webtoonWidth = webtoonWidth;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
            } else {
                webtoonWidth = 800;
                config.webtoonWidth = 800;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = "800px"));
            }
        };

        const reduceWidth = () => {
            let imgs = gae("img", mainElement);
            if (webtoonWidth > 100) {
                webtoonWidth = (Number(webtoonWidth) - 50);
                config.webtoonWidth = webtoonWidth;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = webtoonWidth + "px"));
            } else {
                webtoonWidth = 800;
                config.webtoonWidth = 800;
                saveConfig(config);
                imgs.forEach(e => (e.style.maxWidth = "800px"));
            }
        };

        const closeGallery = () => {
            if (ge("meta[property='og:site_name'][content=禁漫天堂]")) {
                _unsafeWindow.removeEventListener("keydown", kEvent);
            }
            _unsafeWindow.removeEventListener("resize", aspectRatio);
            gae(hideSelector).forEach(e => (e.style.display = ""));
            fn.remove("#overflowYHidden");
            iframe.remove();
            isOpenGallery = false;
            if (isCaptureMode && ge("#FullPictureLoadCaptureNum")?.innerText == 0) {
                ge("#FullPictureLoadCaptureNum").innerText = srcs.length;
            }
            if ("focus" in siteData) {
                let selector = siteData.focus;
                let ele;
                if (isString(selector)) {
                    if (selector.startsWith("last:")) {
                        selector = selector.slice(5);
                        ele = fn.gae(selector).at(-1);
                    } else {
                        ele = ge(selector);
                    }
                } else if (isFn(selector)) {
                    ele = selector();
                }
                if (!isEle(ele)) return;
                setTimeout(() => instantScrollIntoView(ele), 100);
            }
            if (("closeAF" in siteData) && isFn(siteData.closeAF)) {
                siteData.closeAF();
            }
        };

        const toggleWidthEvent = (event) => {
            if (!isOpenFancybox && config.ViewMode == 4 && (event.ctrlKey || event.altKey || event.shiftKey)) {
                event.preventDefault();
                event.stopPropagation();
                if (event.deltaY < 0) {
                    increaseWidth();
                }
                if (event.deltaY > 0) {
                    reduceWidth();
                }
            }
        };

        dom.addEventListener("wheel", toggleWidthEvent, {
            passive: false
        });

        const getNextRowElement = () => {
            const eles = gae("img,#next", mainElement);
            const index = Number(currentReferenceElement.dataset.index);
            if (index >= eles.length - 1) {
                imgViewIndex = index;
                return eles.at(-1);
            }
            for (let i = index + 1; i < eles.length; i++) {
                if (eles[i].offsetTop > currentReferenceElement.offsetTop) {
                    currentReferenceElement = eles[i];
                    imgViewIndex = i;
                    return eles[i];
                }
            }
            imgViewIndex = eles.length - 1;
            return eles.at(-1);
        };

        const getPrevRowElement = () => {
            const eles = gae("img,#next", mainElement);
            const index = Number(currentReferenceElement.dataset.index);
            if (index <= 0) {
                imgViewIndex = 0;
                return eles.at(0);
            }
            for (let i = index - 1; i >= 0; i--) {
                if (eles[i].offsetTop < currentReferenceElement.offsetTop) {
                    currentReferenceElement = eles[i];
                    imgViewIndex = i;
                    return eles[i];
                }
            }
            imgViewIndex = 0;
            return eles.at(0);
        };

        const toggleImage = (event) => {
            if (!isOpenFancybox && [0, 1, 3].some(m => config.ViewMode == m) && [1, 2].some(m => config.shadowGalleryWheel == m) && !event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
                event.preventDefault();
                event.stopPropagation();
                const imgs = gae("img", mainElement);
                const next = ge("#next", mainElement);
                if (config.shadowGalleryWheel == 1) {
                    if (event.deltaY < 0 && imgViewIndex < 0) {
                        nextButtonIsShown = false;
                        imgViewIndex = imgs.length - 1;
                        imgs[imgViewIndex].style.border = "solid #32a1ce";
                        return instantScrollIntoView(imgs[imgViewIndex]);
                    } else if (event.deltaY < 0 && imgViewIndex >= 0) {
                        nextButtonIsShown = false;
                        imgViewIndex--;
                        if (imgViewIndex < 0) imgViewIndex = imgs.length - 1;
                        if (config.ViewMode != 4) {
                            imgs.forEach(e => (e.style.border = ""));
                            if (imgs[imgViewIndex] !== undefined) {
                                imgs[imgViewIndex].style.border = "solid #32a1ce";
                            }
                        }
                        return instantScrollIntoView(imgs[imgViewIndex]);
                    } else if (event.deltaY > 0 && nextButtonIsShown) {
                        next.style.backgroundColor = "gray";
                        return setTimeout(() => (location.href = nextLink), 500);
                    } else if (event.deltaY > 0 && imgViewIndex <= imgs.length - 1) {
                        imgViewIndex++;
                        if (imgs[imgViewIndex] === undefined && next && !nextButtonIsShown) {
                            nextButtonIsShown = true;
                            next.style.border = "solid #32a1ce";
                            return instantScrollIntoView(next);
                        } else if (imgs[imgViewIndex] === undefined) {
                            imgViewIndex = 0;
                        }
                        if (config.ViewMode != 4) {
                            imgs.forEach(e => (e.style.border = ""));
                            if (imgs[imgViewIndex] !== undefined) {
                                imgs[imgViewIndex].style.border = "solid #32a1ce";
                            }
                        }
                        if (imgs[imgViewIndex] !== undefined) {
                            return instantScrollIntoView(imgs[imgViewIndex]);
                        }
                    } else {
                        imgViewIndex = -1;
                    }
                }
                if (config.shadowGalleryWheel == 2) {
                    if (event.deltaY < 0) {
                        nextButtonIsShown = false;
                        if (Number(currentReferenceElement?.dataset?.index) <= 0) return;
                        imgs.forEach(e => (e.style.border = ""));
                        return instantScrollIntoView(getPrevRowElement());
                    }
                    if (event.deltaY > 0) {
                        if (Number(currentReferenceElement?.dataset?.index) >= totalNumberOfElements - 1) return;
                        imgs.forEach(e => (e.style.border = ""));
                        return instantScrollIntoView(getNextRowElement());
                    }
                }
            }
        };

        dom.addEventListener("wheel", toggleImage, {
            passive: false
        });

        const aspectRatio = () => {
            const verticalScreen = win.innerHeight / win.innerWidth > 1;
            const imgs = gae("img", mainElement);
            imgs.forEach(img => {
                if (verticalScreen && img.className === "default") {
                    img.style.maxWidth = "96vw";
                    img.style.maxHeight = "";
                    img.style.minWidth = "96vw";
                    img.style.minHeight = "";
                } else if (img.className === "default") {
                    img.style.maxHeight = "calc(100vh - 6px)";
                    img.style.maxWidth = "100%";
                    img.style.minHeight = "calc(100vh - 6px)";
                    img.style.minWidth = "";
                }
            });
            if (imgs[imgViewIndex] !== undefined && config.ViewMode != 4) {
                imgs.forEach(e => (e.style.border = ""));
                imgs[imgViewIndex].style.border = "solid #32a1ce";
                setTimeout(() => instantScrollIntoView(imgs[imgViewIndex]), 100);
            }
        };
        _unsafeWindow.addEventListener("resize", aspectRatio);

        const kEvent = (event) => {
            if (isOpenFancybox || ["F11", "F12"].some(k => event.code === k || event.key === k)) return;
            const imgs = gae("img", mainElement);
            const next = ge("#next", mainElement);
            if (event.code === "Escape" || event.key === "Escape") return closeGallery();
            if (event.code === "Numpad0" || event.code === "Digit0" || event.key === "0") return defaultImageLayout();
            if (event.code === "Numpad1" || event.code === "Digit1" || event.key === "1") return singleImageLayout();
            if (event.code === "Numpad2" || event.code === "Digit2" || event.key === "2") return smallImageLayout();
            if (event.code === "Numpad3" || event.code === "Digit3" || event.key === "3") return rtlImageLayout();
            if (event.code === "Numpad4" || event.code === "Digit4" || event.key === "4") return webtoonImageLayout();
            if ((event.code === "Home" || event.key === "Home") || (event.code === "End" || event.key === "End")) {
                event.preventDefault();
                nextButtonIsShown = false;
                dNum = 0;
                if (event.code === "Home" || event.key === "Home") {
                    imgViewIndex = 0;
                } else {
                    imgViewIndex = imgs.length - 1;
                }
                const img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    img.style.border = "solid #32a1ce";
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            }
            if (event.code === "KeyN" || event.key === "n" || event.key === "N") {
                if (next) {
                    next.style.backgroundColor = "gray";
                    return (location.href = nextLink);
                }
            }
            if ((["Space", "PageDown"].some(k => event.code === k) || [" ", "PageDown"].some(k => event.key === k)) && nextButtonIsShown) {
                dNum++;
                if (dNum > 2) {
                    next.style.backgroundColor = "gray";
                    return (location.href = nextLink);
                }
            }
            if (event.code === "KeyJ" || event.key === "j" || event.key === "J") {
                let num;
                if (config.jumpNum == 0) {
                    if (_unsafeWindow.devicePixelRatio > 1 && [0, 1, 3].some(m => config.ViewMode == m)) {
                        num = mainElement.scrollTop + imgs[0].offsetHeight;
                    } else {
                        num = mainElement.scrollTop + win.innerHeight;
                    }
                } else {
                    num = mainElement.scrollTop + Number(config.jumpNum);
                }
                let lastTop = mainElement.scrollHeight - win.innerHeight;
                if (num >= lastTop) {
                    num = lastTop;
                }
                return mainElement.scrollTo({
                    top: num,
                    behavior: config.behavior
                });
            }
            if (event.code === "KeyK" || event.key === "k" || event.key === "K") {
                let num;
                if (config.jumpNum == 0) {
                    if (_unsafeWindow.devicePixelRatio > 1 && [0, 1, 3].some(m => config.ViewMode == m)) {
                        num = mainElement.scrollTop - imgs[0].offsetHeight;
                    } else {
                        num = mainElement.scrollTop - win.innerHeight;
                    }
                } else {
                    num = mainElement.scrollTop - Number(config.jumpNum);
                }
                if (num <= 0) {
                    num = 0;
                }
                return mainElement.scrollTo({
                    top: num,
                    behavior: config.behavior
                });
            }
            if (config.ViewMode == 4 && (["NumpadAdd", "Equal"].some(k => event.code === k) || ["+", "="].some(k => event.code === k))) {
                return increaseWidth();
            }
            if (config.ViewMode == 4 && (["NumpadSubtract", "Minus"].some(k => event.code === k) || ["-", "_"].some(k => event.key === k))) {
                return reduceWidth();
            }
            if ((event.code === "KeyR" || event.key === "r" || event.key === "R") && [0, 2, 3].some(m => config.ViewMode == m)) {
                let box = ge("#imgBox", mainElement);
                if (box.style.direction == "rtl") {
                    return (box.style.direction = "ltr");
                } else {
                    return (box.style.direction = "rtl");
                }
            }
            if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex < 0) {
                if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
                event.preventDefault();
                nextButtonIsShown = false;
                imgViewIndex = imgs.length - 1;
                const img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    img.style.border = "solid #32a1ce";
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((["KeyW", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.code === k) || ["w", "W", "a", "A", "KeyA", "ArrowUp", "ArrowLeft"].some(k => event.key === k)) && imgViewIndex >= 0) {
                if (config.ViewMode == 4 && (event.code === "ArrowUp" || event.key === "ArrowUp")) return;
                event.preventDefault();
                nextButtonIsShown = false;
                imgViewIndex--;
                let img = imgs[imgViewIndex];
                if (img === undefined) {
                    imgViewIndex = imgs.length - 1;
                    img = imgs[imgViewIndex];
                }
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (img !== undefined) {
                        img.style.border = "solid #32a1ce";
                    }
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((["KeyS", "KeyD", "ArrowDown", "ArrowRight"].some(k => event.code === k) || ["s", "S", "d", "D", "ArrowDown", "ArrowRight"].some(k => event.key === k)) && nextButtonIsShown) {
                if (config.ViewMode == 4 && (event.code === "ArrowDown" || event.key === "ArrowDown")) return;
                next.style.backgroundColor = "gray";
                return setTimeout(() => (location.href = nextLink), 500);
            } else if ((["KeyS", "KeyD", "ArrowDown", "ArrowRight"].some(k => event.code === k) || ["s", "S", "d", "D", "ArrowDown", "ArrowRight"].some(k => event.key === k)) && imgViewIndex <= imgs.length - 1) {
                if (config.ViewMode == 4 && (event.code === "ArrowDown" || event.key === "ArrowDown")) return;
                event.preventDefault();
                imgViewIndex++;
                let img = imgs[imgViewIndex];
                if (config.ViewMode != 4) {
                    imgs.forEach(e => (e.style.border = ""));
                    if (img !== undefined) {
                        img.style.border = "solid #32a1ce";
                    }
                }
                if (img === undefined && next && !nextButtonIsShown) {
                    nextButtonIsShown = true;
                    next.style.border = "solid #32a1ce";
                    currentReferenceElement = next;
                    return instantScrollIntoView(next);
                } else if (img === undefined) {
                    imgViewIndex = 0;
                    img = imgs[imgViewIndex];
                }
                currentReferenceElement = img;
                return instantScrollIntoView(img);
            } else if ((event.code === "Delete" || event.key === "Delete")) {
                const hideE = gae("img", mainElement)[imgViewIndex];
                if (hideE !== undefined) {
                    hideE.style.display = "none";
                }
            } else if ((event.code === "Enter" || event.key === "Enter")) {
                gae("img", mainElement).forEach(e => (e.style.display = ""));
            } else if (!["KeyR", "NumpadAdd", "Equal", "NumpadSubtract", "Minus"].some(k => event.code === k) || !["r", "R", "-", "+", "=", "_"].some(k => event.key === k)) {
                imgViewIndex = -1;
            }
        };
        if (ge("meta[property='og:site_name'][content=禁漫天堂]")) {
            _unsafeWindow.addEventListener("keydown", kEvent);
        } else {
            dom.addEventListener("keydown", kEvent);
        }

        fn.css(`
html,body {
    overflow-y: hidden !important;
}
        `, "overflowYHidden");
        _GM_addElement(dom.head, "style", {
            textContent: `
p#imgBox {
    display: block;
    min-height: calc(100vh - 70px);
    padding: 0;
    margin: 0;
}
#FixedMenu {
    text-align: center;
    font-family: Arial, sans-serif;
    font-size: 14px;
    color: #000000;
    width: 132px;
    height: auto;
    padding: 5px 5px 2px 5px;
    position: fixed;
    left: -138px;
    bottom: 0px;
    border: #ccc 1px solid;
    border-radius: 3px;
    background-color: #fff;
    z-index: 2147483647;
    &:hover {
        left: 0px;
    }
}
.FixedMenuitem {
    width: 120px;
    height: 24px;
    line-height: 24px;
    overflow: hidden;
    font-size: 14px;
    border: #ccc 1px solid;
    background-color: #f6f6f6;
    padding: 0 5px 0 5px;
    margin: 0 2px 3px 0;
    cursor: pointer;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
#MenuJumpItem {
    width: 130px;
    padding: 0px;
}
.FixedMenuitem.active {
    color: #fff;
    background: #1790e6;
}
img.default {
    vertical-align: middle;
    width: auto;
    height: auto;
    object-fit: contain;
    border: solid #fff;
    background-color: #fff;
}
img.single {
    width: auto;
    height: auto;
    max-width: calc(100% - 6px);
    max-height: calc(100vh - 6px);
    display: block;
    margin: 0 auto;
    border: solid #fff;
}
img.webtoon {
    width: 100%;
    height: auto;
    max-width: 800px;
    display: block;
    margin: 0 auto;
    border: unset;
}
img.small {
    display: inline-block;
    vertical-align: middle;
    width: auto;
    height: auto;
    max-width: 31.8%;
    max-height: 33vh;
    border: solid #fff;
}
#next {
    display: block;
    text-align: center;
    padding: 10px 0;
    border: solid #fff;
    color: rgb(0, 0, 0);
    background-color: antiquewhite;
    font-size: 26px;
    line-height: 50px;
    height: 50px;
    text-decoration: unset;
    cursor: pointer;
}
#FixedMenu select {
    text-align: center;
    background-color: #f6f6f6;
    border: none;
    width: 100%;
    height: 100%;
    padding: 0 auto;
}
#FixedMenu select option {
    text-align: center;
}
#behaviorInput {
    vertical-align: middle;
    width: 16px;
    height: 16px;
    margin-top: ${isFirefox ? "2px" : "0px"};
}
                `
        });
        if (_GM_getValue("FancyboxSlideshowTransition") === "no") {
            _GM_addElement(dom.head, "style", {
                textContent: `
.fancybox__container .to-next>.fancybox__content,
.fancybox__container .to-prev>.fancybox__content {
    display: none !important
}
            `
            });
        }
        const mainElement = dom.createElement("div");
        mainElement.id = "iframeGallery";
        mainElement.tabIndex = "-1";

        Object.assign(mainElement.style, {
            left: "0",
            right: "0",
            top: "0",
            bottom: "0",
            width: "100vw",
            height: "100vh",
            margin: "auto",
            padding: "0",
            position: "fixed",
            opacity: "1",
            zIndex: "2147483647",
            backgroundColor: "#333",
            color: "#222",
            fontSize: "14px",
            overflowY: "scroll",
            overflowX: "hidden",
            textAlign: "center"
        });
        dom.body.appendChild(mainElement);

        function loadImgs(imgs) {
            const loadImgList = imgs.map(img => [simpleLoadImg, null, img]);
            const queue = new Queue(Number(config.threading));
            queue.addList(loadImgList);
            queue.run();
        }

        async function createGalleryElement(mode) {
            mainElement.scrollTo({
                top: 0
            });
            mainElement.focus();
            imgViewIndex = -1;
            gae(".FixedMenuitem", dom).forEach(item => item.classList.remove("active"));
            mainElement.innerHTML = "";
            const imgElements = srcs.map((src, i) => {
                let img = new Image();
                img.className = mode;
                img.dataset.index = i;
                img.dataset.fancybox = "gallery";
                if ("referrerpolicy" in siteData) {
                    img.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                img.src = loading_bak;
                img.dataset.src = src;
                if (thumbnailSrcArray.length > 0) {
                    img.dataset.thumb = thumbnailSrcArray[i];
                } else {
                    img.dataset.thumb = src;
                }
                if (mode === "webtoon") {
                    img.style.maxWidth = webtoonWidth + "px";
                }
                return img;
            });
            const p = document.createElement("p");
            p.id = "imgBox";
            if (config.ViewMode == 3) {
                p.style.direction = "rtl";
            }
            if (siteData.category.includes("comic") && config.ViewMode != 4) {
                if (_unsafeWindow.devicePixelRatio > 1) {
                    p.style.padding = "2px 6% 0";
                } else {
                    p.style.padding = "0 6%";
                }
                p.style.margin = "0 auto";
            } else if (_unsafeWindow.devicePixelRatio > 1) {
                p.style.paddingTop = "1px";
            }
            p.append(...imgElements);
            fragment.append(p);
            mainElement.append(fragment);
            loadImgs(imgElements);
            aspectRatio();
            currentReferenceElement = imgElements.at(0);
            totalNumberOfElements = imgElements.length;
            await fn.wait(() => imgElements.at(-1)?.offsetHeight > 100).then(() => {
                setTimeout(() => {
                    aspectRatio();
                    gae("img", mainElement).forEach(img => fn.imagesObserver.observe(img));
                }, 1000);
            });
            if (options.fancybox != 1) {
                imgElements.forEach(img => {
                    img.onclick = (event) => {
                        imgViewIndex = Number(img.dataset.index);
                        currentReferenceElement = event.target;
                        if (config.ViewMode != 4) {
                            if (event?.target?.style?.border === "") {
                                imgElements.forEach(e => (e.style.border = ""));
                                event.target.style.border = "solid #32a1ce";
                            } else {
                                imgElements.forEach(e => (e.style.border = ""));
                            }
                        }
                    }
                });
            }
            if (options.fancybox == 1) {
                gae("img", mainElement).forEach(img => {
                    img.addEventListener("click", (event) => {
                        const Fancybox = win.Fancybox;
                        if (Fancyboxl10nV5() != "EN") {
                            Fancybox.defaults.l10n = Fancyboxl10nV5();
                        }
                        const index = Number(event.target.dataset.index);
                        Fancybox.fromNodes(gae("[data-fancybox]", mainElement), {
                            Hash: false,
                            idle: false,
                            showClass: false,
                            hideClass: false,
                            wheel: FancyboxWheel,
                            startIndex: index,
                            Images: {
                                Panzoom: {
                                    maxScale: 2
                                },
                                zoom: false
                            },
                            Slideshow: {
                                timeout: FancyboxSlideshowTimeoutNum,
                            },
                            Carousel: {
                                ...Fancybox.defaults.Carousel,
                                transition: FancyboxSlideshowTransition
                            },
                            Thumbs: {
                                showOnStart: false
                            },
                            Toolbar: {
                                display: {
                                    left: ["infobar"],
                                    middle: ["zoomIn", "zoomOut", "iterateZoom", "toggle1to1", "rotateCCW", "rotateCW", "flipX", "flipY", "fitX", "fitY", "reset"],
                                    right: ["slideshow", "fullscreen", "thumbs", "close"]
                                }
                            },
                            on: {
                                done: (fancybox, slide) => {
                                    isOpenFancybox = true;
                                    let slideIndex = slide.index;
                                    let imgs = gae("img", mainElement);
                                    imgs.forEach(e => (e.style.border = ""));
                                    if (fancybox.isCurrentSlide(slide)) {
                                        imgViewIndex = slideIndex;
                                        let img = imgs[imgViewIndex];
                                        currentReferenceElement = img;
                                        img.style.border = "solid #32a1ce";
                                        instantScrollIntoView(img);
                                    } else {
                                        imgViewIndex = fancybox.getSlide().index;
                                        let img = imgs[imgViewIndex];
                                        currentReferenceElement = img;
                                        img.style.border = "solid #32a1ce";
                                        instantScrollIntoView(img);
                                    }
                                },
                                close: fancybox => {
                                    let slideIndex = fancybox.getSlide().index;
                                    imgViewIndex = slideIndex;
                                    let imgs = gae("img", mainElement);
                                    imgs.forEach(e => (e.style.border = ""));
                                    let img = imgs[imgViewIndex];
                                    currentReferenceElement = img;
                                    img.style.border = "solid #32a1ce";
                                    instantScrollIntoView(img);
                                    setTimeout(() => {
                                        isOpenFancybox = false;
                                    }, 100);
                                }
                            }
                        });
                    });
                });
            }
            if (isString(nextLink)) {
                totalNumberOfElements = totalNumberOfElements + 1;
                const next = document.createElement("div");
                next.id = "next";
                next.dataset.index = imgElements.length;
                next.innerText = `${siteData.category?.includes("comic") ? displayLanguage.str_143 : displayLanguage.str_144}( N )`;
                mainElement.append(next);
                next.addEventListener("click", () => {
                    next.style.backgroundColor = "gray";
                    return setTimeout(() => (location.href = nextLink), 200);
                });
                if (config.shadowGalleryWheel != 1) {
                    let isEventAdded = false;
                    const nextObserver = new IntersectionObserver((entries, observer) => {
                        entries.forEach(entry => {
                            if (entry.isIntersecting) {
                                nextButtonIsShown = true;
                                next.style.border = "solid #32a1ce";
                                if (!isEventAdded) {
                                    isEventAdded = true;
                                    dom.addEventListener("wheel", (event) => {
                                        if (isOpenFancybox || event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) return;
                                        if (event.deltaY < 0) {
                                            dNum = 0;
                                            next.style.border = "";
                                            nextButtonIsShown = false;
                                        } else if (event.deltaY > 0 && nextButtonIsShown) {
                                            dNum++;
                                            if (dNum > 2) {
                                                next.style.backgroundColor = "gray";
                                                return setTimeout(() => (location.href = nextLink), 500);
                                            }
                                        }
                                    }, {
                                        passive: true
                                    });
                                }
                            } else {
                                dNum = 0;
                                next.style.border = "";
                                nextButtonIsShown = false;
                            }
                        });
                    }, {
                        threshold: 0.9,
                    });
                    setTimeout(() => {
                        nextObserver.observe(next);
                    }, 1000);
                }
            }
        }

        function addFixedMenu() {
            let menuDiv = document.createElement("div");
            menuDiv.id = "FixedMenu";
            const menuObj = [{
                id: "MenuCancelItem",
                text: displayLanguage.str_142,
                cfn: () => closeGallery()
            }, {
                id: "MenuThreadingItem"
            }, {
                id: "MenuBehaviorItem"
            }, {
                id: "MenuJumpItem",
            }, {
                id: "MenuWebtoonItem",
                text: displayLanguage.galleryMenu.webtoon,
                cfn: () => webtoonImageLayout()
            }, {
                id: "MenuRTLItem",
                text: displayLanguage.galleryMenu.rtl,
                cfn: () => rtlImageLayout()
            }, {
                id: "MenuSmallItem",
                text: displayLanguage.galleryMenu.small,
                cfn: () => smallImageLayout()
            }, {
                id: "MenuSinglePageItem",
                text: displayLanguage.galleryMenu.single,
                cfn: () => singleImageLayout()
            }, {
                id: "MenuDefaultItem",
                text: displayLanguage.galleryMenu.default,
                cfn: () => defaultImageLayout()
            }];
            const createMenu = obj => {
                let item = document.createElement("div");
                item.id = obj.id;
                item.className = "FixedMenuitem";
                if (!!obj.text) item.innerText = obj.text;
                item.oncontextmenu = () => false;
                if (!!obj.cfn) item.addEventListener("click", obj.cfn);
                menuDiv.append(item);
            };
            menuObj.forEach(obj => createMenu(obj));

            let threadingSelect = document.createElement("select");
            for (let i = 1; i <= 32; i++) {
                let option = document.createElement("option");
                option.value = i;
                option.innerText = displayLanguage.str_162 + i;
                threadingSelect.append(option);
            }
            ge("#MenuThreadingItem", menuDiv).append(threadingSelect);

            let jumpSelect = document.createElement("select");
            for (let i = 0; i <= 100; i++) {
                let option = document.createElement("option");
                if (i === 0) {
                    option.value = i;
                    option.innerText = `${displayLanguage.str_150}${displayLanguage.str_152}`;
                } else {
                    option.value = i * 100;
                    option.innerText = `${displayLanguage.str_150}${i * 100}px`;
                }
                jumpSelect.append(option);
            }
            ge("#MenuJumpItem", menuDiv).append(jumpSelect);

            let behaviorDiv = ge("#MenuBehaviorItem", menuDiv);
            let behaviorInput = document.createElement("input");
            behaviorInput.id = "behaviorInput";
            behaviorInput.type = "checkbox";
            behaviorDiv.append(behaviorInput);
            let behaviorLabel = document.createElement("label");
            behaviorLabel.innerText = displayLanguage.str_151;
            behaviorDiv.append(behaviorLabel);

            dom.body.append(menuDiv);

            threadingSelect.value = config.threading;
            threadingSelect.addEventListener("change", () => {
                config.threading = Number(threadingSelect.value);
                saveConfig(config);
                mainElement.focus();
            });
            jumpSelect.value = config.jumpNum;
            jumpSelect.addEventListener("change", () => {
                config.jumpNum = jumpSelect.value;
                saveConfig(config);
                mainElement.focus();
            });

            behaviorInput.checked = config.behavior == "smooth" ? true : false;
            behaviorInput.addEventListener("change", () => {
                config.behavior = behaviorInput.checked == true ? "smooth" : "instant";
                saveConfig(config);
                mainElement.focus();
            });
        }
        addFixedMenu();

        function defaultImageLayout() {
            config.ViewMode = 0;
            saveConfig(config);
            createGalleryElement("default");
            ge("#MenuDefaultItem", dom).classList.add("active");
        }

        function singleImageLayout() {
            config.ViewMode = 1;
            saveConfig(config);
            createGalleryElement("single");
            ge("#MenuSinglePageItem", dom).classList.add("active");
        }

        function smallImageLayout() {
            config.ViewMode = 2;
            saveConfig(config);
            createGalleryElement("small");
            ge("#MenuSmallItem", dom).classList.add("active");
        }

        function rtlImageLayout() {
            config.ViewMode = 3;
            saveConfig(config);
            createGalleryElement("default");
            ge("#MenuRTLItem", dom).classList.add("active");
        }

        function webtoonImageLayout() {
            config.ViewMode = 4;
            saveConfig(config);
            createGalleryElement("webtoon");
            ge("#MenuWebtoonItem", dom).classList.add("active");
        }

        if (config.ViewMode == 1) {
            singleImageLayout();
        } else if (config.ViewMode == 2) {
            smallImageLayout();
        } else if (config.ViewMode == 3) {
            rtlImageLayout();
        } else if (config.ViewMode == 4) {
            webtoonImageLayout();
        } else {
            defaultImageLayout();
        }

    };

    const getFileSize = (src, element = null, label = null) => {
        const config = getConfig();
        return fn.xhrHEAD(src, {
            headers: {
                referer: getReferer(src)
            }
        }).then(res => {
            //console.log(res);
            if (src != res.finalUrl) {
                return getFileSize(res.finalUrl, element);
            }
            const contentLength = res?.responseHeaders?.split("\r\n")?.find(s => s.startsWith("content-length:"));
            //console.log(contentLength);
            if (contentLength) {
                let [num] = contentLength.match(/\d+/);
                if (num.length > 6) {
                    num = (num / 1000000).toFixed(1);
                    if (isEle(element)) {
                        element.innerText = element.innerText + " | Size: " + num + " MB";
                    }
                    return num + " MB";
                } else {
                    num = Math.floor(num / 1000);
                    if (isEle(element)) {
                        element.innerText = element.innerText + " | Size: " + num + " kB";
                    }
                    return num + " kB";
                }
            } else {
                config.noSize = 1;
                saveConfig(config);
                if (isEle(label)) {
                    label.classList.add("line-through");
                }
            }
        });
    };

    //創建篩選下載
    const createFilterDownload = async () => {

        if (checkGeting() || isDragging || isOpenFilter) return;

        isOpenFilter = true;

        let srcs;
        if ("SPA" in siteData) {
            let selector = siteData.capture ?? siteData.imgs;
            srcs = await getImgs(selector);
        } else if (!("capture" in siteData)) {
            globalImgArray.length > 0 ? srcs = globalImgArray : srcs = await getImgs(siteData.imgs);
        } else {
            captureSrcArray.length > 0 ? srcs = captureSrcArray : srcs = await getImgs(siteData.imgs);
        }
        if (srcs.length < 1) return (isOpenFilter = false);

        const config = getConfig();
        let threading = Number(config.threading);
        let backgroundColor = config.backgroundColor;
        let showSize = config.showSize;
        let move = config.move;

        if (!("Viewer" in _unsafeWindow)) {
            _GM_addElement(document.head, "style", {
                textContent: ViewerJsCss
            });
            _GM_addElement(document.head, "script", {
                textContent: ViewerJs
            });
        }
        const mainHtml = '<div id="FullPictureLoadFilterDownload" style="overflow: clip !important;display: initial !important;position: fixed !important;z-index: 2147483640 !important;"></div>';
        document.body.insertAdjacentHTML("beforeend", mainHtml);

        const shadowElement = ge("#FullPictureLoadFilterDownload");
        const shadow = shadowElement.attachShadow({
            mode: "closed"
        });
        fn.css(`
html,body {
    overflow: hidden !important;
}
        `, "overflowYHidden");
        const style = createStyle(`
#main {
    font-size: 14px;
    font-family: Arial, sans-serif;
    text-align: left;
    color: black;
    inset: 0px;
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
    position: fixed;
    opacity: 1;
    z-index: 2147483641;
    background-color: rgb(240, 240, 240);
    overflow: hidden auto;
}
#main.dark {
    color: white;
    background-color: #333;
}
.row {
    display: block;
    margin: 5px;
    padding: 0 0 0 5px;
    border: #000 1px solid;
    border-radius: 5px;
}
.row.dark {
    border: rgb(0, 204, 255) 1px solid;
}
#title {
    display: block;
    margin: 4px auto 0 auto;
}
#buttons {
    display: block;
    margin: 0 auto 4px auto;
}
#label-title,
#close {
    display: inline-block;
    width: 48px;
}
.number {
    display: inline-block;
    margin-top: 4px;
    padding: 0 0 0 2px;
    border-left: #000 1px solid;
}
.number.dark{
    border-left: rgb(0, 204, 255) 1px solid;
}
.close {
    margin: 0 5px;
}
#inputTitle {
    width: calc(100% - 124px);
}
#buttons button {
    margin-top: 4px;
}
button.dark {
    color: #fff;
    border-color: rgb(81 91 105);
    border-style: solid;
    background-color: rgb(81 91 105);
    border-radius: .5rem;
}
#imgBox {
    text-align: center;
}
ul#image-list {
    display: block;
    max-width: 100%;
    margin: ${hasTouchEvent ? "0 0 0 -1px" : "0 0 0 -2px"};
    padding: 4px 0 0 0;
}
li.image-item {
    list-style: none;
    position: relative;
    display: inline-flex;
    width: 200px;
    height: 200px;
    margin: 0 4px 4px 0;
    padding: 0px;
    background-color: #fff;
    border: #000 1px solid;
    border-radius: 2px;
}
li.dark {
    background-color: #333;
    border: rgb(0, 204, 255) 1px solid;
}
img.image {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    margin: 0px auto;
    object-fit: contain;
}
input.check {
    position: absolute;
    top: 2px;
    left: 2px;
}
li p {
    position: absolute;
    font-size: 12px;
    line-height: 14px;
    width: 100%;
    height: 14px;
    top: 186px;
    margin: 0px;
    padding: 0px;
    background-color: rgba(163, 194, 194, 0.8);
}
li p.dark {
    background-color: rgba(82, 82, 122, 0.8);
}
#size,#move {
    width: 16px;
    height: 16px;
    vertical-align: text-top;
    margin: 0 4px;
}
label.line-through:has(>#size) {
    text-decoration: line-through;
}
@media (max-width: 820px) {
    li.image-item {
        width: 194px;
        height: 194px;
    }
    li p {
        top: 180px;
    }
}
@media (max-width: 768px) {
    li.image-item {
        width: 181px;
        height: 181px;
    }
    li p {
        top: 167px;
    }
}
@media (max-width: 712px) {
    li.image-item {
        width: 167px;
        height: 167px;
    }
    li p {
        top: 153px;
    }
}
@media (max-width: 414px) {
    li.image-item {
        width: 192px;
        height: 192px;
    }
    li p {
        top: 178px;
    }
}
@media (max-width: 412px) {
    li.image-item {
        width: 191px;
        height: 191px;
    }
    li p {
        top: 177px;
    }
}
@media (max-width: 400px) {
    li.image-item {
        width: 182px;
        height: 182px;
    }
    li p {
        top: 168px;
    }
}
@media (max-width: 393px) {
    li.image-item {
        width: 182px;
        height: 182px;
    }
    li p {
        top: 168px;
    }
}
@media (max-width: 390px) {
    li.image-item {
        width: 180px;
        height: 180px;
    }
    li p {
        top: 166px;
    }
}
@media (max-width: 375px) {
    li.image-item {
        width: 173px;
        height: 173px;
    }
    li p {
        top: 159px;
    }
}
@media (max-width: 360px) {
    li.image-item {
        width: 165px;
        height: 165px;
    }
    li p {
        top: 151px;
    }
}
@media (max-width: 320px) {
    li.image-item {
        width: 145px;
        height: 145px;
    }
    li p {
        top: 131px;
    }
}
        `);
        shadow.append(style);
        const main = document.createElement("div");
        main.id = "main";
        main.tabIndex = "-1";
        shadow.append(main);

        main.innerHTML = `
<div class="row">
    <div id="title">
        <label id="label-title">${displayLanguage.str_153}</label>
        <input type="text" id="inputTitle">
        <button id="close" class="close">${displayLanguage.str_132}</button>
    </div>
    <div id="buttons">
        <button id="settings">${displayLanguage.str_85.replace(/\(.\)/, "")}</button>
        <button id="gallery">${displayLanguage.str_106.replace(/\(.\)/, "")}</button>
        <button id="favor">${displayLanguage.str_128.replace(/\(.\)/, "")}</button>
        <button id="copy">${displayLanguage.str_105.replace(/\(.\)/, "")}</button>
        <button id="export">${displayLanguage.str_104.replace(/\(.\)/, "")}</button>
        <button id="select-all">${displayLanguage.str_154}</button>
        <button id="unselect-all">${displayLanguage.str_155}</button>
        <button id="reverse-selection">${displayLanguage.str_170}</button>
        <button id="reload">${displayLanguage.str_156}</button>
        <button id="download">${displayLanguage.str_157}</button>
        <label class="number">${displayLanguage.str_169}<select id="backgroundColor"></select></label>
        <label id="label-threading" class="number">${displayLanguage.str_161}<select id="threading"></select></label>
        <label class="number">${displayLanguage.str_167}<select id="width"></select></label>
        <label class="number">${displayLanguage.str_168}<select id="height"></select></label>
        <label class="number">${displayLanguage.str_165 + srcs.length}</label>
        <label id="filterNumber" class="number">${displayLanguage.str_166 + srcs.length}</label>
        <label class="number" title="${displayLanguage.str_173}"><input id="move" type="checkbox"></input>${displayLanguage.str_172}</label>
        <label class="number"><input id="size" type="checkbox"></input>${displayLanguage.str_171}</label>
    </div>
</div>
<div id="imgBox" class="row">
    <ul id="image-list"></ul>
</div>
<div class="row">
    <div id="buttons">
        <button id="settings">${displayLanguage.str_85.replace(/\(.\)/, "")}</button>
        <button id="gallery">${displayLanguage.str_106.replace(/\(.\)/, "")}</button>
        <button id="favor">${displayLanguage.str_128.replace(/\(.\)/, "")}</button>
        <button id="copy">${displayLanguage.str_105.replace(/\(.\)/, "")}</button>
        <button id="export">${displayLanguage.str_104.replace(/\(.\)/, "")}</button>
        <button id="select-all">${displayLanguage.str_154}</button>
        <button id="unselect-all">${displayLanguage.str_155}</button>
        <button id="reverse-selection">${displayLanguage.str_170}</button>
        <button id="reload">${displayLanguage.str_156}</button>
        <button id="download">${displayLanguage.str_157}</button>
        <button id="close">${displayLanguage.str_132}</button>
    </div>
</div>
        `;

        //參考https://syj0905.github.io/drag-drop-demo/
        //還原成原生JavaScript寫法
        const cancelDefault = (event) => {
            event.preventDefault();
            event.stopPropagation();
        };

        const drag_sort_Start = (event) => {
            const dragEle = ["INPUT", "IMG", "P"].some(t => event.target.tagName === t) ? event.target.parentNode : event.target;
            const index = [...dragEle.parentNode.childNodes].indexOf(dragEle);
            event.dataTransfer.setData("text/plain", index);
        };

        const drop_sort = (event) => {
            const oldIndex = event.dataTransfer.getData("text/plain");
            const dropEle = ["INPUT", "IMG", "P"].some(t => event.target.tagName === t) ? event.target.parentNode : event.target;
            const list = dropEle.parentNode;
            const nodes = [...list.childNodes];
            const newIndex = nodes.indexOf(dropEle);
            const dragEle = nodes.at(oldIndex);
            if (newIndex < oldIndex) {
                list.insertBefore(dragEle, dropEle);
            } else if (newIndex > oldIndex) {
                list.insertBefore(dragEle, dropEle.nextSibling);
            }
        };

        if (hasTouchEvent) {
            ge("label:has(>#move)", main).remove();
        }
        if (backgroundColor === "d") {
            gae("#main,.row,.number,button", shadow).forEach(e => e.classList.add("dark"));
        }
        let backgroundSelect = ge("#backgroundColor", main);
        Object.keys(displayLanguage.backgroundColor).forEach((k, i) => {
            const option = document.createElement("option");
            option.value = k;
            option.innerText = displayLanguage.backgroundColor[k];
            fragment.append(option);
        });
        backgroundSelect.append(fragment);
        backgroundSelect.value = config.backgroundColor;
        backgroundSelect.addEventListener("change", () => {
            config.backgroundColor = backgroundSelect.value;
            saveConfig(config);
            backgroundColor = config.backgroundColor;
            if (backgroundColor === "d") {
                gae("#main,.row,.number,li,li p,button", shadow).forEach(e => e.classList.add("dark"));
            } else {
                gae("#main,.row,.number,li,li p,button", shadow).forEach(e => e.classList.remove("dark"));
            }
            main.focus();
        });
        let widthNum = 0;
        let heightNum = 0;
        const changeList = () => {
            gae("img", main).forEach(img => {
                if (!/^(blob|data)/.test(img.src)) {
                    const input = img.previousElementSibling;
                    const parent = img.parentElement;
                    let cw = img.naturalWidth >= widthNum;
                    let ch = img.naturalHeight >= heightNum;
                    if (cw && ch) {
                        input.checked = true;
                        input.classList.add("select");
                        parent.style.display = "";
                    } else {
                        input.checked = false;
                        input.classList.remove("select");
                        parent.style.display = "none";
                    }
                }
            });
        };
        let widthSelect = ge("#width", main);
        for (let i = 0; i <= 40; i++) {
            let option = document.createElement("option");
            option.value = i;
            option.innerText = i == 0 ? "All" : i * 100;
            fragment.append(option);
        }
        widthSelect.append(fragment);
        widthSelect.addEventListener("change", () => {
            widthNum = Number(widthSelect.value) * 100;
            changeList();
            const selects = gae(".select+.image", main);
            ge("#filterNumber", main).innerText = displayLanguage.str_166 + selects.length;
            main.focus();
        });
        let heightSelect = ge("#height", main);
        for (let i = 0; i <= 40; i++) {
            let option = document.createElement("option");
            option.value = i;
            option.innerText = i == 0 ? "All" : i * 100;
            fragment.append(option);
        }
        heightSelect.append(fragment);
        heightSelect.addEventListener("change", () => {
            heightNum = Number(heightSelect.value) * 100;
            changeList();
            const selects = gae(".select+.image", main);
            ge("#filterNumber", main).innerText = displayLanguage.str_166 + selects.length;
            main.focus();
        });
        let threadingSelect = ge("#threading", main);
        for (let i = 1; i <= 32; i++) {
            let option = document.createElement("option");
            option.value = i;
            option.innerText = i;
            fragment.append(option);
        }
        threadingSelect.append(fragment);
        threadingSelect.value = config.threading;
        threadingSelect.addEventListener("change", () => {
            config.threading = Number(threadingSelect.value);
            saveConfig(config);
            addLis();
            main.focus();
        });

        let titleReplace = fn.dt({
            s: "title"
        });
        ge("#inputTitle", main).value = (customTitle || titleReplace);
        gae("#close", main).forEach(button => {
            button.addEventListener("click", () => {
                fn.remove("#overflowYHidden");
                shadowElement.remove();
                isOpenFilter = false;
            });
        });
        gae("#settings", main).forEach(button => button.addEventListener("click", () => createPictureLoadOptionsShadowElement()));
        gae("#gallery", main).forEach(button => button.addEventListener("click", () => newTabView()));
        gae("#favor", main).forEach(button => button.addEventListener("click", () => createFavorShadowElement()));
        gae("#copy", main).forEach(button => {
            button.addEventListener("click", () => {
                const srcs = gae(".select+.image", main).map(img => img.dataset.src);
                if (srcs.length == 0) return;
                copyImgSrcTextB(srcs);
            });
        });
        gae("#export", main).forEach(button => {
            button.addEventListener("click", () => {
                const srcs = gae(".select+.image", main).map(img => img.dataset.src);
                if (srcs.length == 0) return;
                exportImgSrcText(srcs);
            });
        });
        gae("#select-all", main).forEach(button => {
            button.addEventListener("click", () => {
                gae("input.check", main).forEach(input => {
                    input.checked = true;
                    input.classList.add("select");
                    ge("#filterNumber", main).innerText = displayLanguage.str_166 + srcs.length;
                });
            });
        });
        gae("#unselect-all", main).forEach(button => {
            button.addEventListener("click", () => {
                gae("input.check", main).forEach(input => {
                    input.checked = false;
                    input.classList.remove("select");
                    ge("#filterNumber", main).innerText = displayLanguage.str_166 + "0";
                });
            });
        });
        gae("#reverse-selection", main).forEach(button => {
            button.addEventListener("click", () => {
                gae("input.check", main).forEach(input => {
                    if (input.checked) {
                        input.checked = false;
                        input.classList.remove("select");
                    } else {
                        input.checked = true;
                        input.classList.add("select");
                    }
                    const selects = gae(".select+.image", main);
                    ge("#filterNumber", main).innerText = displayLanguage.str_166 + selects.length;
                });
            });
        });
        gae("#reload", main).forEach(button => button.addEventListener("click", () => {
            widthSelect.value = 0;
            heightSelect.value = 0;
            ge("#filterNumber", main).innerText = displayLanguage.str_166 + srcs.length;
            addLis();
        }));
        gae("#download", main).forEach(button => {
            button.addEventListener("click", () => {
                const srcs = gae(".select+.image", main).map(img => img.dataset.src);
                if (srcs.length == 0) return;
                const text = ge("#inputTitle", main).value;
                fn.remove("#overflowYHidden");
                shadowElement.remove();
                isOpenFilter = false;
                DownloadFn(srcs, text);
            });
        });
        let inputSize = ge("#size", main);
        if (config.noSize == 1) {
            inputSize.parentNode.classList.add("line-through");
        }
        inputSize.checked = showSize == 0 ? false : true;
        inputSize.addEventListener("change", () => {
            showSize = inputSize.checked ? 1 : 0;
            config.showSize = showSize;
            saveConfig(config);
            widthSelect.value = 0;
            heightSelect.value = 0;
            ge("#filterNumber", main).innerText = displayLanguage.str_166 + srcs.length;
            addLis();
            main.focus();
        });
        let inputMove = ge("#move", main);
        if (inputMove) {
            inputMove.checked = move == 0 ? false : true;
            inputMove.addEventListener("change", () => {
                move = inputMove.checked ? 1 : 0;
                config.move = move;
                saveConfig(config);
                widthSelect.value = 0;
                heightSelect.value = 0;
                ge("#filterNumber", main).innerText = displayLanguage.str_166 + srcs.length;
                addLis();
                main.focus();
            });
        }
        const imageList = ge("#image-list", main);
        let Viewer;
        let ViewerJsInstance;
        if ("Viewer" in _unsafeWindow) {
            Viewer = _unsafeWindow.Viewer;
            ViewerJsInstance = new Viewer(imageList, {
                navbar: false,
                title: false,
                initialCoverage: 0.99,
                interval: FancyboxSlideshowTimeoutNum,
                url: "data-src",
                viewed: (event) => instantScrollIntoView(event.detail.originalImage)
            });
        }

        const addLis = () => {
            imageList.innerHTML = "";
            const loadImgList = [];
            for (const [index, src] of srcs.entries()) {
                const input = document.createElement("input");
                input.className = "check select";
                input.setAttribute("type", "checkbox");
                input.checked = true;
                input.onchange = () => {
                    if (input.checked == true) {
                        input.classList.add("select");
                    } else {
                        input.classList.remove("select");
                    }
                    const selects = gae(".select+.image", main);
                    ge("#filterNumber", main).innerText = displayLanguage.str_166 + selects.length;
                };
                const img = new Image();
                img.className = "image";
                if ("referrerpolicy" in siteData) {
                    img.setAttribute("referrerpolicy", siteData.referrerpolicy);
                }
                img.src = loading_bak;
                img.dataset.src = src;
                img.onload = () => {
                    if (img.classList.contains("loaded")) {
                        if (move == 0 || hasTouchEvent) {
                            p.innerText = img.dataset.width + " x " + img.dataset.height;
                        } else {
                            p.innerText = (index + 1) + "P | " + img.dataset.width + " x " + img.dataset.height;
                        }
                        img.onload = null;
                        if (showSize != 0) {
                            getFileSize(img.src, p, inputSize.parentNode);
                        }
                    }
                };
                loadImgList.push([simpleLoadImg, null, img]);
                const p = document.createElement("p");
                if (move == 0 || hasTouchEvent) {
                    p.innerText = "? x ?";
                } else {
                    p.innerText = (index + 1) + "P | ? x ?";
                }
                const li = document.createElement("li");
                li.className = "image-item";
                if (backgroundColor === "d") {
                    p.classList.add("dark");
                    li.classList.add("dark");
                }
                li.append(input);
                li.append(img);
                li.append(p);
                if (move != 0 && !hasTouchEvent) {
                    li.setAttribute("draggable", true);
                    li.addEventListener("dragstart", drag_sort_Start);
                    li.addEventListener("drop", drop_sort);
                    li.addEventListener("dragenter", cancelDefault);
                    li.addEventListener("dragover", cancelDefault);
                }
                fragment.append(li);
            }
            imageList.append(fragment);
            if (Viewer && ViewerJsInstance) {
                ViewerJsInstance.update();
            }
            main.focus();
            setTimeout(() => {
                const queue = new Queue(Number(config.threading));
                queue.addList(loadImgList);
                queue.run();
            }, 200);
        };
        addLis();
    };

    const getXY = (event) => {
        let x, y;
        if (event.type.includes("mouse")) {
            x = event.clientX;
            y = event.clientY;
        } else {
            x = event.changedTouches[0].clientX;
            y = event.changedTouches[0].clientY;
        }
        return {
            x: x,
            y: y
        }
    };

    //創建新分頁檢視眼睛圖示按鈕和圖片數量元素
    let viewImgDown = false;
    let isDragging = false;
    let isAddViewImgDraggEvent = false;
    let startX, startY, startLeft, startTop;
    let eventViewImg, eventMenu;
    const addNewTabViewButton = () => {
        if (ge("#FullPictureLoadEye") || FullPictureLoadShowEye == 0) return;
        isAddNewTabViewButton = true;
        let img = new Image();
        img.id = "FullPictureLoadEye";
        img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEV0lEQVRYhb2XTWwTRxTHTShJ4NDegJ4rwbGngkpVxCGQ3loVcaIlEuJU2h5oKyFQtXaigojj3VAQErTlQxQCiRMaoF+HxjhNjD/XxVISbGPHxEAc3MR8xo5xeMybZNezn7HAYaUXWZuZ9/vPmzdv3loaGjbVEltGzGL2cMDV2ELC+81hYX9zmO9sFgVfS1iIN4t83Opv81u9bV2cp/X7fX0HPtz6zSd1C/mTn4XgnIurbxH5bwkwRYDAGoGDLeDQmsincA7OrUSA7nsAWNIS4psIeEwNNoPj+/I4/jaZvwN9VRaO+edw9HAdmXxGD1w5XDH+Ahc8vqIiOOdrXU3g/mrBy/MEH/o2h8/tt7facEZEiI2EYvvpnoeFc4sFl/2QE4QshOMBkAVgwi02XPYXcHw+f/pqy6EnGfta4OjP35b+WvjyLVkAntlK4IfEI9AVvwKe8QD4snHoGbtFzU9+ezJB6E7+DvbIMXP4vC/O2/odFYD7Qf6RNBt8auQCDN2PQiFfAN//D6Fh4AYs7XXDkt/m7I3eftgyEIHg5GOYLc3CzdwtOBPvNI+k3z7a1LS91oLl1Qj+Y+RnGMnGoFgoUjt7OwN1l/tlsNrwf+fHJgBmgVrsQRKODp803sagfZ0Fa7se3Bm/Ck+mn8pwXHmtCZwVEZp6LIsoFGeoL90cEvm9FjwWavjfKZcMRnteeg6bSYgliPNOFtx37sPbX9lg5W4r1J9wKkQ0DkYoHOdJPtzp63oJ3IERCLDw/rRXA8/mi4o9T+SeQG7qEby7cRusXf8xrNnwqUIE5kR2ekbhB60/7VGcHqyOFvInKsF7E39q4LiSwexDxQrf2XMA1m3eTuGSrfyCK4+5dA0GMpMaAejvr7SrnG8h/iZJQj4qhYYVIMHRPCoBGHYWTgWQdxK8prsPBsYndRejEWANtAXZ5MAwsXA03AIMqyQAw41hl+BrPtgK9T91y/BlPX2QeTStgf877tNcUOT2szvV2em+d10hAG0Lk4SSCAw7Gguv6f4HGt2iBu66O6hXnDos2EbpldfOxBXIFwuyACwyhjWAgS+/5ILAxJQMn3k2Az2jf+hXRzyG2MMZ1fYjQ79ANJeQRWCR0YhQwc+N3pXhWBHRh1Fptont71mwHNpCDk0pZu107CKM5OJQKpVokcFzTnOC2fOP3GG68nw+D8OTMTrH9GIS+VHaquG9bHQZqa2VXDTO5FUYzATAOxGFzuQIdBHz3BuiheZirBcO3Tha2c34n7BH0Qnpdb2V3GovdUWT1WPfqWjHsHt9LXD0EW7/TNMP0ms5JPy62HCy+rO6PeFCTWl1OiM+KDWlmp6QbcvnP7uqvXLvD5H2VSxcbsnUD/thUqWesMPhcSxXww0FyDlBuldyV6Re4TsgxSacGm4qQBq86+DON7GBtPrtyYrhopDAc84eNT24bg4YDcaKiT0c1m/81sM9neslhOjcb/puL5ZX9ceoERzfvwApT7t293t0AgAAAABJRU5ErkJggg==";
        img.style.bottom = "24px";
        img.style.right = "24px";
        img.oncontextmenu = () => false;
        img.addEventListener("click", () => newTabView());
        document.body.append(img);
        eventViewImg = img;
        let menuDiv = document.createElement("div");
        menuDiv.id = "FullPictureLoadFixedMenuB";
        menuDiv.style.bottom = "22px";
        menuDiv.style.right = "64px";
        const menuObj = [{
            id: "FullPictureLoadCaptureNum",
            text: "0",
            cfn: async () => {
                let srcArr;
                if (siteData.category === "lazyLoad") {
                    srcArr = captureSrcArray;
                } else {
                    let selector = siteData.capture ?? siteData.imgs;
                    srcArr = await getImgs(selector);
                }
                if (srcArr.length == 0) return fn.showMsg(displayLanguage.str_44);
                let titleText = customTitle ?? document.title;
                let picNum = srcArr.length;
                let fileName = `${titleText}[${picNum}P]_MediaURLs.txt`;
                if (videoSrcArray.length > 0) {
                    srcArr = srcArr.concat(videoSrcArray);
                    fileName = `${titleText}[${picNum}P + ${videoSrcArray.length}V]_MediaURLs.txt`;
                }
                let str = srcArr.join("\n");
                let blob = new Blob([str], {
                    type: "text/plain",
                    endings: "native"
                });
                saveData(blob, fileName);
                fn.showMsg(`${displayLanguage.str_101}`);
            }
        }];
        const createMenu = obj => {
            let item = document.createElement("div");
            if (!!obj.id) item.id = obj.id;
            item.innerText = obj.text;
            item.oncontextmenu = () => false;
            if (!!obj.cfn) item.addEventListener("click", obj.cfn);
            if (!!obj.mfn) item.addEventListener("mousedown", obj.mfn);
            menuDiv.append(item);
        };
        [...menuObj].forEach(obj => createMenu(obj));
        document.body.append(menuDiv);
        eventMenu = menuDiv;

        const downEvent = (event) => {
            const obj = getXY(event);
            viewImgDown = true;
            startX = obj.x;
            startY = obj.y;
            startLeft = eventViewImg.offsetLeft;
            startTop = eventViewImg.offsetTop;
        };

        const moveEvent = (event) => {
            if (!viewImgDown) return;
            event.preventDefault();
            const obj = getXY(event);
            isDragging = true;
            const dx = obj.x - startX;
            const dy = obj.y - startY;
            eventViewImg.style.top = startTop + dy + "px";
            eventViewImg.style.bottom = "auto";
            eventViewImg.style.left = startLeft + dx + "px";
            eventViewImg.style.right = "auto";
            eventMenu.style.opacity = "0";
            eventMenu.style.top = (eventViewImg.offsetTop - ((eventMenu.offsetHeight - 32) / 2)) + "px";
            eventMenu.style.bottom = "auto";
            eventMenu.style.left = (eventViewImg.offsetLeft - (eventMenu.offsetWidth + 10)) + "px";
            eventMenu.style.right = "auto";
        };

        const upEvent = (event) => {
            eventMenu.style.opacity = "1";
            viewImgDown = false;
            setTimeout(() => {
                isDragging = false;
            }, 100);
        };

        const resizeEvent = () => {
            eventViewImg.style.top = "auto";
            eventViewImg.style.bottom = "24px";
            eventViewImg.style.left = "auto";
            eventViewImg.style.right = "24px";
            eventMenu.style.top = "auto";
            eventMenu.style.bottom = "22px";
            eventMenu.style.left = "auto";
            eventMenu.style.right = "64px";
        };

        if (hasTouchEvent) {
            img.addEventListener("touchstart", downEvent, {
                passive: false,
                capture: true
            });
            if (!isAddViewImgDraggEvent) {
                isAddViewImgDraggEvent = true;
                document.addEventListener("touchmove", moveEvent, {
                    passive: false,
                    capture: true
                });
                document.addEventListener("touchend", upEvent);
                _unsafeWindow.addEventListener("resize", resizeEvent);
            }
        } else {
            img.addEventListener("mousedown", downEvent);
            if (!isAddViewImgDraggEvent) {
                isAddViewImgDraggEvent = true;
                document.addEventListener("mousemove", moveEvent);
                document.addEventListener("mouseup", upEvent);
                _unsafeWindow.addEventListener("resize", resizeEvent);
            }
        }

    };

    //清除圖片縮放級別
    const cancelZoom = () => {
        if (isFetching || !siteData.insertImg || isOpenOptionsUI) return;
        if (ge(".FullPictureLoadImage:not(.small)")) {
            options.zoom = 0;
            let jsonStr = JSON.stringify(options);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
            gae(".FullPictureLoadImage:not(.small)").forEach(img => {
                img.style.width = "";
                let pE = img.parentNode;
                if (pE.nodeName === "A") {
                    pE.style.width = "";
                }
            });
            fn.showMsg(displayLanguage.str_61);
        }
    };

    //創建腳本在頁面左下的功能按鈕
    let imgDown = false;
    let isAddDraggEvent = false;
    let eventImg;
    const addFullPictureLoadButton = () => {
        if (ge("#FullPictureLoad")) return;
        isAddFullPictureLoadButton = true;
        let img = new Image();
        img.id = "FullPictureLoad";
        img.className = "FullPictureLoadFixedBtn";
        img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACFlBMVEVEREAAAABEREBEREBUXnFTXXBTXG5VXXJUXHFUW28grV0grV0hrl4hrV0hq10iql0oomAhrV2BiZiAiJd/h5V+h5Uiq16OlaKNlKGMk5+Mkp+KkZ89p28nq2Hp9+/n9u3t8PHs7/Dg9Ojp7O3d8+bo7O3o6+zn6+3m6uzl6evX8OLV8OHi5ujh5efO7dze4uTe4ePb3+LY3eDX29/W2t7T19u35Mu25Mr01lqw4sbz1Vmv4sXA1NWs4cPw0lnv0lmp4MCk3r3ozVuh3buu0M6vz83kylugysefycadx8OexsOdxsOF0qZ6zp5pyJK1p2S0pmOsoGRWv4SLlKEmuZpBsnc5t3AmuJmQi2ont5kmtpcptJiOiWg0tWwytGorr5Yqr5YsrpUws2kqrJRNmpMusmcsqpIuqJMssWkqsWQqsGUnsGUzoI8lsGGAf2wkr2Ekr2BzfI0irl8hrl5ye4x9fGogrWAhrV03mIwgrF9xeoshq10gql8dp2ccp2cdpmkcnIUanIYcm4QRoIUTnoURn4QdmYM/h4QcmIMSnYMXmoMWmoIbloIclYJDgYIYl4EaloAek4IfkYFqbm0jjoBqbW0ni4ApiX9Hd35kanBjaXBhaG9MbnpOanhOaXhPaHdDbXZHanZGanRLZnZJZ3RSYnVMZXRPY3ROY3VSYXRQYnRTYHRVX3NUX3RSYHNUXnNTXXJTXXFME6frAAAAHnRSTlMAAAUGZ2dqeHh7lrzNzc7O3O/09PT19fn5+fn5/f4hZOrvAAAB1UlEQVR42oWTzYoTQRSFv6q6RqOoqBicTTCKK1cOURBGBV9AXCgu9Vl8FF/ApcshI4qKgrtBByZK0HSGmMxkMrF/qq6LTjptErGX5zu3uu65dY3TYCh9ag2UNPsfjnmpZW4MgBbaIy/6PCnxvL7gEQhJ7AruAqifcZ96EHDX67ngKgCJn/k3B6AC1O9Cj9ri/2mBsZIf9iLi0rMFDhhjbO6NsL9er+CQG3pYMT+XuGVmuH9SzPF7S/UONDfUHl44/6A24wfdpMgsSO6tP52ffxjF6cUT056MBdxf/cVRzP6PiQG8KhZMJedhewik0QT43RsBQUEwLufZx53Td85p7wCwEu+Fs6qAGBsA1aO3XUZbG/EAsAJJlM/MGgOoDltdYNTam3JIOlVmOaj2N/sAjHf9lGdBqwACmmi0FU/TOWxfEY483o/9tcuvJBXU+90PaZHf5NtVFzTL+N7bqD4GS9DRmzl3btJWk2WFIKradqX8LfudU3VKBuKd0vwc+HCjNDJhkJXfB6jq+wZJBSAT5MmKN1/la7sJ+jmsiyQrdkZo9N819FNnXcSZFTt1rGnXhl/G6a26IP/YOXczi5prQmFY3snbkzNSXGyBV+28p+nNF+vn2h97PvHD5SOHkgAAAABJRU5ErkJggg==";
        img.style.bottom = "24px";
        img.style.left = "24px";
        img.setAttribute("title", displayLanguage.str_47);
        img.oncontextmenu = () => false;
        img.addEventListener("click", () => {
            fastDownload = false;
            //DownloadFn();
            createFilterDownload();
        });
        img.addEventListener("mousedown", (event) => {
            if (event.button == 1) {
                event.preventDefault();
                exportImgSrcText();
            }
            if (event.button == 2) {
                event.preventDefault();
                copyImgSrcText();
            }
        });
        document.body.append(img);
        eventImg = img;
        if ("insertImg" in siteData) {
            let img2 = new Image();
            img2.id = "FullPictureLoadGoToFirstImage";
            img2.className = "FullPictureLoadFixedBtn";
            img2.style.display = "none";
            img2.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA7BJREFUWEetl29olVUYwH/n3jvvGpp/WtNlIdoK1MJazBwO0/mlZqFgRCgGfZC7TTbwixqbMnPiHIIwmdd9MYiMhD4o6gqirenGsoF/MLfaahFz3a1Shlv7e9/3yHnnxXvv3vee96574P3wcp4/v/M8z3nOOQK3o67Oj2+0EMlWPKxEkg3Wp0YIQQiTLgQXCWc0UV4+4ca00Ao1HM3G8B0CuROYp5WfFhgGcQ5v+FMCFaFEOs4An1WlM+6vRIq9QIZLx/Fiowh5kvSJaj6uGrezYQ9QX7sEYV4A3pyl43i160jPNvbsG4ifmAlwquZVfDQieV7nfJE/3RJ5MGG7uFh1wT3CFFF24E70RCyAWrnH7NA5V0pH8gooW51r2Tp19wYHO1qROmIFYXryoiPxBEDlfCz9B13YlULd+s0EVq6JcdfQdZvytu/1EHCdp8Y3RmriCUDwWDVSVOgq1s55RMc1hJBHKfmkUulNA1hbzftbomp3Wnk8sEuIUbxGjtqi0wCnjwdBFjut3q3z5CIhzlC6v0Qw3eH+cWoyyTpPAmKYcMazgtM17wCNTk0iUc51Re8iHUWC+pozCAJ2DeL/OHcVCUmDIFjTgmRDPMDB3HzUl4qxq7mR87//MtOU4KpKQTfwUvTsgjl+QrtK8Qr9WeUGsG2gn02Xz9uJ9iiAYWBu9OwbmYtp36YOv9SM/8JTZH1ez5RpxhscsQWYP8fPnzsCZPh8MQph0+THv0MULFlqS9Y60M+6rGx8Hk/M/Nlf71B87Ts7HQtgRgqUZNkruZxYt/Fxp4JJ0+Cj5m/IeXoB1XkFtgCVHa10Dt2ndu0GcuYvtGR+fvAvO5uu0DV03yEFDkWopNVqtix70QrdFz2d9D4cYt+atQkBam//ZEFvXrqMCcPg2sA95zxaReiwDZ203AC4rhxrGyZoRHaGUgoARdpWHA+RQoDHrVh50BxG0RApBAhSeqDU9XEcgUgRwAhpRg67KwaTupAoiD2rX+dk/ibbOtvb3kz93Zv6GhTiECX7jyjBpK9k+Yufo+W9D22dvHXpK9oH/9IAiDYyxwr5oGoyFkD9ubyUfln4Lu+veDnG0de93exouqxz3kdaOE+FPiI4q2u5OqRKVr3G2y8st+x82/cHwc5bGDLRvVj0Ycgtia/lEayUP0xEG2nh7dErd45AZCY1T7MRhKjlmbHjkZzH50h/4M/ucfoQOEeacdhu1dEQeoCItPPzXCVenTj9SNmJ4BLeRS0EAlP6/QiPAMXOipDq4W0VAAAAAElFTkSuQmCC";
            img2.setAttribute("title", displayLanguage.str_62);
            img2.addEventListener("click", () => goToImg("first"));
            document.body.append(img2);
            let img3 = new Image();
            img3.id = "FullPictureLoadGoToLastImage";
            img3.className = "FullPictureLoadFixedBtn";
            img3.style.display = "none";
            img3.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA6lJREFUWEfFl21IlWcYx3/3c46vayG1lq5i5FablrQFbon2oiOYzlgfgsY2gvrinCQEwzayklI69SVQPMdDH4KJMkZBoxf6kpkYVjK32FqgtiGbs8xczeF0O5477ucknZfnzaPUDc+n57ru/++67uu6XwROh9+fwNToRiRbECIbWAIsBQQwhGCIILcRfEcgtY3KykknUytn63GibjH/uw4CnwDz7cyf/B8D0YIrcIiyfUNWPuYA39Yk8iBlL1JWAfMcCkebjSPkcZIna9lZM2E0hzGAHrX7NMj8OIWj3a4jta1UVN2N/hEL0ODJwSXOg1xmJu4SgvLst3h/2XLd5OLvv+H75UempDTnFfxBgBJ2f/lTuFEkQCjybitx5dxaVMq2zJURYqd+7eXjtnPWCVMQQS03PBNPAdSaj6S02aU9b/ErXNnykaHQxrPf0HXvT7tVu07KxKbpmngK4Du6HykP2XlXrHqb43mFhmZ7ui7TeOsHuylAyDrKv6pWhiGAUKv1O6n2qjXvUJtbYChS3d3JsZs37AFgHNfU66pFQwBejxcod+I5RwAq9iY+31suqK9Pwj1+H3jx2QIwRiB1kcDrKQYuOBFXNnOXAV2xRNDoaUJQ9lwAJH6Bz3MFyQYzgPXpS0lyubg0OIDaZpxkIHN+Gp+uyCZB0zg/cIdrwybHgaBDLUEvsCIaICttIS1FH7B6wUv6r/5Hf1F1o4PstIWWXdD/90O+LiwmUXPpfgr6i2vtNPzcYxRjnwIYM2q/pvWb2fVGToRTIBjUoylIVydx7Oi8O8i6lzNwa1rEz/FAgFdb/Tz6L+aE/scQQKVueEcFL7gTnJaGrV3emRa+H7kXbacDGC7B5dLt5JtEaqsWZaAOqYxmLw9jM9BnWoTbX3uT5sKSmWoZ2h/u6UJ9MUMvQpM2VFtkff57lGWtmRWE//ZNKq9e0osxZuhtaLERzRbCUjxEU2K7FccL4UD8yVasOLxHfSA/M8v1TCEciIcdRkrVX5fBlH4cp84Wwpl49HGsVH1HapFin1XF2WXCobjBhUSpnqxJ5t/kduDdeCAci4PJlUypNh5LRwt2I/UXj+lQmTicW8DuVWt1m4ZbPezv7jRutfBZLC+l04bqWu7mgh2EMl+QlKx7jU4avjkiA3B0LZ92UZkQwTN2yzGDHWoGD5PpWVVNTCRVI8Ueq+6wgYjzaRY+q96i7gMg1ePU0b0RmIPHaXRooctrEZIP0chCkgH6p0bcz/PHF6yIkDG/FFMAAAAASUVORK5CYII=";
            img3.setAttribute("title", displayLanguage.str_63);
            img3.addEventListener("click", () => goToImg("last"));
            img3.addEventListener("mousedown", (event) => {
                if (event.button == 2) {
                    event.preventDefault();
                    exportImgSrcText();
                }
            });
            document.body.append(img3);
        }

        const downEvent = (event) => {
            const obj = getXY(event);
            imgDown = true;
            startX = obj.x;
            startY = obj.y;
            startLeft = eventImg.offsetLeft;
            startTop = eventImg.offsetTop;
        };

        const moveEvent = (event) => {
            if (!imgDown) return;
            event.preventDefault();
            const obj = getXY(event);
            isDragging = true;
            const dx = obj.x - startX;
            const dy = obj.y - startY;
            eventImg.style.top = startTop + dy + "px";
            eventImg.style.bottom = "auto";
            eventImg.style.left = startLeft + dx + "px";
            eventImg.style.right = "auto";
        };

        const upEvent = (event) => {
            imgDown = false;
            setTimeout(() => {
                isDragging = false;
            }, 100);
        };

        const resizeEvent = () => {
            eventImg.style.top = "auto";
            eventImg.style.bottom = "24px";
            eventImg.style.left = "24px";
            eventImg.style.right = "auto";
        };

        if (hasTouchEvent) {
            img.addEventListener("touchstart", downEvent, {
                passive: false,
                capture: true
            });
            if (!isAddDraggEvent) {
                isAddDraggEvent = true;
                document.addEventListener("touchmove", moveEvent, {
                    passive: false,
                    capture: true
                });
                document.addEventListener("touchend", upEvent);
                _unsafeWindow.addEventListener("resize", resizeEvent);
            }
        } else {
            img.addEventListener("mousedown", downEvent);
            if (!isAddDraggEvent) {
                isAddDraggEvent = true;
                document.addEventListener("mousemove", moveEvent);
                document.addEventListener("mouseup", upEvent);
                _unsafeWindow.addEventListener("resize", resizeEvent);
            }
        }

    };

    //創建浮動選單
    const addFullPictureLoadFixedMenu = () => {
        if (ge("#FullPictureLoadFixedMenu")) return;
        isAddFullPictureLoadFixedMenu = true;
        let menuDiv = document.createElement("div");
        menuDiv.id = "FullPictureLoadFixedMenu";
        menuDiv.style.width = "54px";
        const menuObj = [{
            text: displayLanguage.str_128,
            show: 0,
            cfn: event => {
                event.preventDefault();
                createFavorShadowElement();
            }
        }, {
            name: "shadowGallery",
            text: displayLanguage.str_141,
            show: 0,
            cfn: event => {
                event.preventDefault();
                createShadowGallery();
            }
        }, {
            name: "newTabView",
            text: displayLanguage.str_106,
            show: 0,
            cfn: event => {
                event.preventDefault();
                newTabView();
            }
        }, {
            text: displayLanguage.str_158,
            show: 0,
            cfn: event => {
                event.preventDefault();
                createFilterDownload();
            }
        }, {
            text: displayLanguage.str_107,
            show: 0,
            cfn: event => {
                event.preventDefault();
                fastDownload = true;
                DownloadFn();
            }
        }, {
            text: displayLanguage.str_174,
            show: 0,
            cfn: event => {
                event.preventDefault();
                exportJsonFormat();
            }
        }, {
            text: displayLanguage.str_176,
            show: 0,
            cfn: event => {
                event.preventDefault();
                exportMarkdownFormat();
            }
        }, {
            text: displayLanguage.str_178,
            show: 0,
            cfn: event => {
                event.preventDefault();
                copyMarkdownFormat();
            }
        }, {
            text: displayLanguage.str_104,
            show: 0,
            cfn: event => {
                event.preventDefault();
                exportImgSrcText();
            }
        }, {
            text: displayLanguage.str_105,
            show: 0,
            cfn: event => {
                event.preventDefault();
                copyImgSrcTextB();
            }
        }, {
            name: "fn",
            text: displayLanguage.str_159,
            show: 0,
            cfn: event => {
                event.preventDefault();
                siteData.fn();
            }
        }, {
            name: "zoom",
            text: displayLanguage.str_88,
            show: 0,
            cfn: event => {
                event.preventDefault();
                fn.clearSetTimeout();
                cancelZoom();
            }
        }, {
            name: "zoom",
            text: displayLanguage.str_87,
            show: 0,
            cfn: event => {
                event.preventDefault();
                fn.clearSetTimeout();
                reduceZoom();
            },
            mfn: event => {
                if (event.button == 2) {
                    event.preventDefault();
                    increaseZoom();
                }
            }
        }, {
            name: "toggleImgMode",
            text: displayLanguage.str_86,
            show: 0,
            cfn: event => {
                event.preventDefault();
                toggleImgMode();
            }
        }, {
            name: "insert",
            id: "insertImgMenu",
            text: displayLanguage.str_160,
            show: 0,
            cfn: event => {
                event.preventDefault();
                fn.immediateInsertImg("yes");
            }
        }, {
            text: displayLanguage.str_85,
            show: 0,
            cfn: event => {
                event.preventDefault();
                createPictureLoadOptionsShadowElement();
            }
        }, {
            text: displayLanguage.str_133,
            show: 1
        }];
        const createMenu = obj => {
            if (!("insertImg" in siteData) && obj.name === "insert" || !("fn" in siteData) && obj.name === "fn" || !siteData.insertImg && ["toggleImgMode", "zoom"].some(e => e === obj.name) || "newTabView" === obj.name && siteData.eye === 0) return;
            let item = document.createElement("div");
            item.innerText = obj.text;
            if (!!obj.id) item.id = obj.id;
            if (obj.show === 0) item.classList.add("itemNoShow");
            item.oncontextmenu = () => false;
            if (!!obj.cfn) item.addEventListener("click", obj.cfn);
            if (!!obj.mfn) item.addEventListener("mousedown", obj.mfn);
            fragment.append(item);
        };
        [...menuObj].forEach(obj => createMenu(obj));
        menuDiv.append(fragment);
        document.body.append(menuDiv);
        menuDiv.onmouseenter = () => {
            isOpenMenu = true;
            fn.gae(".itemNoShow", menuDiv).forEach(e => {
                e.classList.remove("itemNoShow");
                e.classList.add("itemShow");
                e.width = "116px";
            });
            menuDiv.style.width = "128px";
            menuDiv.lastChild.width = "116px";
            menuDiv.lastChild.innerText = displayLanguage.str_134;
        }
        menuDiv.onmouseleave = () => {
            fn.gae(".itemShow", menuDiv).forEach(e => {
                e.classList.remove("itemShow");
                e.classList.add("itemNoShow");
                e.width = "38px";
            });
            menuDiv.style.width = "48px";
            menuDiv.lastChild.width = "38px";
            menuDiv.lastChild.innerText = displayLanguage.str_133;
            setTimeout(() => (isOpenMenu = false), 200);
        }
    };

    //元素模擬點擊
    const EClick = obj => {
        const event = new MouseEvent("click", {
            bubbles: true,
            cancelable: true,
            view: _unsafeWindow
        });
        if (isEle(obj)) {
            obj.dispatchEvent(event);
        } else if (isString(obj)) {
            let ele = fn.ge(obj);
            if (isEle(ele)) {
                ele.dispatchEvent(event);
            } else {
                console.error("EClick點擊元素參數錯誤", obj);
            }
        }
    };

    //創建返回頂部按鈕
    const addReturnTopButton = () => {
        let a = document.createElement("a");
        a.href = "javascript:void(0);";
        a.setAttribute("onclick", "window.scrollTo({top:0,behavior:'smooth'});");
        let img = new Image();
        img.src = "data:image/png;base64,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";
        img.className = "FullPictureLoadImageReturnTop";
        a.append(img);
        document.body.append(a);
    };

    //列出一般圖片站
    const photoData = customData.filter(item => item.category === "photo");
    //列出寫真站
    const nsfw1Data = customData.filter(item => item.category === "nsfw1");
    //列出老司機站
    const nsfw2Data = customData.filter(item => item.category === "nsfw2");
    //列出漫畫站
    const comicData = customData.filter(item => item.category === "comic");
    //列出H漫站
    const hcomicData = customData.filter(item => item.category === "hcomic");
    //列出LazyLoad模式規則
    const lazyLoadData = customData.filter(item => item.category === "lazyLoad");
    //列出自動翻頁
    const autoPagerData = customData.filter(item => item.category.includes("autoPager"));
    //列出去廣告規則
    const AD_Data = customData.filter(item => item.category === "ad");
    //列出未分類
    const noneData = customData.filter(item => item.category === "none");

    let topDistance = () => {};

    //創建腳本選項元素
    const createPictureLoadOptionsShadowElement = () => {

        isOpenOptionsUI = true;

        const config = getConfig();

        const mainHtml = '<div id="FullPictureLoadOptionsShadowElement" style="display: initial !important;position: fixed !important;z-index: 2147483647 !important;"></div>';
        document.body.insertAdjacentHTML("beforeend", mainHtml);

        const mainElement = ge("#FullPictureLoadOptionsShadowElement");
        const shadow = mainElement.attachShadow({
            mode: "closed"
        });

        const style = createStyle(`
#FullPictureLoadOptions {
    text-align: center;
    width: 360px;
    height: auto;
    position: fixed;
    top: 10%;
    left: calc((100% - 362px) / 2);
    border: 1px solid #a0a0a0;
    border-radius: 3px;
    box-shadow: -2px 2px 5px rgb(0 0 0 / 30%);
    background-color: #fafafb;
    z-index: 2147483647;
}

#FullPictureLoadOptions label,
#FullPictureLoadOptions select {
    margin: 0px;
    padding: ${isFirefox ? "0px 0px 0px 4px" : "0px"};
}

#FullPictureLoadOptions select {
    border: 1px solid #a0a0a0;
    background-color: transparent;
    border-radius: 0px;
    min-width: 60px;
    height: unset;
    -webkit-box-shadow: unset;
    box-shadow: unset;
    -webkit-appearance: auto;
    appearance: auto;
    background-image: unset;
    display: inline-block;
}

#FullPictureLoadOptions * {
    font: unset;
    font-family: Arial, sans-serif;
    font-size: 14px;
    color: black;
    float: none;
    line-height: 18px;
    margin-bottom: 4px;
    padding: 1px 4px;
    width: auto;
}

#FullPictureLoadOptions button {
    width: auto;
    min-width: 102px;
    max-width: 110px;
    min-height: unset;
    max-height: 24px;
    margin-left: 2px;
    margin-right: 2px;
    margin-bottom: 4px;
    display: inline-block;
    color: #000000;
    border: 1px solid #a0a0a0;
    background-color: transparent;
    border-radius: unset;
}

#FullPictureLoadOptions input {
    position: unset;
    opacity: 1;
    pointer-events: auto;
    color: #000000;
    height: 18px;
    border: 1px solid #a0a0a0;
    border-radius: unset;
    background-color: transparent;
    outline: unset;
    display: unset;
    -webkit-appearance: auto;
}

#FullPictureLoadOptions p {
    width: calc(100% - 16px);
    text-align: center;
    margin-block-start: 0px;
    margin-block-end: 0px;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
}
        `);
        shadow.appendChild(style);

        const main = document.createElement("div");
        main.id = "FullPictureLoadOptions";
        const FullPictureLoadOptionsMainHtmlStr = `
<div style="width: 100%;">
    <p id="title">${displayLanguage.str_68}</p>
</div>
<div id="iconDIV" style="width: 348px; display: flex;">
    <input id="icon" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_69}</label>
</div>
<div id="ShowEyeDIV" style="width: 348px; display: none;">
    <input id="ShowEye" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_123}</label>
</div>
<div id="ShowFixedMenuDIV" style="width: 348px; display: flex;">
    <input id="ShowFixedMenu" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>※${displayLanguage.str_117}</label>
</div>
<div style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_108}</label>
    <select id="MsgPos"></select>
</div>
<div style="width: 348px; display: flex;">
    <input id="FavorNewTab" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>※${displayLanguage.str_50}</label>
</div>
<div id="AutoInsertImgDIV" style="width: 348px; display: flex;">
    <input id="AutoInsertImg" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_139}</label>
</div>
<div id="ZoomDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_79}</label>
    <select id="Zoom"></select>
</div>
<div id="viewModeDIV" style="width: 348px; display: flex;">
    <input id="viewMode" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_103}</label>
</div>
<div id="ColumnDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_80}</label>
    <select id="Column" title="${displayLanguage.str_81}"></select>
</div>
<div id="ShadowGalleryModeDIV" style="width: 348px; display: flex;">
    <input id="ShadowGalleryMode" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_140}</label>
</div>
<div style="width: 348px; display: flex;">
    <input id="autoExport" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_180}</label>
</div>
<div id="ShadowGalleryWheelDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_147}</label>
    <select id="ShadowGalleryWheel"></select>
</div>
<div id="FancyboxDIV" style="width: 348px; display: flex;">
    <input id="Fancybox" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_78}</label>
</div>
<div id="FancyboxWheelDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>※${displayLanguage.str_146}</label>
    <select id="FancyboxWheel"></select>
</div>
<div id="FancyboxSlideshowTimeoutDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>※${displayLanguage.str_145}</label>
    <select id="FancyboxSlideshowTimeout"></select>
</div>
<div id="FancyboxTransitionDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>※${displayLanguage.str_148}</label>
    <select id="FancyboxTransition"></select>
</div>
<div id="ComicDIV" style="width: 348px; display: none;">
    <input id="Comic" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_76}</label>
</div>
<div id="DoubleDIV" style="width: 348px; display: flex;">
    <input id="Double" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_77}</label>
</div>
<div id="AutoDownloadDIV" style="width: 348px; display: flex;">
    <input id="AutoDownload" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_73}${displayLanguage.str_74}</label>
</div>
<div id="CountdownDIV" style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_75}</label>
    <select id="Countdown"></select>
</div>
<div style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_70}</label>
    <select id="Threading"></select>
</div>
<div style="width: 348px; display: flex;">
    <input id="Zip" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_71}</label>
</div>
<div style="width: 348px; display: flex; margin-left: 6px;">
    <label>${displayLanguage.str_72}</label>
    <select id="Extension"></select>
</div>
<div style="width: 348px; display: flex;">
    <input id="Convert" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_110}</label>
</div>
<div id="CustomDownloadVideoDIV" style="width: 348px; display: none;">
    <input id="CustomDownloadVideo" type="checkbox" style="width: 14px; margin: 0 6px;">
    <label>${displayLanguage.str_124}</label>
</div>
<button id="CancelBtn">${isOpenFilter ? displayLanguage.str_82.replace(" (Esc)", "") : displayLanguage.str_82}</button>
<button id="ResetBtn">${displayLanguage.str_83}</button>
<button id="SaveBtn">${displayLanguage.str_84}</button>
`;
        main.innerHTML = FullPictureLoadOptionsMainHtmlStr;

        const MsgPosSelect = ge("#MsgPos", main);
        Object.values(displayLanguage.str_109).forEach((v, i) => {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = v;
            fragment.append(option);
        });
        MsgPosSelect.append(fragment);

        const ZoomSelect = ge("#Zoom", main);
        for (let i = 0; i < 11; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = i === 0 ? "Auto" : i + "0%";
            fragment.append(option);
        }
        ZoomSelect.append(fragment);

        const ColumnSelect = ge("#Column", main);
        for (let i = 2; i <= 6; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = i;
            ColumnSelect.append(option);
        }

        const ShadowGalleryWheelSelect = ge("#ShadowGalleryWheel", main);
        Object.values(displayLanguage.ShadowGalleryWheel).forEach((v, i) => {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = v;
            fragment.append(option);
        });
        ShadowGalleryWheelSelect.append(fragment);

        const FancyboxWheelSelect = ge("#FancyboxWheel", main);
        Object.values(displayLanguage.FancyboxWheel).forEach((v, i) => {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = v;
            fragment.append(option);
        });
        FancyboxWheelSelect.append(fragment);

        const FancyboxSlideshowTimeoutSelect = ge("#FancyboxSlideshowTimeout", main);
        for (let i = 0; i < 61; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = i === 0 ? "500 ms" : i + " sec";
            fragment.append(option);
        }
        FancyboxSlideshowTimeoutSelect.append(fragment);

        const FancyboxTransitionSelect = ge("#FancyboxTransition", main);
        for (const [k, v] of Object.entries(displayLanguage.FancyboxTransition)) {
            const option = document.createElement("option");
            option.value = k;
            option.innerText = v;
            fragment.append(option);
        }
        FancyboxTransitionSelect.append(fragment);

        const CountdownSelect = ge("#Countdown", main);
        for (let i = 1; i <= 60; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = i;
            fragment.append(option);
        }
        CountdownSelect.append(fragment);

        const ThreadingSelect = ge("#Threading", main);
        for (let i = 1; i <= 32; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.innerText = i;
            fragment.append(option);
        }
        ThreadingSelect.append(fragment);

        const ExtensionSelect = ge("#Extension", main);
        ["zip", "cbz"].forEach(v => {
            const option = document.createElement("option");
            option.value = v;
            option.innerText = v;
            fragment.append(option);
        });
        ExtensionSelect.append(fragment);

        topDistance = () => {
            if (main.offsetHeight < _unsafeWindow.innerHeight) {
                let num = (_unsafeWindow.innerHeight - main.offsetHeight) / 2;
                main.style.top = num + "px";
            } else {
                main.style.top = "10px";
            }
        };

        ge("#icon", main).checked = options.icon == 1 ? true : false;
        ge("#AutoInsertImg", main).checked = options.autoInsert == 1 ? true : false;
        ge("#ShowFixedMenu", main).checked = _GM_getValue("ShowFullPictureLoadFixedMenu", 1) == 1 ? true : false;
        ge("#FavorNewTab", main).checked = _GM_getValue("FavorOpenInNewTab", 0) == 1 ? true : false;
        ge("#MsgPos", main).value = _GM_getValue("FullPictureLoadMsgPos", 0);
        ge("#Threading", main).value = options.threading;
        ge("#Zip", main).checked = options.zip == 1 ? true : false;
        ge("#Extension", main).value = options.file_extension;
        ge("#Convert", main).checked = _GM_getValue("convertWebpToJpg", 1) == 1 ? true : false;
        ge("#AutoDownload", main).checked = options.autoDownload == 1 ? true : false;
        ge("#Countdown", main).value = options.autoDownloadCountdown;
        ge("#Comic", main).checked = options.comic == 1 ? true : false;
        ge("#Double", main).checked = options.doubleTouchNext == 1 ? true : false;
        if (siteData.category != "lazyLoad" && ("capture" in siteData) || isString(siteData.imgs) && !isArray(siteData.insertImg)) {
            ge("#ShowEyeDIV", main).style.display = "flex";
            ge("#ShowEye", main).checked = FullPictureLoadShowEye == 1 ? true : false;
        }
        if ("insertImg" in siteData) {
            const [, insertMode] = siteData.insertImg;
            if (![1, 2].some(n => n == insertMode)) {
                ge("#AutoInsertImgDIV", main).style.display = "none";
            }
        }
        if (!("insertImg" in siteData)) {
            ge("#AutoInsertImgDIV", main).style.display = "none";
            ge("#ZoomDIV", main).style.display = "none";
            ge("#viewModeDIV", main).style.display = "none";
            ge("#ColumnDIV", main).style.display = "none";
        }
        if (hasTouchEvent) {
            ge("#ShowFixedMenuDIV", main).style.display = "none";
            ge("#ShadowGalleryModeDIV", main).style.display = "none";
            ge("#ShadowGalleryWheelDIV", main).style.display = "none";
            ge("#FancyboxWheelDIV", main).style.display = "none";
        }
        if (isBoolean(siteData.SPA)) {
            ge("#ShadowGalleryModeDIV", main).style.display = "none";
            ge("#ShadowGalleryWheelDIV", main).style.display = "none";
        }
        if (isSimpleMode || siteData.aeg == 0) {
            ge("#ShadowGalleryModeDIV", main).style.display = "none";
        }
        if (isSimpleMode) {
            ge("#iconDIV", main).style.display = "none";
            ge("#AutoDownloadDIV", main).style.display = "none";
            ge("#CountdownDIV", main).style.display = "none";
        }
        if (fancyboxBlackList()) {
            //ge("#Fancybox", main).checked = false;
            ge("#FancyboxDIV", main).style.display = "none";
            ge("#FancyboxSlideshowTimeoutDIV", main).style.display = "none";
            ge("#FancyboxWheelDIV", main).style.display = "none";
            ge("#FancyboxTransitionDIV", main).style.display = "none";
        } else {
            ge("#Fancybox", main).checked = options.fancybox == 1 ? true : false;
            ge("#FancyboxSlideshowTimeout", main).value = FancyboxSlideshowTimeout;
            ge("#FancyboxWheel", main).value = _GM_getValue("FancyboxWheel", 1);
            ge("#FancyboxTransition", main).value = _GM_getValue("FancyboxSlideshowTransition", "fade");
        }
        ge("#Zoom", main).value = options.zoom;
        siteData.category == "comic" ? ge("#Column", main).value = 2 : ge("#Column", main).value = options.column;
        ge("#viewMode", main).checked = options.viewMode == 1 ? true : false;
        ge("#ShadowGalleryMode", main).checked = options.shadowGallery == 1 ? true : false;
        ge("#autoExport", main).checked = options.autoExport == 1 ? true : false;
        ge("#ShadowGalleryWheel", main).value = config.shadowGalleryWheel;
        if (comicSwitch) {
            ge("#ComicDIV", main).style.display = "flex";
        }
        let autoDownload = siteData.autoDownload;
        if (hasTouchEvent && showOptions || !autoDownload && showOptions) {
            fn.gae("#AutoDownloadDIV,#CountdownDIV", main).forEach(e => (e.style.display = "none"));
        }
        if (isSimpleMode || !hasTouchEvent && showOptions || (hasTouchEvent && showOptions && !siteData.next)) {
            ge("#DoubleDIV", main).style.display = "none";
        }
        let downloadVideo = siteData.downloadVideo;
        if (!!downloadVideo && downloadVideo === true && !hasTouchEvent) {
            ge("#CustomDownloadVideoDIV", main).style.display = "flex";
            ge("#CustomDownloadVideo", main).checked = FullPictureLoadCustomDownloadVideo == 1 ? true : false;
        }
        ge("#CancelBtn", main).addEventListener("click", () => {
            mainElement.remove();
            _unsafeWindow.removeEventListener("resize", topDistance);
            setTimeout(() => (isOpenOptionsUI = false), 200);
        });
        ge("#ResetBtn", main).addEventListener("click", event => {
            event.preventDefault();
            setDefault();
            location.reload();
        });
        ge("#SaveBtn", main).addEventListener("click", event => {
            event.preventDefault();
            options.icon = ge("#icon", main).checked == true ? 1 : 0;
            options.autoInsert = ge("#AutoInsertImg", main).checked == true ? 1 : 0;
            _GM_setValue("ShowFullPictureLoadFixedMenu", ge("#ShowFixedMenu", main).checked == true ? 1 : 0);
            _GM_setValue("FavorOpenInNewTab", ge("#FavorNewTab", main).checked == true ? 1 : 0);
            _GM_setValue("FullPictureLoadMsgPos", ge("#MsgPos", main).value);
            options.threading = ge("#Threading", main).value;
            options.zip = ge("#Zip", main).checked == true ? 1 : 0;
            options.file_extension = ge("#Extension", main).value;
            _GM_setValue("convertWebpToJpg", ge("#Convert", main).checked == true ? 1 : 0);
            options.comic = ge("#Comic", main).checked == true ? 1 : 0;
            options.autoDownload = ge("#AutoDownload", main).checked == true ? 1 : 0;
            options.autoDownloadCountdown = ge("#Countdown", main).value;
            options.doubleTouchNext = ge("#Double", main).checked == true ? 1 : 0;
            options.fancybox = ge("#Fancybox", main).checked == true ? 1 : 0;
            _GM_setValue("FancyboxSlideshowTimeout", ge("#FancyboxSlideshowTimeout", main).value);
            _GM_setValue("FancyboxWheel", ge("#FancyboxWheel", main).value);
            _GM_setValue("FancyboxSlideshowTransition", ge("#FancyboxTransition", main).value);
            options.zoom = ge("#Zoom", main).value;
            options.column = ge("#Column", main).value;
            options.viewMode = ge("#viewMode", main).checked == true ? 1 : 0;
            options.shadowGallery = ge("#ShadowGalleryMode", main).checked == true ? 1 : 0;
            options.autoExport = ge("#autoExport", main).checked == true ? 1 : 0;
            config.shadowGalleryWheel = ge("#ShadowGalleryWheel", main).value;
            saveConfig(config);
            if (siteData.category != "lazyLoad" && ("capture" in siteData) || isString(siteData.imgs) && !isArray(siteData.insertImg)) {
                ge("#ShowEye", main).checked == true ? localStorage.setItem("FullPictureLoadShowEye", 1) : localStorage.setItem("FullPictureLoadShowEye", 0);
            }
            if (!!downloadVideo && downloadVideo === true && !hasTouchEvent) {
                ge("#CustomDownloadVideo", main).checked == true ? localStorage.setItem("FullPictureLoadCustomDownloadVideo", 1) : localStorage.setItem("FullPictureLoadCustomDownloadVideo", 0);
            }
            let jsonStr = JSON.stringify(options);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
            location.reload();
        });
        shadow.appendChild(main);
        topDistance();
        _unsafeWindow.addEventListener("resize", topDistance);
    };

    //腳本的CSS樣式
    let FullPictureLoadMsgPos = _GM_getValue("FullPictureLoadMsgPos", 0);

    let msgPosCss;
    if (FullPictureLoadMsgPos == 1) {
        msgPosCss = `
    top: 10px;
    left: 10px;
        `;
    } else if (FullPictureLoadMsgPos == 2) {
        msgPosCss = `
    top: 10px;
    right: 10px;
        `;
    } else if (FullPictureLoadMsgPos == 3) {
        msgPosCss = `
    bottom: 10px;
    left: 72px;
        `;
    } else if (FullPictureLoadMsgPos == 4) {
        msgPosCss = `
    bottom: 10px;
    right: 10px;
        `;
    } else {
        msgPosCss = `
    top: 30%;
    left: 50%;
    margin-left: -180px;
        `;
    }

    const FullPictureLoadStyle = `
.fancybox-container,
.fancybox__container,
.viewer-container {
    z-index: 2147483647 !important;
}

.fancybox-image,
.viewer-canvas > img {
    opacity: 1 !important;
}

.viewer-backdrop {
    background-color: rgba(0, 0, 0, 0.96) !important;
}

.FullPictureLoadImageReturnTop {
    position: fixed;
    right: 10px;
    bottom: 80px;
    width: 53px !important;
    height: 53px !important;
    border: unset;
    z-index: 99;
    opacity: 0.6;
}

#FullPictureLoad {
    display: block !important;
}

#FullPictureLoadGoToLastImage {
    bottom: 66px !important;
}

#FullPictureLoadGoToFirstImage {
    bottom: 108px !important;
}

.FullPictureLoadFixedBtn {
    position: fixed !important;
    left: 24px;
    width: 32px !important;
    height: 32px !important;
    border: unset !important;
    border-radius: unset !important;
    margin: unset !important;
    padding: unset !important;
    z-index: 2147483640 !important;
    cursor: pointer !important;
    pointer-events: auto !important;
    background: unset !important;
    min-width: unset !important;
    min-height: unset !important;
    opacity: 0.8 !important;
}

#FullPictureLoadEye {
    position: fixed !important;
    display: block !important;
    width: 32px !important;
    height: 32px !important;
    border-radius: unset !important;
    z-index: 2147483600 !important;
    opacity: 1 !important;
    cursor: pointer !important;
    pointer-events: auto !important;
}

#FullPictureLoadFixedMenu {
    text-align: center !important;
    font-family: Arial, sans-serif !important;
    font-size: 14px !important;
    color: #000000 !important;
    height: auto !important;
    padding: 5px 5px 2px 5px !important;
    position: fixed !important;
    left: 10px !important;
    bottom: 152px !important;
    border: #ccc 1px solid !important;
    border-radius: 3px !important;
    background-color: #fff !important;
    box-sizing: unset !important;
    opacity: 0.4;
    z-index: 2147483640 !important;
}

#FullPictureLoadFixedMenu > div,
#FullPictureLoadFixedMenuB > div {
    height: 24px !important;
    line-height: 24px !important;
    overflow: hidden !important;
    font-size: 14px !important;
    text-shadow: unset !important;
    text-align: center !important;
    letter-spacing: unset !important;
    border: #ccc 1px solid !important;
    background-color: #f6f6f6 !important;
    padding: 0 5px 0 5px !important;
    margin: 0 2px 3px 0 !important;
    cursor: pointer !important;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

#FullPictureLoadFixedMenu:hover,
.FullPictureLoadFixedBtn:hover {
    opacity: 1 !important;
}

#FullPictureLoadFixedMenu .itemNoShow {
    display: none !important;
}

#FullPictureLoadFixedMenuB {
    text-align: center !important;
    font-family: Arial, sans-serif !important;
    font-size: 14px !important;
    color: #000000 !important;
    width: 112px !important;
    height: auto !important;
    min-height: 29px !important;
    padding: 5px 5px 2px 5px !important;
    position: fixed !important;
    border: #ccc 1px solid !important;
    border-radius: 3px !important;
    background-color: #fff !important;
    opacity: 1;
    z-index: 2147483600 !important;
    letter-spacing: unset !important;
}

#FullPictureLoadMsg {
    font-family: Arial, sans-serif !important;
    font-size: 24px;
    font-weight: bold;
    text-align: center;
    line-height: 50px;
    color: #ffffff;
    width: 360px;
    height: auto;
    ${msgPosCss}
    padding: 0px !important;
    background-color: #000;
    border: 1px solid #303030;
    border-radius: 10px;
    position: fixed;
    z-index: 2147483640;
    opacity: 0.7;
}

.FullPictureLoadImage:not(.small) {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: unset !important;
    display: block !important;
    float: unset !important;
    opacity: 1 !important;
    border: none !important;
    border-radius: unset !important;
    padding: 0 !important;
    margin: 0 auto !important;
    transition: unset !important;
    transform: unset !important;
}

.FullPictureLoadImage.small {
    width: auto;
    height: auto;
    max-width: 100% !important;
    max-height: 100% !important;
    min-height: 50x !important;
    display: block !important;
    float: unset !important;
    opacity: 1 !important;
    border: none !important;
    border-radius: unset !important;
    padding: 0 !important;
    margin: auto;
    transition: unset !important;
    transform: unset !important;
}

#FullPictureLoadImgBox {
    display: block;
    opacity: 1 !important;
    border: none !important;
    border-radius: unset !important;
    padding: 0 !important;
    margin: 0 auto 10px !important;
}

#FullPictureLoadImgBox > div {
    height: auto;
}

a[data-fancybox="FullPictureLoadImageOriginal"],
a[data-fancybox="FullPictureLoadImageSmall"] {
    position: unset !important;
    padding: 0 !important;
    margin: 0 auto !important;
    display: block !important;
    color: unset !important;
    border: unset !important;
    --local-colour1-primary: unset !important;
    --local-colour1-secondary: unset !important;
    --local-colour2-primary: unset !important;
    --local-colour2-secondary: unset !important;
    transition-property: unset !important;
    transition-duration: unset !important;
}

#FullPictureLoadEnd {
    font-size: 20px;
    height: 30px;
    width: 100%;
    line-height: 30px;
    text-align: center !important;
    margin: 5px auto !important;
}

#FullPictureLoadEnd
    ~ *:not(
        h3,
        ul,
        p,
        .tags,
        [id^="Full"],
        [class^="Full"],
        a[href="javascript:void(0);"],
        .post-info,
        .post-tags,
        .article-tags,
        *[class^="fancybox"],
        div[tabindex],
        .row,
        .text-center,
        .link-d,
        #myrating,
        .gallery-a,
        .pagination,
        div[class^="picnext"],
        a.zwf,
        .bo_nav
    ) {
    display: none !important;
}

.FullPictureLoadLoading {
    font-size: 20px;
    text-align: center;
    height: 30px;
    line-height: 30px;
    margin: 5px auto !important;
    border: none !important;
}

.autoPagerTitle {
    width: auto;
    height: 30px;
    font-size: 18px;
    color: black;
    font-family: Arial, sans-serif !important;
    line-height: 29px;
    text-align: center;
    overflow: hidden;
    display: block;
    margin: 10px 5px;
    border: 1px solid #e0e0e0;
    background-color: #f0f0f0;
    background: -webkit-gradient(
        linear,
        0 0,
        0 100%,
        from(#f9f9f9),
        to(#f0f0f0)
    );
    background: -moz-linear-gradient(top, #f9f9f9, #f0f0f0);
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.6);
    border-radius: 5px;
}

.autoPagerTitle.off {
    color: white;
    border: 1px solid #0e0e0e;
    background-color: #0f0f0f;
    background: -webkit-gradient(
        linear,
        0 0,
        0 100%,
        from(#9f9f9f),
        to(#0f0f0f)
    );
    background: -moz-linear-gradient(top, #9f9f9f, #0f0f0f);
    box-shadow: 0 0 5px rgba(255, 255, 255, 0.6);
    border-radius: 5px;
}

.autoPagerTitle a:-webkit-any-link {
    font-family: Arial, sans-serif !important;
    color: black;
}

.autoPagerTitle.off a:-webkit-any-link {
    color: white;
}

.autoPagerLoading {
    width: auto;
    height: auto;
    max-width: 60px !important;
    max-height: 60px !important;
    display: block !important;
    opacity: 1 !important;
    border: none !important;
    border-radius: unset !important;
    padding: 0 !important;
    margin: 20px auto !important;
}

#FullPictureLoadOptionsButtonParentDiv {
    max-width: 100% !important;
    height: 80px !important;
}

.FullPictureLoadPageButtonTop {
    height: 24px;
    min-height: unset !important;
    padding: 1px !important;
    margin: 10px 0 10px 0 !important;
    border-radius: unset !important;
    appearance: auto;
    text-rendering: auto;
    color: black !important;
    letter-spacing: normal;
    word-spacing: normal;
    line-height: normal;
    font-size: 14px !important;
    font-weight: unset !important;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;
    display: inline-block !important;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    align-items: flex-start;
    cursor: default;
    box-sizing: border-box;
    background: unset !important;
    background-color: #f6f6f6 !important;
    border: 1px solid #a0a0a0 !important;
    cursor: pointer !important;
}

.FullPictureLoadPageButtonBottom {
    height: 24px;
    min-height: unset !important;
    padding: 1px !important;
    margin: 0 0 6px 0 !important;
    border-radius: unset !important;
    appearance: auto;
    text-rendering: auto;
    color: black !important;
    letter-spacing: normal;
    word-spacing: normal;
    line-height: normal;
    font-size: 14px !important;
    font-weight: unset !important;
    text-transform: none;
    text-indent: 0px;
    text-shadow: none;
    display: inline-block !important;
    text-align: center;
    align-items: flex-start;
    cursor: default;
    box-sizing: border-box;
    background: unset !important;
    background-color: #f6f6f6 !important;
    border: 1px solid #a0a0a0 !important;
    cursor: pointer !important;
}

#FullPictureLoadOptions button:hover,
.FullPictureLoadPageButtonTop:hover,
.FullPictureLoadPageButtonBottom:hover {
    color: black !important;
}

.viewer-open:not(.fancybox-active) {
    overflow: unset !important;
    padding-right: 0px !important;
}

.fancybox-infobar *,
.fancybox__infobar,
a[data-fancybox-download],
a[data-fancybox-download]:hover,
a[data-fancybox-download]:link,
a[data-fancybox-download]:visited,
a[data-fancybox-download]:active {
    color: white;
}

a[data-fancybox]:hover {
    opacity: 1 !important;
}
.viewer-toolbar > ul > li {
    line-height: unset !important;
}
        `;

    let noGoToFirstImage = _GM_getValue("noGoToFirstImage", 0);
    let TurnOffImageNavigationShortcutKeys = _GM_getValue("TurnOffImageNavigationShortcutKeys", 0);
    let ShowFullPictureLoadFixedMenu = _GM_getValue("ShowFullPictureLoadFixedMenu", 1);
    let autoScrollAllElement = _GM_getValue("autoScrollAllElement", 0);
    let convertWebpToJpg = _GM_getValue("convertWebpToJpg", 0);

    let lazyLoadFullResolution = _GM_getValue("lazyLoadFullResolution", 0);
    let lazyLoadPreloadImages = _GM_getValue("lazyLoadPreloadImages", 0);

    let comicInfiniteScrollMode = localStorage.getItem("FullPictureLoadComicInfiniteScrollMode") ?? 0;

    const addLazyLoadFullResolutionMenu = async () => {
        _GM_registerMenuCommand(lazyLoadFullResolution == 0 ? "❌ " + displayLanguage.str_111 : "✔️ " + displayLanguage.str_111, () => {
            lazyLoadFullResolution == 0 ? _GM_setValue("lazyLoadFullResolution", 1) : _GM_setValue("lazyLoadFullResolution", 0);
            location.reload();
        });
        _GM_registerMenuCommand(lazyLoadPreloadImages == 0 ? "❌ " + displayLanguage.str_113 : "✔️ " + displayLanguage.str_113, () => {
            lazyLoadPreloadImages == 0 ? _GM_setValue("lazyLoadPreloadImages", 1) : _GM_setValue("lazyLoadPreloadImages", 0);
            location.reload();
        });
    };

    let E_HENTAI_LoadOriginalImage = _GM_getValue("E_HENTAI_LoadOriginalImage", 0);

    if (/^https?:\/\/(e-hentai|exhentai).org\//.test(fn.url)) {
        _GM_registerMenuCommand(E_HENTAI_LoadOriginalImage == 0 ? "❌ " + displayLanguage.str_114 : "✔️ " + displayLanguage.str_114, () => {
            E_HENTAI_LoadOriginalImage == 0 ? _GM_setValue("E_HENTAI_LoadOriginalImage", 1) : _GM_setValue("E_HENTAI_LoadOriginalImage", 0);
            location.reload();
        });
    }

    let setYinawSinaOriginalURL = _GM_getValue("setYinawSinaOriginalURL", 0);

    if (/^https?:\/\/yinaw\.com\/\d+\.html$/.test(fn.url)) {
        _GM_registerMenuCommand(setYinawSinaOriginalURL == 0 ? "❌ 壹纳网使用原始新浪图床链接" : "✔️ 壹纳网使用原始新浪图床链接", () => {
            setYinawSinaOriginalURL == 0 ? _GM_setValue("setYinawSinaOriginalURL", 1) : _GM_setValue("setYinawSinaOriginalURL", 0);
            location.reload();
        });
    }

    //確認選項設置資料
    const checkOptionsData = async () => {
        const getOptionsData = localStorage.getItem("FullPictureLoadOptions");
        if (getOptionsData === null && options.autoDownload !== 1) {
            let jsonStr = JSON.stringify(defaultOptions);
            localStorage.setItem("FullPictureLoadOptions", jsonStr);
        } else if (options.autoDownload !== 1) {
            let optionsJson = JSON.parse(getOptionsData);
            options = Object.assign(defaultOptions, optionsJson);
            //debug("\nFull Picture Load Options Json\n", options);
        }
    };

    //Fancybox5的語系
    const Fancyboxl10nV5 = () => {
        let l10n;
        switch (language) {
            case "zh-TW":
            case "zh-HK":
            case "zh-Hant-TW":
            case "zh-Hant-HK":
                l10n = {
                    PANUP: "上移",
                    PANDOWN: "下移",
                    PANLEFT: "左移",
                    PANRIGHT: "右移",
                    ZOOMIN: "放大",
                    ZOOMOUT: "縮小",
                    TOGGLEZOOM: "切換縮放等級",
                    TOGGLE1TO1: "切換縮放等級",
                    ITERATEZOOM: "切換縮放等級",
                    ROTATECCW: "逆時針旋轉",
                    ROTATECW: "順時針旋轉",
                    FLIPX: "水平翻轉",
                    FLIPY: "垂直翻轉",
                    FITX: "水平適應",
                    FITY: "垂直適應",
                    RESET: "重設",
                    TOGGLEFS: "切換全螢幕",
                    CLOSE: "關閉",
                    NEXT: "下一個",
                    PREV: "上一個",
                    MODAL: "使用 ESC 鍵關閉",
                    ERROR: "發生了錯誤,請稍後再試",
                    IMAGE_ERROR: "找不到圖像",
                    ELEMENT_NOT_FOUND: "找不到 HTML 元素",
                    AJAX_NOT_FOUND: "載入 AJAX 時出錯: 未找到",
                    AJAX_FORBIDDEN: "載入 AJAX 時出錯: 被阻止",
                    IFRAME_ERROR: "載入頁面出錯",
                    TOGGLE_ZOOM: "切換縮放等級",
                    TOGGLE_THUMBS: "切換縮圖",
                    TOGGLE_SLIDESHOW: "切換幻燈片",
                    TOGGLE_FULLSCREEN: "切換全螢幕",
                    DOWNLOAD: "下載"
                };
                break;
            case "zh":
            case "zh-CN":
            case "zh-Hans-CN":
                l10n = {
                    PANUP: "上移",
                    PANDOWN: "下移",
                    PANLEFT: "左移",
                    PANRIGHT: "右移",
                    ZOOMIN: "放大",
                    ZOOMOUT: "缩小",
                    TOGGLEZOOM: "切换缩放级别",
                    TOGGLE1TO1: "切换缩放级别",
                    ITERATEZOOM: "切换缩放级别",
                    ROTATECCW: "逆时针旋转",
                    ROTATECW: "顺时针旋转",
                    FLIPX: "水平翻转",
                    FLIPY: "垂直翻转",
                    FITX: "水平适应",
                    FITY: "垂直适应",
                    RESET: "重置",
                    TOGGLEFS: "切换全屏",
                    CLOSE: "关闭",
                    NEXT: "下一个",
                    PREV: "上一个",
                    MODAL: "使用 ESC 键关闭",
                    ERROR: "发生了错误,请稍后再试",
                    IMAGE_ERROR: "找不到图像",
                    ELEMENT_NOT_FOUND: "找不到 HTML 元素",
                    AJAX_NOT_FOUND: "载入 AJAX 时出错: 未找到",
                    AJAX_FORBIDDEN: "载入 AJAX 时出错: 被阻止",
                    IFRAME_ERROR: "加载页面出错",
                    TOGGLE_ZOOM: "切换缩放级别",
                    TOGGLE_THUMBS: "切换缩略图",
                    TOGGLE_SLIDESHOW: "切换幻灯片",
                    TOGGLE_FULLSCREEN: "切换全屏",
                    DOWNLOAD: "下载"
                };
                break;
            default:
                l10n = "EN";
        }
        if (_unsafeWindow?.Fancybox?.defaults?.l10n && l10n != "EN") {
            _unsafeWindow.Fancybox.defaults.l10n = l10n;
            _unsafeWindow.Fancybox.defaults.animated = false;
            //debug("\nFancybox 5.0.xx 預設選項物件 Fancybox.defaults\n", Fancybox.defaults);
        }
        return l10n;
    };

    //Fancybox3的語系
    const Fancyboxi18nV3 = async () => {
        if (siteData.fancybox?.js === false) return;
        switch (language) {
            case "zh-TW":
            case "zh-HK":
            case "zh-Hant-TW":
            case "zh-Hant-HK":
                _unsafeWindow.jQuery.fancybox.defaults.i18n.tw = {
                    "CLOSE": "關閉",
                    "NEXT": "下一個",
                    "PREV": "上一個",
                    "ERROR": "無法載入請求的內容。 <br/> 請稍後重試。",
                    "PLAY_START": "開始幻燈片",
                    "PLAY_STOP": "暫停幻燈片",
                    "FULL_SCREEN": "全螢幕",
                    "THUMBS": "縮圖",
                    "DOWNLOAD": "下載",
                    "SHARE": "分享",
                    "ZOOM": "縮放"
                };
                _unsafeWindow.jQuery.fancybox.defaults.lang = "tw";
                break;
            case "zh":
            case "zh-CN":
            case "zh-Hans-CN":
                _unsafeWindow.jQuery.fancybox.defaults.i18n.cn = {
                    "CLOSE": "关闭",
                    "NEXT": "下一个",
                    "PREV": "上一个",
                    "ERROR": "无法加载请求的内容。 <br/> 请稍后重试。",
                    "PLAY_START": "开始幻灯片",
                    "PLAY_STOP": "暂停幻灯片",
                    "FULL_SCREEN": "全面屏",
                    "THUMBS": "缩略图",
                    "DOWNLOAD": "下载",
                    "SHARE": "分享",
                    "ZOOM": "缩放"
                };
                _unsafeWindow.jQuery.fancybox.defaults.lang = "cn";
                break;
        }
    };

    //更改Fancybox3的預設選項
    const FancyboxOptionsV3 = () => {
        if (siteData.fancybox?.js === false) return; //"download",
        _unsafeWindow.jQuery.fancybox.defaults.buttons = ["zoom", "slideShow", "fullScreen", "thumbs", "close"];
        _unsafeWindow.jQuery.fancybox.defaults.loop = true;
        _unsafeWindow.jQuery.fancybox.defaults.toolbar = true;
        //console.log("fancybox 3.5.7 選項物件", _unsafeWindow.jQuery.fancybox.defaults);
    };

    //頁面容器快捷鍵
    const addKeyEvent = async event => {
        if (isOpenFilter || isOpenFancybox || isOpenGallery || ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
        if (event.ctrlKey && event.altKey && (event.code === "KeyC" || event.key === "c" || event.key === "C")) return;
        if (event.ctrlKey && (event.code === "NumpadDecimal" || event.code === "Period" || event.key === ".")) return;
        if ((event.code != "Escape" || event.key != "Escape") && isOpenOptionsUI) return;
        if (["INPUT", "TEXTAREA"].some(n => n === document.activeElement.tagName)) return;
        if (event.ctrlKey && event.altKey && (event.code === "KeyT" || event.key === "t" || event.key === "T")) {
            let str = _unsafeWindow.getSelection().toString();
            str == "" ? null : customTitle = str;
            let newTitle = await prompt("New Title", customTitle);
            newTitle == null ? null : customTitle = newTitle;
            fn.showMsg(displayLanguage.str_118);
            debug("圖集新標題", newTitle || customTitle);
        }
        if (event.code === "KeyF" || event.key === "f" || event.key === "F") { //F鍵
            return createFilterDownload();
        }
        if (event.code === "KeyG" || event.key === "g" || event.key === "G") { //G鍵
            return createShadowGallery();
        }
        if ((!event.ctrlKey && !event.shiftKey) && (event.code === "KeyI" || event.key === "i" || event.key === "I")) { //I鍵
            return createIframeGallery();
        }
        if (event.code === "Numpad0" || event.key === "0") { //數字鍵0
            fastDownload = false;
            return DownloadFn();
        }
        if (event.code === "Numpad1" || event.key === "1") return copyImgSrcText(); //數字鍵1
        if (event.code === "Numpad2" || event.key === "2") return goToImg("first"); //數字鍵2
        if (event.code === "Numpad3" || event.key === "3") { //數字鍵3
            fastDownload = true;
            return DownloadFn();
        }
        if (event.code === "Numpad4" || event.key === "4") return goToImg("last"); //數字鍵4
        if (event.code === "Numpad5" || event.key === "5") return toggleImgMode(); //數字鍵5
        if (event.code === "Numpad6" || event.key === "6") { //數字鍵6
            if ("fn" in siteData && isFn(siteData.fn)) {
                return siteData.fn();
            } else {
                return autoScrollEles();
            }
        }
        if (event.code === "Numpad7" || event.key === "7") return exportImgSrcText(); //數字鍵7
        if (event.code === "Numpad8" || event.key === "8") return newTabView(); //數字鍵8
        if (event.code === "Numpad9" || event.key === "9") return createFavorShadowElement(); //數字鍵9
        if (event.code === "NumpadSubtract" || event.key === "-") { //數字鍵-
            fn.clearSetTimeout();
            return reduceZoom();
        }
        if (event.code === "NumpadAdd" || event.key === "+") { //數字鍵+
            fn.clearSetTimeout();
            return increaseZoom();
        }
        if (event.code === "NumpadDecimal" || event.code === "Period" || event.key === ".") { //數字鍵.
            fn.clearSetTimeout();
            return cancelZoom();
        }
        if (event.code === "NumpadMultiply" || event.key === "*") { //數字鍵*
            createPictureLoadOptionsShadowElement();
        }
        if (event.code === "Escape" || event.key === "Escape") { //Esc鍵
            if (!isStopDownload && isDownloading) {
                isStopDownload = true;
                isDownloading = false;
                fn.clearAllTimer(2);
                fn.showMsg(displayLanguage.str_149);
            }
            if (isCountdowning) {
                isCountdowning = false;
                isStopDownload = true;
                fn.clearAllTimer(2);
                fn.showMsg(displayLanguage.str_149);
            }
            isEsc = true;
            setTimeout(() => (isEsc = false), 200);
            let UI = ge("#FullPictureLoadOptionsShadowElement");
            if (UI) {
                UI.remove();
                _unsafeWindow.removeEventListener("resize", topDistance);
                setTimeout(() => (isOpenOptionsUI = false), 200);
            }
            return;
        }
        if (event.code === "NumpadDivide" || event.key === "/") { //數字鍵/
            fn.showMsg(displayLanguage.str_91);
            setDefault(); //重置用戶設定恢復為預設選項
            setTimeout(() => location.reload(), 1000);
            return;
        }
    };

    const toggleUI = async () => {
        if (!"SPA" in siteData || !isFn(siteData.SPA) || !!ge(".FullPictureLoadImage") || isOpenMenu || isFetching) return;
        const validPage = siteData.SPA();
        if (validPage === true || isPromise(validPage)) {
            isValidPage = true;
            if (isAddFullPictureLoadButton) addFullPictureLoadButton();
            if (isAddFullPictureLoadFixedMenu) addFullPictureLoadFixedMenu();
            if (isAddNewTabViewButton) addNewTabViewButton();
            if (isPromise(validPage)) {
                isFetching = true;
                await validPage;
                isFetching = false;
            }
            if (!isAddKeyEvent) {
                document.addEventListener("keydown", addKeyEvent);
                isAddKeyEvent = true;
            }
            if ("insertImg" in siteData) {
                let [, insertMode, ] = siteData.insertImg;
                if (insertMode === 1 || insertMode === 2) {
                    if (options.autoInsert == 1) {
                        await fn.immediateInsertImg();
                    }
                    if (options.shadowGallery == 1 && siteData.aeg != 0) {
                        await createShadowGallery();
                    }
                }
            }
        } else {
            fn.remove(".FullPictureLoadFixedBtn,#FullPictureLoadEye,#FullPictureLoadFixedMenu,#FullPictureLoadFixedMenuB");
            document.removeEventListener("keydown", addKeyEvent);
            isAddKeyEvent = false;
            isValidPage = false;
        }
        await delay(200);
    };

    const getNextLink = async (next, text = "\n圖片全載NEXT:") => {
        let tempLink = null;
        isFn(next) ? tempLink = await next() : tempLink = fn.ge(next);
        debug(text, tempLink);
        try {
            if (tempLink !== null && tempLink !== undefined) {
                if (isString(tempLink)) {
                    nextLink = tempLink;
                    return tempLink;
                }
                if (isEle(tempLink) && tempLink?.tagName === "A") {
                    try {
                        if (/^http/.test(tempLink.href)) {
                            nextLink = tempLink.href;
                            return tempLink;
                        } else {
                            nextElement = tempLink;
                        }
                    } catch {}
                } else if (isEle(tempLink)) {
                    nextElement = tempLink;
                }
            }
        } catch {}
        return tempLink;
    };

    const getTitle = async (title) => {
        let text;
        if (isString(title)) {
            text = fn.dt({
                s: title
            });
        } else if (isFn(title)) {
            text = await title();
        }
        return text;
    };

    let showOptions = false;
    let comicSwitch = false;

    //遍歷腳本站點JSON數據
    for (const [i, data] of customData.entries()) {
        tempData = data;
        let check = false;
        try {
            if ("url" in data) {
                const url = data.url;
                if (isObject(url)) {
                    check = fn.checkUrl(url);
                } else if (isFn(url)) {
                    check = await url();
                }
            }
            if ("reg" in data) {
                const reg = data.reg;
                if (isRegExp(reg)) {
                    check = reg.test(siteUrl);
                } else if (isArray(reg)) {
                    check = reg.some(r => r.test(siteUrl));
                } else if (isFn(reg)) {
                    check = await reg();
                }
            }
            if (check) {
                const category = data.category;
                if (category == "comic" && data.enable == 0) {
                    showOptions = true;
                    comicSwitch = true;
                }
                const delayTime = data.delay;
                if (isNumber(delayTime)) await delay(delayTime);
                checkOptionsData();
                if (data.enable == 0) {
                    //checkOptionsData();
                    if (options.comic == 1 && category === "comic") {
                        showOptions = true;
                        options.enable = 1;
                        debug("\n漫畫類預設關閉的此站規則已開啟");
                    } else {
                        //showOptions = true;
                        debug("\n此規則禁用", data);
                        continue;
                    }
                }
                //if (data.enable != 0) checkOptionsData();
                const include = data.include;
                if (isString(include)) {
                    if (!fn.ge(include)) {
                        debug("\n頁面沒有包含必須的元素", data);
                        continue;
                    }
                } else if (isArray(include)) {
                    const checkEles = include.every(e => !!fn.ge(e));
                    if (!checkEles) {
                        debug("\n頁面沒有包含必須的所有元素", data);
                        continue;
                    }
                }
                const exclude = data.exclude;
                if (isString(exclude)) {
                    if (!!fn.ge(exclude)) {
                        debug("\n頁面包含必須排除的元素", data);
                        continue;
                    }
                } else if (isArray(exclude)) {
                    const checkEles = exclude.some(s => !!fn.ge(s));
                    if (checkEles) {
                        debug("\n頁面包含陣列選擇器中必須排除的元素", data);
                        continue;
                    }
                }
                if ("autoPager" in data && isObject(data.autoPager) && category !== "comic autoPager") {
                    if (!fn.checkAutoPagerEle(data.autoPager)) {
                        siteData = {};
                        _this = {};
                        continue;
                    }
                }
                siteData = data;
                _this = data;
                if (!data.category.includes("autoPager") && !["lazyLoad", "none", "ad"].some(c => c === data.category)) {
                    showOptions = true;
                }
                const loadingBakBlobURL = fn.dataURLtoBlobURL(loading_bak);
                const checkBlobURL = await fn.checkImgStatus(loadingBakBlobURL, 0);
                if (checkBlobURL.ok) {
                    loading_bak = loadingBakBlobURL;
                    autoPagerLoading_gif = fn.dataURLtoBlobURL(autoPagerLoading_gif);
                }
                break;
            }
        } catch (error) {
            console.error("圖片全載規則出錯", error);
            debug("圖片全載規則出錯", data);
            debug("出錯之前的規則", customData[i - 1]);
            return;
        }
    }

    if (showOptions) {
        //_unsafeWindow.FullPictureLoadCustomData = customData;
        //debug("\n圖片全載開啟了GM選單?\n", showOptions);
        _GM_registerMenuCommand(displayLanguage.str_67, () => createPictureLoadOptionsShadowElement());
        if (!ge("#FullPictureLoadMainStyle") && !["none", "ad"].some(c => c === siteData.category)) {
            fn.css(FullPictureLoadStyle, "FullPictureLoadMainStyle");
        }
    }

    //if (!("category" in siteData)) {
    //_GM_unregisterMenuCommand(FullPictureLoadBlacklist_menu_command_id);
    //return;
    //}

    try {
        if (("category" in siteData) && !ge("#FullPictureLoadMainStyle") && !["none", "ad"].some(c => c === siteData.category)) {
            fn.css(FullPictureLoadStyle, "FullPictureLoadMainStyle");
        }
        if (("category" in siteData) && options.fancybox == 1 && siteData.category !== "none" && !isObject(siteData.autoPager) && siteData.fancybox?.v == 3 && siteData.fancybox?.insertLibrarys == 1) {
            addLibrarysV3();
            Fancyboxi18nV3();
            FancyboxOptionsV3();
        } else if (("category" in siteData) && options.fancybox == 1 && !siteData.category?.includes("autoPager") && !["lazyLoad", "none", "ad"].some(c => c === siteData.category) && !fancyboxBlackList()) {
            addLibrarysV5();
            Fancyboxl10nV5();
            fn.css(FancyboxV5Css, "FancyboxV5Css");
        }
        if ("init" in siteData) {
            const init_code = siteData.init;
            if (isString(init_code)) {
                await new Function("siteData", "fn", '"use strict";' + init_code)(siteData, fn);
            } else if (isFn(init_code)) {
                await init_code();
            }
        }
        if (("category" in siteData) && !ge("#addLibrarysV3") && options.fancybox == 1 && siteData.category !== "none" && !isObject(siteData.autoPager) && siteData.fancybox?.v == 3 && siteData.fancybox?.insertLibrarys == 1) {
            fn.css(FancyboxV3Css, "FancyboxV3Css");
        } else if (("category" in siteData) && !ge("#FancyboxV5Css") && options.fancybox == 1 && !siteData.category?.includes("autoPager") && !["lazyLoad", "none", "ad"].some(c => c === siteData.category) && !fancyboxBlackList()) {
            fn.css(FancyboxV5Css, "FancyboxV5Css");
        }
        if (("category" in siteData) && !ge("#FullPictureLoadMainStyle") && !["none", "ad"].some(c => c === siteData.category)) {
            fn.css(FullPictureLoadStyle, "FullPictureLoadMainStyle");
        }
        if ("css" in siteData && isString(siteData.css)) {
            fn.css(siteData.css);
        }
        if ("hide" in siteData && (isString(siteData.hide) || isArray(siteData.hide))) {
            let text = siteData.hide;
            if (isArray(text)) {
                text = text.join(",");
            }
            text += "{display:none!important;}";
            fn.css(text);
        }
        if (_GM_getValue("FancyboxSlideshowTransition") === "no") {
            fn.css(".fancybox__container .to-next>.fancybox__content,.fancybox__container .to-prev>.fancybox__content{display:none!important}");
        }
        if ("imgs" in siteData) {
            debug("\nCSS/Xpath/JS選擇器:" + siteData.imgs);
        }
        if ("threading" in siteData && isNumber(siteData.threading)) {
            options.threading = siteData.threading;
            debug("\n下載線程數:" + options.threading);
        }
        if ("customTitle" in siteData) {
            customTitle = await getTitle(siteData.customTitle);
            if (isString(customTitle)) {
                customTitle = fn.dt({
                    t: customTitle
                });
            }
            debug(`\n自定義標題:${customTitle}`);
        }
        if ("observerTitle" in siteData && isBoolean(siteData.observerTitle) && siteData.observerTitle === true) {
            const observerTitle_CB = async (mutationList, observer) => {
                //console.log(mutationList);
                if (mutationList) {
                    const mutationList_removedNodes = [...mutationList].filter(item => item.type === "childList" && item?.removedNodes?.length > 0);
                    if (mutationList_removedNodes.length > 0) {
                        for (const mutation of mutationList_removedNodes) {
                            const removedNodes = mutation.removedNodes;
                            for (const node of removedNodes) {
                                if (node?.id == "FullPictureLoadOptionsShadowElement" || node?.id == "FullPictureLoadShadowGallery" || node?.id == "FullPictureLoadIframeGallery") {
                                    return;
                                }
                            }
                        }
                    }
                }
                if (observer) {
                    observer.disconnect();
                    setTimeout(async () => {
                        const body = await fn.waitEle("body");
                        observer.observe(body, MutationObserverConfig);
                        if (!isOpenGallery) {
                            await toggleUI();
                        }
                    }, 200);
                }
                if (mutationList) {
                    try {
                        const mutationList_addedNodes = [...mutationList].filter(item => item.type === "childList" && item?.addedNodes?.length > 0);
                        if (mutationList_addedNodes.length === 0) {
                            return;
                        }
                        const strings = ["FullPictureLoad", "FullPictureLoadOptionsShadowElement", "FullPictureLoadShadowGallery", "FullPictureLoadIframeGallery", "pagetual", "comicRead", "Autopage", "pv-"];
                        for (const mutation of mutationList_addedNodes) {
                            const attributes = [mutation?.target?.id, mutation?.target?.className, mutation?.target?.name].filter(e => e);
                            const checkM = attributes.some(attr => strings.some(str => attr?.startsWith(str)));
                            if (checkM) {
                                return;
                            }
                            const addedNodes = mutation.addedNodes;
                            for (const node of addedNodes) {
                                const attributes = [node?.id, node?.className, node?.name].filter(e => e);
                                const checkN = attributes.some(attr => strings.some(str => attr?.startsWith(str)));
                                if (checkN) {
                                    return;
                                }
                            }
                        }
                        //console.log(mutationList_addedNodes);
                    } catch {}
                }
                if (isFetching || isDownloading) return;
                await toggleUI();
                const newCustomTitle = await getTitle(siteData.customTitle);
                if ("capture" in siteData && !newCustomTitle) {
                    captureSrcB(1);
                }
                if (customTitle !== newCustomTitle && newCustomTitle !== null && newCustomTitle !== undefined && newCustomTitle !== "") {
                    customTitle = newCustomTitle;
                    debug(`\n自定義標題:${newCustomTitle}`);
                    if ("capture" in siteData) {
                        captureSrcB();
                    }
                    if ("next" in siteData) {
                        await getNextLink(siteData.next, "\n標題變換 nextLink:");
                    }
                }
            };
            const MutationObserverURL = new MutationObserver(observerTitle_CB);
            MutationObserverURL.observe(document.body, MutationObserverConfig);
        }
        if ("observerURL" in siteData && isBoolean(siteData.observerURL) && siteData.observerURL === true) {
            const observerURL_CB = async (mutationList, observer) => {
                if (mutationList) {
                    const mutationList_removedNodes = [...mutationList].filter(item => item.type === "childList" && item?.removedNodes?.length > 0);
                    if (mutationList_removedNodes.length > 0) {
                        for (const mutation of mutationList_removedNodes) {
                            const removedNodes = mutation.removedNodes;
                            for (const node of removedNodes) {
                                if (node?.id == "FullPictureLoadOptionsShadowElement" || node?.id == "FullPictureLoadShadowGallery" || node?.id == "FullPictureLoadIframeGallery") {
                                    return;
                                }
                            }
                        }
                    }
                }
                if (observer) {
                    observer.disconnect();
                    setTimeout(async () => {
                        const body = await fn.waitEle("body");
                        observer.observe(body, MutationObserverConfig);
                        if (!isOpenGallery && siteUrl !== _unsafeWindow.document.URL) {
                            await toggleUI();
                        }
                        if ("customTitle" in siteData && !("capture" in siteData)) {
                            const newCustomTitle = await getTitle(siteData.customTitle);
                            if (customTitle !== newCustomTitle && newCustomTitle !== null && newCustomTitle !== undefined && newCustomTitle !== "") {
                                customTitle = newCustomTitle;
                                debug(`\n自定義標題:${newCustomTitle}`);
                            }
                        }
                    }, 200);
                }
                if (mutationList) {
                    try {
                        const mutationList_addedNodes = [...mutationList].filter(item => item.type === "childList" && item?.addedNodes?.length > 0);
                        if (mutationList_addedNodes.length === 0) {
                            return;
                        }
                        const strings = ["FullPictureLoad", "FullPictureLoadOptionsShadowElement", "FullPictureLoadShadowGallery", "FullPictureLoadIframeGallery", "pagetual", "comicRead", "Autopage", "pv-"];
                        for (const mutation of mutationList_addedNodes) {
                            const attributes = [mutation?.target?.id, mutation?.target?.className, mutation?.target?.name].filter(e => e);
                            const checkM = attributes.some(attr => strings.some(str => attr?.startsWith(str)));
                            if (checkM) {
                                return;
                            }
                            const addedNodes = mutation.addedNodes;
                            for (const node of addedNodes) {
                                const attributes = [node?.id, node?.className, node?.name].filter(e => e);
                                const checkN = attributes.some(attr => strings.some(str => attr?.startsWith(str)));
                                if (checkN) {
                                    return;
                                }
                            }
                        }
                        //console.log(mutationList_addedNodes);
                    } catch {}
                }
                if (isFetching || isDownloading) return;
                if (siteUrl !== _unsafeWindow.document.URL.replace(_unsafeWindow.location.hash, "")) {
                    siteUrl = _unsafeWindow.document.URL;
                    isGotAll = false;
                    await toggleUI();
                    const newCustomTitle = await getTitle(siteData.customTitle);
                    if ("capture" in siteData && !newCustomTitle) {
                        await captureSrcB(1);
                        const newCustomTitle = await getTitle(siteData.customTitle);
                        if (customTitle !== newCustomTitle && newCustomTitle !== null && newCustomTitle !== undefined && newCustomTitle !== "") {
                            customTitle = newCustomTitle;
                        }
                    }
                    if (customTitle !== newCustomTitle && newCustomTitle !== null && newCustomTitle !== undefined && newCustomTitle !== "") {
                        customTitle = newCustomTitle;
                        debug(`\n自定義標題:${newCustomTitle}`);
                        if ("capture" in siteData) {
                            captureSrcB();
                        }
                    }
                    if ("next" in siteData) {
                        await getNextLink(siteData.next, "\nURL變換 nextLink:");
                    }
                }
            };
            const MutationObserverURL = new MutationObserver(observerURL_CB);
            MutationObserverURL.observe(document.body, MutationObserverConfig);
        }
        if ("next" in siteData) {
            const next = siteData.next;
            const nextE = await getNextLink(next);
            const callback = (event) => {
                if (event.type === "dblclick") {
                    if (["is-next", "is-prev", "fancybox-button"].some(n => event?.target?.className?.includes(n))) return;
                }
                if (isFn(next)) {
                    fn.showMsg(displayLanguage.str_34, 0);
                    if (isString(nextE)) {
                        location.href = nextE;
                    } else if (isEle(nextE)) {
                        EClick(nextE);
                    } else {
                        fn.showMsg(displayLanguage.str_37);
                    }
                } else if (isString(next)) {
                    if (isEle(nextE)) {
                        EClick(nextE);
                        fn.showMsg(displayLanguage.str_35);
                    } else {
                        fn.showMsg(displayLanguage.str_37);
                    }
                }
            };
            if (hasTouchEvent && !!siteData.next && options.doubleTouchNext == 1) {
                document.addEventListener("dblclick", (event) => callback(event));
            }
            document.addEventListener("keydown", event => {
                if (isOpenOptionsUI || isOpenGallery || ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
                if (event.code === "ArrowRight" || event.key === "ArrowRight") callback(event);
            });
        }
        if ("prev" in siteData) {
            const prev = siteData.prev;
            document.addEventListener("keydown", event => {
                if (isOpenOptionsUI || isOpenGallery || ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
                if (event.code === "ArrowLeft" || event.key === "ArrowLeft") {
                    event.preventDefault();
                    if (prev === 1) {
                        fn.showMsg(displayLanguage.str_38);
                        history.back();
                        return;
                    }
                    let ele = fn.ge(prev);
                    if (ele) {
                        EClick(ele);
                        fn.showMsg(displayLanguage.str_39);
                    } else {
                        fn.showMsg(displayLanguage.str_40);
                    }
                }
            });
        }
        if ("autoClick" in siteData) {
            const autoClick = siteData.autoClick;
            if (isArray(autoClick)) {
                let [selector, delay] = autoClick;
                setTimeout(() => {
                    let ele = fn.ge(selector);
                    if (ele) {
                        EClick(ele);
                        debug(`\n圖片全載autoClick("${selector}")`, ele);
                    }
                }, delay ?? 1000);
            } else if (isString(autoClick)) {
                let ele = fn.ge(autoClick);
                if (!!ele) {
                    EClick(ele);
                    debug(`\n圖片全載autoClick("${autoClick}")`, ele);
                }
            }
        }
        if ("observerClick" in siteData) {
            const observerClick = siteData.observerClick;
            let selectors;
            if (isString(observerClick)) {
                selectors = [observerClick];
            } else {
                selectors = observerClick;
            }
            fn.wait(() => selectors.some(selector => !!fn.ge(selector)), 30).then(() => {
                selectors.forEach((selector, i) => {
                    setTimeout(() => {
                        let ele = fn.ge(selector);
                        if (ele) {
                            const observer = new IntersectionObserver((entries, observer) => {
                                entries.forEach(entry => {
                                    if (entry.isIntersecting) {
                                        observer.unobserve(entry.target);
                                        EClick(entry.target);
                                        debug(`\n圖片全載observerClick("${selector}")\n`, entry.target);
                                        setTimeout(async () => {
                                            if (await fn.waitEle(selector, 30)) {
                                                observer.observe(fn.ge(selector));
                                            }
                                        }, 1000);
                                    }
                                });
                            });
                            observer.observe(ele);
                        }
                    }, (i + 1) * 200);
                });
            });
        }
        if ("loadMore" in siteData && isString(siteData.loadMore)) {
            const selector = siteData.loadMore;
            const callback = () => {
                if (_unsafeWindow.innerHeight + _unsafeWindow.pageYOffset >= document.body.offsetHeight - 200) {
                    document.removeEventListener("scroll", callback);
                    const ele = fn.ge(selector);
                    if (!!ele) {
                        EClick(ele);
                        debug(`圖片全載loadMore("${selector}")`);
                    }
                    setTimeout(async () => {
                        if (await fn.waitEle(selector, 30)) {
                            document.addEventListener("scroll", callback);
                        }
                    }, 1000);
                }
            };
            document.addEventListener("scroll", callback);
        }
        if ("autoPager" in siteData && isObject(siteData.autoPager)) {
            const observer = siteData.autoPager?.observer;
            if (isString(observer)) {
                let ele = fn.gae(observer).at(-1);
                if (ele) fn.nextObserver.observe(ele);
            } else {
                const callback = async () => {
                    if (_unsafeWindow.innerHeight + _unsafeWindow.pageYOffset >= document.body.offsetHeight - (siteData.autoPager?.bottom ?? screen.height)) {
                        if (!autoPagerSwitch) return;
                        document.removeEventListener("scroll", callback);
                        await fn.infiniteScroll();
                        await delay(siteData.autoPager?.sleep || 1000);
                        document.addEventListener("scroll", callback);
                    }
                };
                document.addEventListener("scroll", callback);
            }
            document.addEventListener("dblclick", () => fn.toggleAutoPager());
            let hide = siteData.autoPager?.hide;
            if (isString(hide)) {
                let eles = fn.gae(hide);
                eles.forEach(e => (e.style.display = "none"));
            }
            let preloadNextPage = siteData.autoPager?.preloadNextPage;
            if (!!preloadNextPage) {
                fn.preloadNextPage();
            }
        }
        if ("insertImg" in siteData) {
            const insertImg = siteData.insertImg;
            const autoDownload = siteData.autoDownload;
            if (isArray(insertImg)) {
                let autoStart;
                if (isArray(autoDownload)) {
                    [autoStart] = autoDownload;
                    autoStart = (autoStart == 1 || options.autoDownload == 1);
                }
                const [, insertMode] = insertImg;
                if (insertMode == 1 && !autoStart || insertMode == 2 && !autoStart) {
                    if (options.autoInsert == 1) {
                        if (options.shadowGallery == 1 && siteData.aeg != 0) {
                            await fn.immediateInsertImg();
                        } else {
                            fn.immediateInsertImg();
                        }
                    }
                }
            }
        }
        if ("autoDownload" in siteData) {
            const autoDownload = siteData.autoDownload;
            if (isArray(autoDownload)) {
                const [autoStart] = autoDownload;
                if (autoStart == 1 || options.autoDownload == 1) {
                    DownloadFn();
                }
            }
        }
        if (options.shadowGallery == 1 && siteData.aeg != 0 && options.autoDownload != 1 && ("imgs" in siteData) && !siteData.category.includes("autoPager") && !["lazyLoad", "none", "ad"].some(c => c === siteData.category) && !(("capture" in siteData) && ("SPA" in siteData))) {
            if ("SPA" in siteData && isFn(siteData.SPA)) {
                if (await siteData.SPA()) {
                    setTimeout(() => createShadowGallery(), 200);
                }
            } else {
                setTimeout(() => createShadowGallery(), 200);
            }
        }
        if (options.autoExport == 1 && options.autoDownload != 1) {
            exportImgSrcText();
        }
        if ("openInNewTab" in siteData && isString(siteData.openInNewTab)) {
            const openInNewTab = siteData.openInNewTab;
            fn.openInNewTab(openInNewTab);
            fn.addMutationObserver(() => fn.openInNewTab(openInNewTab));
        }
        if ("topButton" in siteData && isBoolean(siteData.topButton) && siteData.topButton === true) {
            addReturnTopButton();
        }
        if ("setFancybox" in siteData) {
            const setFancybox = siteData.setFancybox;
            if (isBoolean(setFancybox) && options.fancybox == 1 && isString(siteData.imgs)) {
                fn.setFancybox(siteData.imgs);
            } else if (isString(setFancybox) && options.fancybox == 1) {
                fn.setFancybox(setFancybox);
            }
        }
    } catch (error) {
        console.error("圖片全載規則出錯", error);
        debug("圖片全載規則出錯", siteData);
        return;
    }

    if (("reg" in siteData) || ("url" in siteData)) {
        debug("\n列出此站資料", siteData);
        debug(`\n列出規則總數(${customData.length})`);
        debug("\n列出PHOTO規則", photoData);
        debug("\n列出NSFW規則", nsfw1Data);
        debug("\n列出NSFW+規則", nsfw2Data);
        debug("\n列出COMIC規則", comicData);
        debug("\n列出HCOMIC規則", hcomicData);
        debug("\n列出LazyLoad模式規則", lazyLoadData);
        debug("\n列出自動翻頁規則", autoPagerData);
        debug("\n列出去廣告規則", AD_Data);
        debug("\n列出未分類規則", noneData);
    }

    if (!hasTouchEvent && showOptions && isArray(siteData.insertImg)) {
        _GM_registerMenuCommand(TurnOffImageNavigationShortcutKeys == 0 ? "❌ " + displayLanguage.str_121 : "✔️ " + displayLanguage.str_121, () => {
            TurnOffImageNavigationShortcutKeys == 0 ? _GM_setValue("TurnOffImageNavigationShortcutKeys", 1) : _GM_setValue("TurnOffImageNavigationShortcutKeys", 0);
            location.reload();
        });
    }

    if (showOptions && isNumber(siteData.go)) {
        _GM_registerMenuCommand(noGoToFirstImage == 0 ? "❌ " + displayLanguage.str_115 : "✔️ " + displayLanguage.str_115, () => {
            noGoToFirstImage == 0 ? _GM_setValue("noGoToFirstImage", 1) : _GM_setValue("noGoToFirstImage", 0);
            location.reload();
        });
    }

    if (isArray(siteData.scrollEle) || isFn(siteData.scrollEle)) {
        _GM_registerMenuCommand(autoScrollAllElement == 0 ? "❌ " + displayLanguage.str_116 : "✔️ " + displayLanguage.str_116, () => {
            autoScrollAllElement == 0 ? _GM_setValue("autoScrollAllElement", 1) : _GM_setValue("autoScrollAllElement", 0);
            location.reload();
        });
    }

    if (siteData.category && ["nsfw1", "nsfw2", "hcomic", "comic", "lazyLoad"].some(c => c === siteData.category)) {
        _GM_registerMenuCommand(newTabViewLightGallery == 0 ? "❌ " + displayLanguage.str_120 : "✔️ " + displayLanguage.str_120, () => {
            newTabViewLightGallery == 0 ? localStorage.setItem("newTabViewLightGallery", 1) : localStorage.setItem("newTabViewLightGallery", 0);
            location.reload();
        });
    }

    if (siteData.category === "comic" && siteData.infiniteScroll || siteData.category === "comic autoPager") {
        _GM_registerMenuCommand(comicInfiniteScrollMode == 0 ? "❌ " + displayLanguage.str_122 : "✔️  " + displayLanguage.str_122, () => {
            comicInfiniteScrollMode == 0 ? localStorage.setItem("FullPictureLoadComicInfiniteScrollMode", 1) : localStorage.setItem("FullPictureLoadComicInfiniteScrollMode", 0);
            location.reload();
        });
    }

    let autoDownload = siteData.autoDownload;

    if (!!autoDownload) {
        //自動下載快捷鍵
        document.addEventListener("keydown", event => {
            if (captureExclude() || ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
            if (event.ctrlKey && (event.code === "NumpadDecimal" || event.code === "Period" || event.key === ".")) {
                if (options.autoDownload == 0) {
                    fn.showMsg(displayLanguage.str_64, 0);
                    options.autoDownload = 1;
                    let jsonStr = JSON.stringify(options);
                    localStorage.setItem("FullPictureLoadOptions", jsonStr);
                    setTimeout(() => location.reload(), 2000);
                } else {
                    isStopDownload = true;
                    fn.clearAllTimer(2);
                    options.autoDownload = 0;
                    let jsonStr = JSON.stringify(options);
                    localStorage.setItem("FullPictureLoadOptions", jsonStr);
                    fn.clearSetTimeout();
                    fn.showMsg(displayLanguage.str_65, 0);
                    location.reload();
                }
            }
        });
    }

    //移動端手動模式頁面聚圖
    if (hasTouchEvent && "insertImg" in siteData) {
        let timeId;
        const touchstartCB = event => {
            //console.log(event);
            if (isFetching || isDownloading || isOpenFilter || isOpenFancybox || isOpenGallery || ge(".fancybox-container,#FullPictureLoadFavorSites")) return;
            const check = (e) => {
                if (["DIV", "A"].some(t => t === e.target.tagName) && getComputedStyle(e.target).getPropertyValue("background-image") != "none") {
                    return true;
                }
                if (["A", "FIGURE", "SPAN"].some(t => t === e.target.tagName)) {
                    return !!e.target.querySelector("img,canvas");
                }
                if (e.target.tagName === "A" && e.target?.previousElementSibling?.nodeName === "IMG") {
                    return true;
                }
                if (["IMG", "CANVAS"].some(t => t === e.target.tagName) && !["Full"].some(id => e.target?.id?.startsWith(id)) && !["fancybox", "viewer-move"].some(className => e.target?.className?.startsWith(className))) {
                    return true;
                }
                return false;
            };
            if (check(event)) {
                timeId = setTimeout(() => {
                    copyImgSrcText();
                }, 500);
            }
        };
        const clearCB = () => {
            if (isFetching || isDownloading) return;
            clearTimeout(timeId);
        };
        document.addEventListener("touchstart", touchstartCB);
        document.addEventListener("touchmove", clearCB);
        document.addEventListener("touchend", clearCB);
    }

    //debug("\n最終options物件\n", options);

    if (siteData.category == "lazyLoad") {
        addLazyLoadFullResolutionMenu();
    }

    //漫畫類預讀下一話圖片
    setTimeout(() => {
        let preloadNext = siteData.preloadNext;
        try {
            if (!!nextLink && !!preloadNext && !isDownloading) {
                fn.xhrDoc(nextLink).then(async nextDoc => {
                    //debug("\nnextDoc", nextDoc);
                    if (isBoolean(preloadNext) && preloadNext === true && isFn(siteData.imgs) && isFn(siteData.customTitle)) {
                        fn.picPreload(await siteData.imgs(nextDoc), await siteData.customTitle(nextDoc), "next");
                    } else if (isBoolean(preloadNext) && preloadNext === true && isString(siteData.imgs) && isFn(siteData.customTitle)) {
                        let arr = fn.getImgSrcArr(siteData.imgs, nextDoc);
                        fn.picPreload(arr, await siteData.customTitle(nextDoc), "next");
                    } else if (isFn(preloadNext)) {
                        preloadNext(nextDoc, siteData);
                    }
                });
            }
        } catch (error) {
            console.error("圖片全載preloadNext()出錯", error);
        }
    }, 1000);

    //捕獲圖片網址
    async function captureSrc(mutationList) {
        if (isChangeNum || isOpenOptionsUI || isOpenGallery || isOpenFancybox || isOpenFilter || isDownloading || isFetching || FullPictureLoadShowEye == 0) return;
        if (mutationList) {
            for (const mutation of mutationList) {
                if (mutation.type === "childList" && mutation?.target?.id === "FullPictureLoadCaptureNum") {
                    return;
                }
            }
            //console.log(mutationList);
        }
        let imgSrcs = await getImgs(siteData.capture ?? siteData.imgs);
        let imagePreloadArray = [];
        imgSrcs.forEach(src => {
            if (!captureSrcArray.includes(src)) {
                captureSrcArray.push(src);
                imagePreloadArray.push(src);
            }
        });
        if (ge("#FullPictureLoadCaptureNum") && captureTotal != captureSrcArray.length) {
            isChangeNum = true;
            captureTotal = captureSrcArray.length;
            ge("#FullPictureLoadCaptureNum").innerText = captureSrcArray.length;
            await delay(100);
            isChangeNum = false;
            if (options.shadowGallery == 1 && siteData.aeg != 0) {
                setTimeout(() => createShadowGallery(), 200);
            }
        }
        if (lazyLoadPreloadImages == 1) {
            fn.picPreload(imagePreloadArray, "Lazy Load Mode");
        }
    }

    async function captureSrcB(invalidPage = 0) {
        if (isChangeNum || isOpenOptionsUI || isOpenGallery || isOpenFancybox || isOpenFilter || isDownloading || isFetching || FullPictureLoadShowEye == 0) return;
        if (invalidPage === 1 && !!ge("#FullPictureLoadCaptureNum") && ge("#FullPictureLoadCaptureNum")?.innerText != 0) {
            isChangeNum = true;
            ge("#FullPictureLoadCaptureNum").innerText = 0;
            await delay(100);
            isChangeNum = false;
            return;
        }
        if (!["m2ph.xyz", "bdsmlr.com"].some(h => fn.lh.includes(h))) {
            await delay(900);
        }
        let captureSrcArray = await getImgs(siteData.capture ?? siteData.imgs);
        let num = captureSrcArray.length;
        if (ge("#FullPictureLoadCaptureNum")) {
            isChangeNum = true;
            ge("#FullPictureLoadCaptureNum").innerText = num;
            await delay(100);
            isChangeNum = false;
            if (options.shadowGallery == 1 && siteData.aeg != 0) {
                setTimeout(() => createShadowGallery(), 200);
            }
        }
    }

    //動態捕獲圖片網址
    if (siteData.category?.includes("lazyLoad") && lazyLoadFullResolution == 1 && !!siteData.capture || isString(siteData.imgs) && !isArray(siteData.insertImg) || isFn(siteData.capture) && siteData.category != "lazyLoad") {
        if (isFn(siteData.capture) && siteData.category != "lazyLoad" || isString(siteData.capture) && siteData.category != "lazyLoad" || isString(siteData.imgs) && siteData.category != "lazyLoad") {
            if (FullPictureLoadShowEye == 1 && siteData.eye != 0) {
                await delay(1000);
                isCaptureMode = true;
                addNewTabViewButton();
                captureSrc();
            }
        }
        if (siteData.category === "lazyLoad" && siteData.eye != 0) {
            isCaptureMode = true;
            addNewTabViewButton();
            fn.addMutationObserver(captureSrc, document.body, {
                childList: true,
                subtree: true,
                attributes: true
            });
        }
    }

    const defaultFavor = "main-background-color,#fafafa\ntext-color,#000\nbackground-color,#aceebb\n4KHD,https://www.4khd.com/\nSpace Miss,https://spacemiss.com/\n小黃書,https://xchina.biz/\n紳士会所,https://www.hentaiclub.net/\n图宅网,https://www.tuzac.com/\n丝袜客,https://siwake.cc/\n萌图社,http://www.446m.com/\n美女图册,https://www.mntuce.com/\n六色美图,https://www.06se.com/\nEVERIA.CLUB,https://everia.club/\nAVJB,https://avjb.com/albums/\nエロ画像まとめ,https://geinou-nude.com/\nXasiat,https://www.xasiat.com/albums/\nXO福利圖,https://kb1.a7xofulitu.com/儿歌三百首/\n色图,https://setu.lol/\n紳士漫畫,https://www.wnacg.com/albums-index-cate-3.html";

    let FavorOpenInNewTab = _GM_getValue("FavorOpenInNewTab", 0);

    const createFavorShadowElement = () => {

        const mainHtml = '<div id="FullPictureLoadFavorSites" style="overflow: clip !important;display: initial !important;position: fixed !important;z-index: 2147483647 !important;"></div>';
        document.body.insertAdjacentHTML("beforeend", mainHtml);

        const FavorSitesShadowElement = ge("#FullPictureLoadFavorSites");
        const shadow = FavorSitesShadowElement.attachShadow({
            mode: "closed"
        });
        fn.css(`
html,body {
    overflow: hidden !important;
}
        `, "overflowYHidden");

        const style = createStyle(`
#FavorUl {
    width: 100%;
    background-color: transparent;
    list-style-type: none;
    display: grid;
    list-style: none;
    margin: 10px 0px 0px 0px;
    padding: 0px;
    border: 0;
    font: inherit;
    vertical-align: baseline;
}

.favor-item {
    float: left;
    width: unset;
    height: unset;
    min-height: unset;
    max-height: 44px;
    margin: 0px 10px 10px 0px;
    position: unset;
    line-height: 26px;
    padding: 3px;
    font: unset;
    font-family: Arial, sans-serif;
    font-size: 16px;
    text-align: center;
    border-radius: 8px;
    white-space: nowrap;
    list-style: none;
}

.favor-item a {
    display: block;
    text-align: center;
    text-decoration: unset;
    font: unset;
    font-family: Arial, sans-serif;
    font-size: 16px;
    background-color: unset;
    border-color: unset;
    margin: 0;
}

#editFavorTextarea {
    display: block;
    height: 30em;
    resize: both;
    overflow: auto;
    background-color: unset;
    color: #000000;
    border-color: #000000;
    margin: 0px auto;
    padding: 5px;
    max-width: unset;
    max-height: unset;
}

#editFavorDiv {
    text-align: center;
    background-color: #fafafa;
    margin: 0;
    padding-top: 6px;
}

.editFavorButton {
    min-width: 70px;
    line-height: 25px;
    margin: 5px;
    float: none;
    padding: 0;
    color: #000000;
    border: 1px solid #a0a0a0;
    background-color: transparent;
}
        `);
        shadow.append(style);

        const FavorSitesElement = document.createElement("div");

        Object.assign(FavorSitesElement.style, {
            left: "0",
            right: "0",
            top: "0",
            bottom: "0",
            width: "99%",
            height: "98%",
            margin: "auto",
            padding: "10px",
            position: "fixed",
            opacity: "1",
            zIndex: "2147483647",
            backgroundColor: "#fafafa",
            fontSize: "14px",
            overflowY: "auto",
            overflowX: "hidden"
        });
        shadow.append(FavorSitesElement);

        const reSize_cb = () => {
            const verticalScreen = _unsafeWindow.innerHeight / _unsafeWindow.innerWidth > 1;
            let ul = ge("#FavorUl", shadow);
            if (ul) {
                ul.style.gridTemplateColumns = `${fn.arr(Math.floor(_unsafeWindow.innerWidth / 180), () => "1fr").join(" ")}`;
                if (hasTouchEvent) {
                    if (verticalScreen) {
                        ul.style.width = "calc(100% - 5px)";
                    } else {
                        ul.style.width = "calc(100% - 2px)";
                    }
                }
            }
            let edit = ge("#editFavorDiv", shadow);
            if (edit && hasTouchEvent) {
                if (verticalScreen) {
                    edit.style.width = "calc(100% - 18px)";
                } else {
                    edit.style.width = "calc(100% - 14px)";
                }
            } else if (edit) {
                if (verticalScreen) {
                    edit.style.width = "calc(100% - 2px)";
                } else {
                    edit.style.width = "calc(100% - 6px)";
                }
            }
        };

        const createFavorTextarea = () => {
            FavorSitesElement.style.backgroundColor = "#fafafa";
            let favorData = _GM_getValue("favorData", defaultFavor);
            let editFavorDiv = document.createElement("div");
            editFavorDiv.id = "editFavorDiv";
            if (hasTouchEvent) {
                const verticalScreen = _unsafeWindow.innerHeight / _unsafeWindow.innerWidth > 1;
                if (verticalScreen) {
                    editFavorDiv.style.width = "calc(100% - 18px)";
                } else {
                    editFavorDiv.style.width = "calc(100% - 14px)";
                }
            } else {
                editFavorDiv.style.width = "calc(100% - 6px)";
            }
            editFavorDiv.style.height = "calc(100% - 20px)";
            let textarea = document.createElement("textarea");
            textarea.id = "editFavorTextarea";
            textarea.style.width = "calc(100% - 10px)";
            textarea.style.height = "calc(100% - 30px)";
            editFavorDiv.append(textarea);
            FavorSitesElement.appendChild(editFavorDiv);
            [{
                text: displayLanguage.str_132,
                id: "editFavorCloseBtn",
                cfn: event => {
                    event.preventDefault();
                    editFavorDiv.remove();
                    createFavor();
                }
            }, {
                text: displayLanguage.str_131,
                id: "editFavorSaveBtn",
                cfn: event => {
                    event.preventDefault();
                    _GM_setValue("favorData", textarea.value);
                    editFavorDiv.remove();
                    createFavor();
                }
            }].forEach(obj => {
                let button = document.createElement("button");
                button.id = obj.id;
                button.className = "editFavorButton";
                button.innerText = obj.text;
                button.addEventListener("click", obj.cfn);
                editFavorDiv.append(button);
            });
            textarea.value = favorData;
        };

        const createFavor = () => {
            let favorData = _GM_getValue("favorData", defaultFavor);
            FavorSitesElement.style.backgroundColor = "#fafafa";
            let FavorUl = document.createElement("ul");
            FavorUl.id = "FavorUl";
            FavorUl.style.gridTemplateColumns = `${fn.arr(Math.floor(_unsafeWindow.innerWidth / 180), () => "1fr").join(" ")}`;
            if (hasTouchEvent) {
                const verticalScreen = _unsafeWindow.innerHeight / _unsafeWindow.innerWidth > 1;
                if (verticalScreen) {
                    FavorUl.style.width = "calc(100% - 5px)";
                } else {
                    FavorUl.style.width = "calc(100% - 2px)";
                }
            }
            FavorSitesElement.appendChild(FavorUl);
            let favorDataArray = favorData.split("\n").filter(item => item);
            let textColor = "#000";
            let backgroundColor = "#aceebb";
            for (let favor of favorDataArray) {
                try {
                    let [name, value] = favor.split(",");
                    if (name === "main-background-color") {
                        FavorSitesElement.style.backgroundColor = value;
                    } else if (name === "text-color") {
                        textColor = value;
                    } else if (name === "background-color") {
                        backgroundColor = value;
                    } else {
                        let li = document.createElement("li");
                        li.className = "favor-item";
                        li.style.backgroundColor = backgroundColor;
                        li.style.color = textColor;
                        let a = document.createElement("a");
                        a.innerText = name;
                        a.href = value;
                        if (FavorOpenInNewTab == 1) {
                            a.setAttribute("target", "_blank");
                        }
                        a.style.color = textColor;
                        li.append(a);
                        fragment.append(li);
                    }
                } catch (error) {
                    console.error(error);
                }
            }
            [{
                text: displayLanguage.str_130,
                cfn: () => {
                    createFavorTextarea();
                    FavorUl.remove();
                }
            }, {
                text: displayLanguage.str_129,
                cfn: () => {
                    if (!isOpenFilter) {
                        fn.remove("#overflowYHidden");
                    }
                    FavorSitesShadowElement.remove();
                    _unsafeWindow.removeEventListener("resize", reSize_cb);
                }
            }].forEach(obj => {
                let li = document.createElement("li");
                li.className = "favor-item";
                li.style.backgroundColor = backgroundColor;
                li.style.color = textColor;
                li.innerText = obj.text;
                li.addEventListener("click", obj.cfn);
                fragment.append(li);
            });
            FavorUl.append(fragment);
        };
        createFavor();

        _unsafeWindow.addEventListener("resize", reSize_cb);

    };

    _GM_registerMenuCommand(displayLanguage.str_125, () => {
        const keys = [
            "newTabViewLightGallery",
            "newWindowData",
            "FullPictureLoadComicInfiniteScrollMode",
            "FullPictureLoadOptions",
            "FullPictureLoadCustomDownloadVideo",
            "FullPictureLoadShowEye",
            "FullPictureLoadBlacklist"
        ];
        for (const key of keys) {
            if (key in localStorage) {
                localStorage.removeItem(key);
            }
        }
        location.reload();
    });
    _GM_registerMenuCommand(displayLanguage.str_126, () => {
        const GM_keys = _GM_listValues();
        if (GM_keys.length > 0) {
            GM_keys.forEach(key => _GM_deleteValue(key));
        }
        location.reload();
    });

    //簡易模式規則
    if (!("category" in siteData)) {
        isSimpleMode = true;
        let menu_command_id_1;
        let menu_command_id_2;
        let menu_command_id_3;
        const registerA = () => {
            menu_command_id_2 = _GM_registerMenuCommand(displayLanguage.str_163, () => {
                menu_command_id_1 = _GM_registerMenuCommand(displayLanguage.str_67, () => createPictureLoadOptionsShadowElement());
                checkOptionsData();
                siteData = {
                    imgs: () => fn.getImgSrcset("a,p,div,span,li,figure,article,img:not(.FullPictureLoadFixedBtn)"),
                    repeat: 1,
                    SPA: true,
                    category: "photo"
                };
                addFullPictureLoadButton();
                if (!hasTouchEvent) {
                    addFullPictureLoadFixedMenu();
                    document.addEventListener("keydown", addKeyEvent);
                }
                if (!ge("#FullPictureLoadMainStyle")) {
                    fn.css(FullPictureLoadStyle, "FullPictureLoadMainStyle");
                }
                if (!("Fancybox" in _unsafeWindow)) {
                    addLibrarysV5();
                    Fancyboxl10nV5();
                    fn.css(FancyboxV5Css, "FancyboxV5Css");
                }
                _GM_unregisterMenuCommand(menu_command_id_2);
                registerB();
            });
        };
        const registerB = () => {
            menu_command_id_3 = _GM_registerMenuCommand(displayLanguage.str_164, () => {
                _GM_unregisterMenuCommand(menu_command_id_1);
                siteData = {};
                fn.remove(".FullPictureLoadFixedBtn,#FullPictureLoadFixedMenu");
                if (!hasTouchEvent) {
                    document.removeEventListener("keydown", addKeyEvent);
                }
                _GM_unregisterMenuCommand(menu_command_id_3);
                registerA();
            });
        };
        registerA();
    }

    if (!isSimpleMode && !siteData.category?.includes("autoPager") && !["lazyLoad", "none", "ad"].some(c => c === siteData.category)) {
        if (siteData.key != 0) {
            if (!hasTouchEvent) {
                if (ShowFullPictureLoadFixedMenu === 1) addFullPictureLoadFixedMenu();
            }
            if (!isAddKeyEvent) {
                document.addEventListener("keydown", addKeyEvent);
                isAddKeyEvent = true;
            }
        }

        if (siteData.icon == 0) {
            //return;
        } else if (options.icon == 1 || siteData.icon == 1) {
            addFullPictureLoadButton();
        }
        setTimeout(() => toggleUI(), 500);
    }

    if (fn.lh.includes(".v2ph.")) {
        _GM_registerMenuCommand("🍪 Set V2PH Cookie", () => {
            v2ph_cookie = prompt("Set Cookie", v2ph_cookie || "");
            if (!!v2ph_cookie) {
                _GM_setValue("v2ph_cookie", v2ph_cookie);
            }
        });
    }

})(JSZip);