Ajax Load ImageHost·Demo

通过 ajax 的方式,自动加载图床超链接的图片,本脚推荐使用【Tampermonkey】运行,其它脚本扩展可能引发的未知问题,请反馈时说明。\n首次访问图床,需要允许脚本访问域名,否则降本将无法正常工作。

// ==UserScript==
// @name         Ajax Load ImageHost·Demo
// @namespace      https://greasyfork.org/zh-CN/users/122964
// @version       2.6.8
// @description    通过 ajax 的方式,自动加载图床超链接的图片,本脚推荐使用【Tampermonkey】运行,其它脚本扩展可能引发的未知问题,请反馈时说明。\n首次访问图床,需要允许脚本访问域名,否则降本将无法正常工作。
// @author        ThisAV
// @require      https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js
//
// @include      https://sukebei.*
// @include      https://*.nyaa.*/view/*
// @include      https://jojodl.com/*/*
// @include      https://jojodl.pw/*/*
// @include      https://fapforfun.net/archives/*
// @include      http://www.alabout.com/view.php?*
// @include      http://roriland.info/*/*/*
// @include      /https://[^.]+.blogspot.com/\d{4}/\d{2}/[^.]+.html/
// @include      https://github.com/Owyn/HandyImage/issues/*
// @exclude      */list.php*

//
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addStyle
// @grant       GM_openInTab
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @grant       GM_notification
// @grant			GM_registerMenuCommand
// @icon         https://www.google.com/s2/favicons?domain=https://blogspot.com/favicon.ico
// @license      MIT
// ==/UserScript==

/* *
 * 更新日志
 * 2.6.8
 1、支持 Base64 编码加载图片(应用于受CSP限制的网站)
 2、PostPIC → pics4upload.com
 3、SoDaBug → imgyng.buzz、imglqw.buzz、imgmeno.buzz、kejinomama.icu、imgveni.xyz、imgkuiw.xyz、imglina.xyz、imgalor.xyz、imgirx.xyz、imgwewo.xyz、imgbird.xyz、imgkr.xyz、imglin.xyz
 4、#screenshot-image → skr.sh、skrinshoter.ru
 5、MetaInIMG → postimgs.org、ibb.co、imgbb.com、servimg.com、imgstar.eu、rintor.space、
 6、chevereto.com → empornium.sx、empornium.ph
 7、ImgHost → vfl.ru
 8、Redirect → imgtorrnt.in
 9、noLink → imgjazz.xyz
 10、.centred → xxxwebdlxxx.org、olarixas.xyz、imgdawgknuttz.com
 11、noSupport → tezzpic.com、picrok.com



 * 2.5.8
 1、soDabug 图床获取逻辑规则更新
 2、PostPIC → imgsen.com

 * 2.5.7.4
 1、soDaBug 模板更新,支持 imgwang.buzz
 2、metaInSmallToBig 模板更新,支持 imgwallet.com、imgdrive.net
 3、直链 images2.imgbox.com

 * 2.5.7.3
 1、soDaBug 模板更新,支持 imgkaka.xyz
 2、PostPIC 支持 imgstar.eu

 * 2.5.7.1
 1、破解 imagexport.com、imagetwist.com 防盗链
 2、soDaBug 模板网站更新
 3、将 uvonahaze.xyz 转为通用模板 #imgContinue
 4、#imgContinue 支持 pornhd720p.com

 * 2.4.7
 1、支持 kvador.com、x8img.com
 2、处理链接中的不规范字符([/?img])

 * 2.4.6
 1、3xplanet.net
 2、silverpic.com

 * 2.4.5
 1、匹配 sukebei 类网站
 2、通用规则与域名规则分离
 3、修复通用规则兼容性BUG

 * 2.3.4
 1、[#ID>IMG>src]规则,eroticmovies.xyz
 2、修复 picbaron 等基于 PostPic 规则的网站
 3、PostPic 规则,pics4you.net


*/

(function() {
    'use strict';

    let blockList=/bbyxv.xyz|baixn.xyz|8a88b.com/i; //如果文件清单中有这些域名,则黑掉下载按钮,拒绝辣鸡网站

    class setting{
        constructor (small, text2link){
            {
                this.small = small;
                this.text2link = text2link;
            }
        }
    }

    let log_control=true,
        Config,
        hosts=location.hostname.toLowerCase(),
        hostRoot=document.domain.toLowerCase().replace(/.+\.([^.]+\.(com|cn|net|org|pw|ru|com.cn|jp))/i,'$1'),
        domain=location.hostname.replace(/^www\./i,'').toLowerCase(),
        webTitle=document.title;
    let ImgRules={
        meta : 'meta[property="og:image"], meta[name="og:image"]',
        script : function(str){
            return "script:contains("+str+")"
        },
        NotLink : ''
    },
        ShareHost={
            'direct' : {'direct':true}, //直接加载,不需要ajax,域名表需要完整的域名
            'direct403' : {
                blobImg : true
            }, //403拒绝连接,需要使用GM_xml获取
            'notSupport' : {notSupport: true}, //不支持的网站
            'noLink' : {noLink: true}, //已失效网站
            'soDaBug':{
                reHost: 'imgpekele.buzz', //映射 Host 规则,最终目标网址被替换为这个
                //rule : ".main-content-box>"+ImgRules.script('soDaBug'),
                rule : ".main-content-box script:contains(wuLu)",
                text : true, //数据在文本中
                src : function(str){
                    if(!str) return; //图片不存在时
                    let src=str.match(/.src\s*=\s*["'](http[^"']+?)["']/i)[1],
                        host=src.match(/:\/\/([^/]+)/i)[1];
                    console.log(src, host)
                    //if(HostToList[host]) src=src.replace(host,'www.pixsera.net');
                    return src;
                },
                errorTips: '.tackle_flex'
            },
            'metaInIMG' : {//直接提取meta中的图片地址
                rule : ImgRules.meta,
                attr : 'content',
                blobImg : true
            },
            'metaInIMG&Direct':{
                rule : ImgRules.meta,
                attr : 'content',
                blobImg : true,
                isIMG: (a)=>{
                    console.log(123, a);
                    if(/\.(?:jpg|png|gif|webp)/i.test(a.href)) {
                        $(a).append('<br>',$('<img>').attr({'class':'ImageHostAjax', 'src': a.href, 'alt': "图片占位", 'data-AjaxSrc': a.href}));
                        return false;
                    } else {
                        return true;
                    }
                }
            },
            'metaInSmallToBig':{
                rule : ImgRules.meta,
                attr : 'content',
                thumb : '', //缩略图信息,用于移除默认缩略图的
                big : true, //小图转大图
                blobImg : true
            },
            '.centred': {attr : 'src', rule : '.centred', method : 'post', formdata: {"imgContinue":"Continue to image ... "}, path : /\/img-\w+/i, blobImg: true},
            '#imgContinue':{attr : 'src', rule :'.centred_resized', method : 'post', formdata: {"imgContinue":"Continue to image ... "}}, //一次性 Post 方法
            '#image-viewer-container':{attr : 'src', rule : '#image-viewer-container>img', path : /\/image\/\w+/i, blobImg: true},
            'PostPic':{//需要 Cookies,Post 表单,所以需要二次 ajax
                rule : '.pic',
                attr : 'src',
                form : { // 需要进行二次提交表单动作来获取数据,Form Data 由 ImageHostAjaxCore 函数采集
                    method : 'post',
                    cookie : {
                        'file_code' : 'input[name="id"]',
                        'fcode' : 'input[name="id"]',
                        'fadedin' : 'yes', //2020.11.23
                    }, //cookie获取开关,后续将自行获取cookie
                    success : function(){

                    }
                }
            },
            'MyFileShare':{attr : 'src', rule : '.uk-margin-large-top>img', path : /\/v\/\w+/i, blobImg : true},
            '#screenshot-image': {attr:'src', rule:'#screenshot-image', path:/\/s\/\d+\/\w+\//},
            '#photo': {attr:'src', rule:'#photo', path:/\/view.php/i},
            '#imgpreview': {attr:'src', rule:'#imgpreview', path:/\/\w+\/\w+/i},
            '.main-image': {attr:'src', rule:'.main-image', path:/\/image\/\w+/i},
            'chevereto.com': {},
            'center>a>img': {attr:'src', rule: 'center>a>img'}
        },
        ImgHost={
            'i.postimg.cc': {attr : 'content', rule : ImgRules.meta, reHost: 'pixxxels.cc', NoFileName: true, blobImg : true},
            'm.imgur.com': {attr : 'content', rule : ImgRules.meta, reHost : 'imgur.com',},
            'i.imgur.com': {attr : 'content', rule : ImgRules.meta, },
            'imagetwist.com': {attr : 'src', rule : '.pic', blobImg : true}, //blob 协议加载
            'imagexport.com':{attr:'src', rule:'.pic', reHost: 'imagetwist.com', blobImg:true},
            'imgbabes.com':{ //需要 cookies,Post 表单,所以需要二次 ajax,recaptcha 验证
                rule : '#source', attr : 'src', form : {method : 'post',reCaptcha: true, headers : {'Content-Type': 'application/x-www-form-urlencoded'}},
            },
            'imgtorrnt.in':{attr:'src', path:/view.php/i, redirect: (that)=>{return 'https://i.imgur.com/'+getUrlParam('id', that.href);}},
            'imgflare.com':{rule : '#source', attr : 'src', form : {method : 'post', reCaptcha: true, headers : {'Content-Type': 'application/x-www-form-urlencoded'}}},//同imgbabes.com,需要 cookies,recaptcha 验证
            'eroticmovies.xyz':{attr:'src', rule : '#view1 img', path : /\/(?:(?!new|top|folder\/.+)$).*/i},
            'piccy.info': {attr:'src',rule:'#mainim', path:/view\d\/.+/},
            'vfl.ru': {attr:'src',rule:'#f_image>img', path:/fotos\/.+/i},
            //blog
            '3xplanet.com':{errorTips : '.td-404-title', rule : '#view-content>img, img#show_image', attr : 'src', path : /\/view(?:image)?\/\d+.html/i},
            'xpic.org': {attr:'src',rule:'.img-inner.dark>img', path:/cover-\w+/i},
        },
        HostArr=[],
        HostToList={},
        HostToListArr={//跳转域名对照表(某些图床需要跳转到本体站)
            '3xplanet.com': ['3xplanet.net'],
            //此处的名单会将域名进行映射,而非规则引用

            //'pixsera.net':['imgsee.net']
        },
        CurrentHostListArr={//通用规则域名映射表
            '.centred': ['pornhd720p.com','dimtus.com','picmoney.org','xxxwebdlxxx.org','olarixas.xyz','imgdawgknuttz.com','trans.firm.in'],
            '#imgContinue': ['uvonahaze.xyz','damimage.com','dewimg.com'],
            '#image-viewer-container': ['hentai-covers.site', 'images.free4.xyz'],
            'soDaBug':['pixsera.net','pixsense.net',
                       'imgblaze.net','imgair.net','imghot.net','imgsee.net','imgfrost.net','imgsky.net','imgfile.net','iceimg.net',
                       'imgbig.xyz','imgtigr.xyz','imgkaka.xyz','imgkuiw.xyz','imgveni.xyz','imgpak.xyz','imglina.xyz','imgalor.xyz','imgirx.xyz','imgwewo.xyz','imgbird.xyz','imgkr.xyz','imglin.xyz','imgkoi.xyz',
                       'imgjut.buzz','imgwang.buzz','imgpekele.buzz','imgbbd.buzz','imgyng.buzz','imglqw.buzz','imgmeno.buzz','imgtrw.buzz',
                      ], //主站 'pixsera.net',
            'metaInIMG' : ['servimg.com','imgbb.com','ibb.co',
                           'postimgs.org','postimages.org',
                           'pixxxels.cc','picmoney.org',
                          'rintor.space',
                          ],
            'metaInIMG&Direct' : ['thumbsnap.com','i.pixxxels.cc'], //支持直链 或者 metaInIMG
            'metaInSmallToBig' : ['imgtaxi.com','imgadult.com','imgwallet.com','imgdrive.net'],
            'PostPic' : ['picbaron.com','imgbaron.com','kropic.com', 'imgsto.com','silverpic.com','kvador.com','picdollar.com','imgstar.eu','imgsen.com',
                         'pics4you.net', 'pics4upload.com',],
            'notSupport':['imgrock.net','imgrock.pw',],
            'noLink' : ['img.yt','imgseed.com','imgseeds.com','imgchili.net','imgrock.co','erimge.com','imgmega.com','imgmaster.net','imgcash.co','imgserve.net','imgdino.com','imgtiger.com','imgdream.net',
                        'imgbros.xyz','imgjazz.xyz','imgao.xyz','imgxx.xyz','imageking.xyz','picusha.net','imgazure.com',
                        'imgweng.xyz', //soDabug
                        'beautifulero.com','xxxwebdlxxx.top','imghost.top','placeimg.net','xxx.kodiak.top','multiimg.com','blameless.work','imageshtorm.com','xaoutchouc.live','bustyimg.top','picshost.info','pic.hotimg.site','hdmoza.com'//.centred 规则 —— /img-\w+.html
                       ], //已失效的图床网站
            'direct403' :[],
            'direct' : ['imgur.com','pone.bnimg.com','image01.myfiles.link','pics.dmm.co.jp','x8img.com','images2.imgbox.com'], //直接加载的图床
            'MyFileShare' : ['skviap.xyz','ovkwiz.xyz'],
            '#screenshot-image': ['skr.sh','skrinshoter.ru'],
            '#photo': ['hostpic.org'],
            '#imgpreview': ['pixroute.com'],
            'chevereto.com': ['empornium.ph','empornium.sx'],
            '.main-image': ['imagebam.com'],
            '.picview': [],
            'center>a>img': ['imgprime.com']
//未处理
        },
        JumpHost={ //跳转链规则表,跳转链处理只应用于相应的图片链接上
            'alabout.com':{
                path: '/j.phtml', //跳转链执行文件
                url: 'url', //存放原始链接地址的参数
            },
            'jojodl.pw':{path: 'goto.php',url: 'gogourl',},
            'jojodl.com': {path: 'goto.php',url: 'gogourl'},
        },
        domainRule={ //需要特殊支持的网站(如ajax加载的描述数据,附加功能)
            'github.com': {
                CSP : true, //受到内容安全策略限制,使用Base64加载图片
                callback : function(){
                    console.log('内容安全策略限制,使用Base64加载图片');
                }
            },
            'alabout.com' : {
                callback : function(){
                    let PageID=Number(getUrlParam('id'));
                    $('a[href="./list.php"]').text('首页').css({'padding':'0 10px'});
                    $('a[href="./list.php"]').before($('<a>').attr({'href':'/view.php?id='+(PageID-1)}).text('上一页 ['+(PageID-1)+']'))
                    $('a[href="./list.php"]').after($('<a>').attr({'href':'/view.php?id='+(PageID+1)}).text('下一页 ['+(PageID+1)+']'))
                }
            },
            'blogspot.com' : {
                callback : function(){
                    console.log('注入CSS');
                    GM_addStyle(`.post-body img, .first-img{height:auto!Important;}`);
                }
            },
            'jojodl.pw' : {
                MObserver: '#description',
                callback: function(){

                    //影片规则
    let VideoID_Rule={
        'RJ\d+' : {name:'DLsite', regexp: /(R[EJR]\d{6})/i, replace : '$1'},
        '1Pondo' : {name: '1Pondo', regexp: /1pondo-(\d{6})|(\d{6})-1pon/i, replace : '1Pondo $1$2'},
        'Caribbean' : {name: 'Caribbean', regexp: /Caribbean(?:com)?[-_](\d{6}[-_]\d{3})|(\d{6}[-_]\d{3})[-_]Carib/i, replace : 'Caribbean $1$2'},
        'Heyzo' : {name: 'Heyzo', regexp:  /Heyzo[_-](\d+)/i, replace : 'Heyzo-$1'},
        'H0930' : {name: 'H0930', regexp: /H0930-(\w+)/i, replace : 'H0930-$1'},
        '10musume' : {name:'10musume', regexp: /(\d{6}_\d{2})[-_]10mu/i, replace : '10musume $1'},
        'Pacopacomama' : {name: 'Pacopacomama', regexp: /(\d{6}_\d{3})-paco/i, replace : 'Pacopacomama $1'},
        'FC2-PPV': {name: 'FC2-PPV', regexp: /FC2[-_]PPV[-_](\d{6})/i, replace : 'FC2-PPV-$1'},
        'Uncensored Leaked' : {name: 'Uncensored Leaked', regexp: /([A-Z]{2,4}[-_]\d{2,4})/i, replace : '[Uncensored Leaked]$1', titleRegExp: /Uncensored Leaked/i},
        'DMM' : {name:'DMM', regexp: /([A-Z]{2,4}-\d{2,4})/i, replace : '$1'},
    }

                    if(/detail/i.test(location.href)) {
                        $('input[placeholder="Search"], button[type="submit"]').removeAttr('disabled'); //解锁搜过功能
                        $('#filelistBox').insertAfter('.form-group'); //移动文件列表
                        let tagObj=$('#description').next();
                        tagObj.insertBefore('#description'); //移动分类标签

                        //排版调整
                        //主内容框架
                        GM_addStyle(`
body>.container {margin:15px 0;max-width:100%;}
body>.container>.row{width:400px;position:sticky;top:155px;z-index:1;}
body>.container>.card{width:850px;margin:0 15px;}
body>.container>.row, body>.container>.card {display:inline-flex;}
.newTag {background-color:#ff008d!important;}
`);
                        $('.torrent-file-desc').parent().appendTo('body>.container');
                        //磁力链
                        GM_addStyle('.form-group{position:sticky;top:55px;z-index:2;}');
                        $('.form-group, .entry-title').prependTo('.torrent-file-desc');//.prependTo('body>.container');


                        let magnetBtn=$('.btn-primary:not("#copyBtn")'),
                            magnetA=magnetBtn.find('a'),
                            magnetHash=magnetA.attr('href').replace(/.+urn:btih:(\w{40}).+/i, '$1');
                        magnetA.addClass(magnetBtn.attr('class'));
                        magnetBtn.removeClass();

                        console.log(webTitle, magnetHash);
                        if(webTitle=='- Real Life:Videos - JoJoDL') document.title=localStorage[magnetHash];

                        if(blockList.test($('.torrent-file-list').text())) {
                            GM_addStyle(`a.btn.btn-primary.btn-lg ::after {content: "X";color: red;font-size: 50px;padding: 0;margin: 0;position: absolute;top: 0;left: 8px;text-align: center;}`);
                        };


                        let tagList={},
                            title=$('.entry-title').text().trim(),
                            VideoID=localStorage[magnetHash]||'',
                            VideoID_Number,
                            titleArr=title.split(/[- ]/g);

                        if(!VideoID) {
                            for(let key in VideoID_Rule) {
                                if((VideoID_Rule[key]['titleRegExp'] && VideoID_Rule[key]['titleRegExp'].test(title))||VideoID_Rule[key]['regexp'].test(title)) {
                                    console.warn(key, VideoID_Rule[key]['regexp'], title, title.match(VideoID_Rule[key]['regexp']));
                                    VideoID=VideoID_Rule[key]['replace'].replace('$1', title.match(VideoID_Rule[key]['regexp'])[1]);
                                    console.warn(VideoID);
                                    VideoID_Number=VideoID?VideoID.match(VideoID_Rule[key]['regexp'])[1]:title;
                                    break;
                                }
                            }
                        };
                        VideoID_Number=VideoID?VideoID.match(/(\d{3,6}(?:[-_]\d{2,3})?)/i,'')[1]:!VideoID_Number?title.text().match(/(\d{3,6}(?:[-_]\d{2,3})?)/i,'')[1]:title;

                        $('.tag').each(function(){
                            tagList[$(this).text()]=$(this).text();
                            //#ff008d
                        })
                        console.warn(tagList, VideoID_Number, titleArr);

                        if(VideoID&&VideoID.length>0) {
                            console.warn('%c VideoID: '+VideoID, 'color: green;')
                            magnetA.attr('href', magnetA.attr('href')+"&dn="+VideoID.toString().toUpperCase());
                            if(/FC2[-_ ]?PPV/i.test(VideoID)) {
                                magnetA.click(function(){
                                    es(VideoID_Number);
                                });
                            }
                        }
                        if(VideoID_Number&&VideoID_Number.length>0) {
                            VideoID_Number=VideoID_Number.toString();
                            if(!tagList[VideoID_Number]) $('<a>').attr({'class':'tag newTag', href:'/en/search/ac0/s_'+VideoID_Number}).text(VideoID_Number).prependTo(tagObj)
                        }
                        $('body').on('click', 'a.tag', function(e){
                            //GM_openInTab('es://'+$(this).text(), {active :true, insert:true, setParent : true});
                            if(e.ctrlKey) {
                                es($(this).text());
                                return false;
                            }
                            return true;
                        })
                    } else {
                        GM_addStyle(`.warn18::before {content:'🔞';color:red;}
                        .FindNewPage::before {content:'🔎';color:blue;}`);

                        //页码查找资源
                        function FindNewPageFn ($this, NextPageID, ActivePageID){
                            GM_xmlhttpRequest({
                                url: `/zh/page/${NextPageID}`,
                                nocache: true,
                                onload: (result)=>{
                                    let doc=parsetext(result.response),
                                        $thisHash=$this.href.match(/\w{40}/).toString();
                                    console.log(NextPageID, doc, $thisHash, $(doc).find((`a[href*="${$thisHash}"]`)).length);
                                    if($(doc).find((`a[href="${$thisHash}"]`)).length>0) {
                                        notifyMe(`最新页码${NextPageID},新增了${NextPageID-ActivePageID}页`,{},function(){
                                            location.href=`https://jojodl.pw/zh/page/${NextPageID}`;
                                        })
                                        return false;
                                    }
                                    else if(NextPageID<100) {
                                        NextPageID++;
                                        FindNewPageFn($this, NextPageID, ActivePageID);
                                    }
                                    else {
                                        alert('已经到页码末尾,未找到记录');
                                        return false;
                                    }
                                }
                            });
                        }


                        $('.torrent-name>a').each(function(e){
                            //插入找寻最新页码位置按钮
                            let $this=this,
                                FindNewPage=$('<span class="FindNewPage">');
                            FindNewPage.click(x=>{
                                let ActivePageID=+($('.btn.btn-secondary.active').text()),
                                    NextPageID=ActivePageID<=100?ActivePageID++:ActivePageID;
                                let newPageID=FindNewPageFn($this, NextPageID, ActivePageID);
                            });
                            $(this).before($this, FindNewPage)

                            //列表中没有标题的,获取文件列表名字
                            //没有标题,添加标题
                            if($(this).text()=='') {
                                let $this=$(this),
                                    hash=this.href.replace(/.+\/(\w{40})\.html$/i, '$1');
                                if(hash && localStorage[hash]) {
                                    $this.addClass('warn18');
                                    $this.text(localStorage[hash]);
                                } else {
                                    GM_xmlhttpRequest({
                                        url: this.href,
                                        onload: (result)=>{
                                            let id=result.response.match(/\d+_\d+(?=\/filelist)/).toString();
                                            //获取文件列表内容
                                            GM_xmlhttpRequest({
                                                url: `/zh/detail/${id}/filelist`,
                                                onload: (result)=>{
                                                    let folderTitle=$(result.response).find('.folder').text();
                                                    $this.addClass('warn18');
                                                    localStorage[hash]=folderTitle;
                                                    $this.text(folderTitle);
                                                    //let id=result.response.match(/\/(\d+_\d+)\/filelist/);
                                                }
                                            });
                                        }
                                    });
                                }
                            }
                        });
                    }
                }
            },
            'jojodl.com' : {MObserver: '#description'}
        };
    let domainRuleConfig=domainRule[domain.toLowerCase()]||domainRule[hostRoot];

    //配置加载
    if(typeof(GM_getValue('config'))=='undefined') {
        console.warn(typeof(GM_getValue('config')), new setting(false,false))
        GM_setValue('config', new setting(false,false));
    } else {
        Config = GM_getValue('Config');
    }




    /*规则映射*/
    for(let i in CurrentHostListArr){ //通用规则域名表转 ImgHost
        //console.log(i);
        for(let j=0;j<CurrentHostListArr[i].length;j++){
            ImgHost[CurrentHostListArr[i][j]]=ShareHost[i]; //通用规则域名映射表中的域名存入 ImgHost
        }
    }
    //for(let i in ShareHost['direct']) ImgHost[ShareHost['direct'][i]]={'direct':true} //直接连接表加入 ImgHost


    for(let i2 in HostToListArr){
        console.log(i2);
        for(let j2=0;j2<HostToListArr[i2].length;j2++){
            HostToList[HostToListArr[i2][j2]]=i2; //存入跳转域名对照表
            ImgHost[HostToListArr[i2][j2]]=ImgHost[i2];
        }
    }

    for(let HostObj in ImgHost) HostArr.push('a[href*="'+HostObj+'"]');					//插入域名对象到数组
    //log('- 图床表 -', ImgHost);

    console.group(' -----===== Ajax ImageHost =====----- ');

    if(!ImgHost[hosts.toLowerCase()]||!ImgHost[domain.toLowerCase()]) { //当前网站不是图床网站的时候


        log('- 已匹配的图床链接 -', $(HostArr.join(",")));
        /*选择器获取支持的图床链接,显示图片*/

        $(document).ready(function(){

            //跳转链预处理,处理掉网页中的跳转链
            if(JumpHost[domain]) {
                console.log('domain', domain, JumpHost[domain]['path']);
                $('a[href*="'+JumpHost[domain]['path']+'"]').each(function(){
                    //处理跳转链
                    //log('-处理跳转链-', this.search, JumpHost[this.host.replace(/^www\./i,'').toLowerCase()]['url'], new URLSearchParams(this.search), this.search);
                    this.href=new URLSearchParams(this.search).get(JumpHost[this.host.replace(/^www\./i,'').toLowerCase()]['url']);
                    //this.href=decodeURIComponent(getUrlParam(JumpHost[this.host.replace(/^www\./i,'').toLowerCase()]['url'], this.href));
                })
            };
        })

        //console.table(ImgHost);
        GM_addStyle('.ImageHostAjax{max-height:100%!Important;max-width:100%!Important;}');

        //图像加载方法原型
        let ajaxLib = {
            blobImg : (AjaxConf, src, that) => { //该方法应用于图床规则
                log('-blobImg-', src, that);
                log(AjaxConf);
                src=src||$(that).find('img').src;
                let srcUrl=new URL(src);
                AjaxConf.headers={
                    Host : srcUrl.host,
                    //'Host' : src.replace(/https?:\/\/([^/]+)\/.+/i, '$1'),
                    'Referer': src, //AjaxConf.headers.referer||src,
                    'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8',
                    'Content-Type': 'image/jpeg',
                    'Cache-Control': 'cache',
                    'Sec-Fetch-Dest' : 'image',
                    'Sec-Fetch-Mode' : 'no-cors',
                    //'Sec-Fetch-Site': 'same-site',
                    'Sec-Fetch-Site': 'cross-site', //跨域请求
                    'Pragma': 'no-cache'
                }

                GM_xmlhttpRequest({
                    url: src,
                    method: 'get',
                    responseType : 'blob',
                    headers : AjaxConf.headers,
                    onload: function(result){
                        let blob=new Blob([result.response]),
                            bolbUrl=URL.createObjectURL(blob);
                        console.log('blob Img 图片请求成功', result);
                        console.table([src, result.finalUrl, bolbUrl]);
                        $('img[data-AjaxSrc="'+that.href+'"]').attr('src', bolbUrl);
                    },
                    onerror : function(e, result) {
                        console.warn('blob Img 图片请求失败', result)
                        //return result;
                    }
                });
            },
            PostImg : (AjaxConf, src, that) => {

            },
            base64Img : (AjaxConf, src, that) => { //该方法应用于存在CSP限制的网站
                console.log('base64Img方法')
                GM_xmlhttpRequest({
                    url: src,
                    responseType: 'arraybuffer',
                    method :"GET",
                    headers: {
                    },
                    onload:function(xhr){
                        console.log('base64Img', xhr);
                        let url=arrayBufferToBase64(xhr.response);
                        $('img[data-AjaxSrc="'+that.href+'"]').attr('src', 'data:image/jpeg;base64,'+url);
                    },
                    onerror : function(e, result) {
                        console.warn('base64 Img 图片请求失败', e)
                        //return result;
                    }
                });


                function arrayBufferToBase64(buffer) {
                    let binary = '';
                    let bytes = new Uint8Array(buffer);
                    let len = bytes.byteLength;
                    for (let i = 0; i < len; i++) binary += String.fromCharCode(bytes[i]);
                    return window.btoa(binary);
                }
            }
        }

        /******
        **
        **  第二阶段 —— 图片集预处理进程 **
        **
        **
        1、对符合脚本处理要求的链接进行预处理,以便于后续的核心请求函数获取图片真实地址
        2、处理内容保护,跳转链、适用规则筛选
        3、根据适用规则对请求数据加工
        **
        **/
        //
        let ImageAjaxPre = (i, that) => { //that = A 超链接,i = index

            //处理跳转链
            if(JumpHost[that.host.replace(/^www\./i,'').toLowerCase()]) that.href=decodeURI(getUrlParam(JumpHost[that.host.replace(/^www\./i,'').toLowerCase()]['url'], that.href));
            //处理域名
            if(HostToList[that.host.toLowerCase()]) that.host=that.host.toLowerCase().replace(that.host,HostToList[that.host.toLowerCase()]);

            let thisDomain=that.hostname.replace(/^www\./i,''),
                HostConf=ImgHost[that.host]||ImgHost[thisDomain]; //图床规则装载

            console.log('ImageAjaxPre: ', HostConf||'图床规则装载失败(可能不存在该域名规则)', that, that.host, thisDomain);
            if(!HostConf.host) HostConf.host=that.host;

            //过滤掉超链接中的[UBB]内容
            that.href=that.href.replace(/%5B\/?img%5D/ig,'').replace(/\[\/?img\]/ig,''); //过滤掉 [/?img]

            //配置数据加工
            HostConf.href=that.href;

            msg({'title': `2、ImageAjaxPre HostConf —— ${that.host}`, css:"color: red;background:yellow", type:'title'},
                {'title':'Url Path', 'text':that.pathname, css:'color: green;'},
                {'title':'Config', 'text':HostConf, css:'color: #DD045B;'},
                {'title':'Path匹配', 'text':HostConf['path']?HostConf['path'].test(that.pathname):'无路径匹配', css:'color: green;'}
               );

            /**
            **** 规则适配顺序 ****
            1、适配网站专用规则
            2、重定向网址
            3、直链
            4、直链403情况(未完成)
            5、不支持网站(alt内容提示)
            6、失效图床(alt提示图床失效)
            7、通用规则(调取核心图像请求,由核心处理)
            **/
            if(HostConf['isIMG']) { //使用内部专用的处理方法
                if(HostConf['isIMG'](that)) CallImageHostAjaxCore(that, HostConf);
            } else if(HostConf.redirect){
                that.href=HostConf.redirect(that);
                ImageAjaxPre(i, that);
            }
            else if(HostConf['direct']) { //可以直接进行加载,不需要 ajax
                $(that).append('<br>',$('<img>').attr({'class':'ImageHostAjax', 'src': that.href, 'alt': "图片占位", 'data-AjaxSrc': that.href}));
            } else if(HostConf['direct403']) {
                GM_xmlhttpRequest({
                    url: AjaxConf.urls,
                    data : $.param(AjaxConf.data.formdata, true),
                    method: AjaxConf.data.method,
                    headers : AjaxConf.data.headers,
                    cookie: AjaxConf.cookie,
                    onload: function (result) {
                    }
                });
            } else if(HostConf['notSupport']) {
                $(that).append('<br>',$('<img>').attr({'class':'ImageHostAjax', 'alt': "因防盗链系统,不支持图床: " + HostConf.host}));
            } else if(HostConf['noLink']) {
                $(that).append('<br>',$('<img>').attr({'class':'ImageHostAjax', 'alt': "已失效图床: " + HostConf.host}));
            }
            //else if(HostConf['path']&&HostConf['path'].test(that.href)) { //需要匹配路径的规则
            else {
                CallImageHostAjaxCore(that, HostConf);
            }
        }

        //用于第二阶段,调用核心进程
        function CallImageHostAjaxCore(that, HostConf){
            //无路径匹配,获取图片
            $(that).append('<br>',$('<img>').attr({'class':'ImageHostAjax', 'src': '', 'alt': "图片占位", 'data-AjaxSrc': that.href}));
            if(HostConf['pre']) HostConf['pre'](that.href, HostConf);

            HostConf.ImageHostRule={ //用于 AjaxCore 中获取图像地址的规则
                'errorTips': HostConf['errorTips'],
                'selection':HostConf['rule'],
                'attr':HostConf['attr']||'src',
                'text':HostConf['text'],
            };
            ImageHostAjaxCore({ //调用核心请求
                'urls': that.href,
                'host': that.host,
                'HostRuleConf' : HostConf,
                'ImageHostRule': HostConf['ImageHostRule'],
                'data':{method:HostConf['method']||'get', formdata: HostConf['formdata']||{}, headers:HostConf['headers']||{'Content-Type': 'application/x-www-form-urlencoded',}},
                'cookie':HostConf['cookie']||'',
                'form': HostConf['form']||'', //需要二次提交表单的时候使用
                'onload' : HostConf['onload'], // ImageHostAjaxCore 使用该 onload 方法时,则不使用 success 的处理结果
                'process' : HostConf['process'], //站点无 onload 方法时,ImageHostAjaxCore使用该 process 方法,不使用 success 的处理结果
                'success':function(src, doc){
                    //log('-ImageHostAjaxCore-', HostConf, '---', src);
                    //此属性为处理 ImageHostAjaxCore 返回结果使用,使用 HostConf['success'] 时,则先处理 HostConf['success'] 中的内容
                    if(HostConf['success']) HostConf['success'](that, src);

                    //console.log('%c 获取到地址:'+src, 'color:green');
                    if(HostConf.src) src=HostConf.src(src); //使用对应站点规则,内置的特殊方法提取Src
                    if(HostConf.big) src=smallToBig(src); //将小图转换为大图,来源于 metaInSmallToBig 规则

                    msg({'title': HostConf.host + ' 核心结果', css:'color:red', type:'title'}, {'title':'HostConf: ', 'text': HostConf, css:'color:red', type:'warn'});


                    //屏蔽了热链接的图床需要二次get图片资源,以 blob 输出
                    if(domainRuleConfig && domainRuleConfig.CSP) {
                        ajaxLib.base64Img(HostConf, src, that);
                    }
                    else if(HostConf['blobImg']) {
                        ajaxLib.blobImg(HostConf, src, that);
                    }
                    else {
                        //显示图片内容
                        $('img[data-AjaxSrc="'+that.href+'"]').attr('src', src);
                    }

                    //移除旧的缩略图
                    $(that).find(HostConf.thumb).remove();
                }
            });
        }
        //图片集 Ajax 请求发起进程
        /***
        *
        *   第一阶段 ——
        *
        *
        ***/
        let AjaxCoreProcess=(doc)=>{ //doc 由站点匹配结果传递
            if(doc) {
                let newDoc=$(doc).find(HostArr.join(","));
                console.log('图片处理核心:', doc, newDoc);
                newDoc.each(function(i, e){
                    ImageAjaxPre(i, e)
                });

                $(doc).find('img').on({ //绑定 title 事件
                    'mouseover' : function(e){
                        if(!this.title && !$(this).data('img-title')) {
                            if(this.src) {
                                $(this).data('img-title',this.src);
                                this.title=$(this).data('img-title');
                            }
                        } else if(!this.title && $(this).data('img-title')) {
                            this.title=$(this).data('img-title');
                        }
                    },
                    'mouseout' : function(e){
                        if(this.title==$(this).data('img-title')) {
                            $(this).removeAttr('title');
                        }
                    }
                });
            } else {
                //组合ImgHost,用于匹配图床地址
                $(HostArr.join(",")).each(function(i, e){
                    ImageAjaxPre(i, e);
                });
            }
        }

        console.log('当前网站:', location, location.href, domain, hostRoot)
        //种子站点匹配,这些网站需要专用规则处理
        if(domainRuleConfig) {
            console.log('domainRuleConfig:', domainRuleConfig);

            if(domainRuleConfig['MObserver']) {
                MObserver(domainRuleConfig['MObserver'], function(mutations, observer){
                    //mutations 是每次变化的记录集,数组类型
                    //console.log('observer: ', observer)
                    //console.log('mutations:', mutations);
                    for(let mutation of mutations) {
                        let type = mutation.type;
                        //console.log(type, mutation);
                        switch (type) {
                            case "childList":
                                console.log(" ---=== 节点发生了增加或者删除 ===---");
                                //遍历添加事件的节点
                                for(let x of mutation.addedNodes) { //遍历添加节点记录
                                    //只处理非文本节点,不处理已经包含了 ImageHostAjax className 的节点
                                    if(x.nodeType==1 && x.nodeName!=="BR" && x.className!=="ImageHostAjax") AjaxCoreProcess(x);
                                }
                                break;
                            case "attributes":
                                console.log(`The ${mutation.attributeName} attribute was modified.`);
                                break;
                            case "subtree":
                                console.log(`The subtree was modified.`);
                                break;
                            default:
                                break;
                        }
                    }


                    //=============》增加节点后会执行的代码 ↓
                    /*
                    var nodeAdded = mutations.some(function(x){ //是否增加了节点
                        console.log(x);
                        return x.addedNodes.length > 0;
                    });
                    console.log('nodeAdded: ', nodeAdded);
                    if (nodeAdded) {
                        if(nodeAdded.nodeType==1) {
                            //core(nodeAdded);
                        }

                        console.log(mutations);
                        return true||false; //是否停止监听事件
                    }
                    */
                    //=============》增加节点后会执行的代码 ↑

                }, true)
                //document.querySelector(domainRuleConfig['DOMNodeInserted']).addEventListener('DOMNodeInserted', core);
            }
            if(domainRuleConfig['callback']) {
                domainRuleConfig['callback'](); //网站特殊支持规则
                if(domainRuleConfig.CSP) AjaxCoreProcess();//ImageAjaxPre('base64');
                else AjaxCoreProcess(); //调用图片加载进程
            }
        } else {
            console.log('通用站点规则')
            AjaxCoreProcess();
        }

    }

    console.groupEnd(' -----===== Ajax ImageHost =====----- ');

    //第三阶段——图像加载核心进程
    function ImageHostAjaxCore(AjaxConf){

        let Ajax_onload=(doc, sources)=>{ //Ajax 成功结果处理
            console.log(`请求来源:${sources}`);

            msg({'title': AjaxConf.host + ' ajax 结果' + " —— " + AjaxConf.urls, css:'color:red;background:#a0ffc0', type:'title'}, {'title': 'AjaxConf', text:AjaxConf, css:"color: green;"});

            let result=$(parsetext(doc)); //返回的内容,没有 responseText
            let src, t = result.find(AjaxConf.ImageHostRule.selection), //使用站点规则的 rule 来做选择器
                errorTips = result.find(AjaxConf.ImageHostRule.errorTips).text();

            //检测是否存在错误提示
            if(errorTips) {
                console.warn('图片不存在:', errorTips);
                console.log(AjaxConf.urls, this);

                $('img[data-AjaxSrc="'+(AjaxConf.OriginalUrl||AjaxConf.urls)+'"]').attr('alt', `图片不存在:${errorTips.trim()}`);
            }
            //检测是否链接已过期
            else if(doc=='Link expired') {
                $('img[data-AjaxSrc="'+(AjaxConf.OriginalUrl||AjaxConf.urls)+'"]').attr('alt', `链接已过期:${doc}`);
            }
            else { //没有错误提示时,进入图片地址识别流程
                log(t, AjaxConf.ImageHostRule.text, t.text(), t.attr(AjaxConf.ImageHostRule.attr));
                src = AjaxConf.ImageHostRule.text ? t.text(): t.attr(AjaxConf.ImageHostRule.attr);
                msg({'title': AjaxConf.host + ' responseText', text:!src?'图片地址无法显示,responseText:\n'+doc:'已找到匹配图片,不显示请求内容', css:"color: #a0ffc0;"})
                msg({'title': '图片地址', text:src, css:"color: green;"}, {'title': 'img', text:t, css:"color: green;"});
                if(!src) {
                    notifyMe('未获取到图片地址');
                    debugger;
                    return false;
                }
                AjaxConf.success(src, doc);
            }
            //return t;
        }

        //核心进程开始处理
        if(AjaxConf.data && AjaxConf.data.method=='post') {
            console.warn('使用 Post 方法')

            GM_xmlhttpRequest({
                url: AjaxConf.urls,
                data : $.param(AjaxConf.data.formdata), //获取表单数据
                cookie: AjaxConf.data.cookie||'',
                method: 'post',
                headers : AjaxConf.data.headers||{
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                onload: function(result){
                    console.log('form 请求成功', result)
                    let formDoc = result.responseText; //转换可被jQuery识别的对象结构
                    console.log('ImageHostRule.selection', $(formDoc).find(AjaxConf.ImageHostRule.selection))
                    switch(result.status) {
                        case 404:
                            $('img[data-AjaxSrc="'+(AjaxConf.OriginalUrl||AjaxConf.urls)+'"]').attr('alt', `404错误,图片不存在`);
                        break;
                        default:
                        Ajax_onload(formDoc);
                    }
                }
            });
        } else { //默认 Get 方法
            console.warn('使用Get方法')
            //console.log(AjaxConf);

            if(AjaxConf.HostRuleConf.reHost) { // soDaBug 处理方法,替换掉 Host
                AjaxConf.OriginalUrl=AjaxConf.urls; //备份原始地址
                //AjaxConf.urls=AjaxConf.urls.replace(/(?<=\/\/)[^/]+/, AjaxConf.HostRuleConf.reHost);
                let newURL=new URL(AjaxConf.urls);
                newURL.host=AjaxConf.HostRuleConf.reHost
                AjaxConf.urls=newURL.href;
                log('-reHost-', AjaxConf.urls);
            }

            if(AjaxConf.HostRuleConf.NoFileName) { //请求的地址不包含文件名
                AjaxConf.urls=AjaxConf.urls.replace(/\/[^/]+\.(jpg|png|gif|webp)$/i, '');
                AjaxConf.href=AjaxConf.urls;
                log('-NoFileName-', AjaxConf.urls)
            }

            if(AjaxConf.data.headers) {
                AjaxConf.data.headers.referer=AjaxConf.urls;
            }

            msg({'title': AjaxConf.host + ' Ajax Data', type:'title', css:"color: red;background:#a0a0ff"},
                {'title': 'AjaxConf', text: AjaxConf, css:"color: #0EB9F9;"},
                {'title': 'AjaxConf data', text:AjaxConf.data, css:"color: yellow;"}
               );

            GM_xmlhttpRequest({
                url: AjaxConf.urls,
                data : $.param(AjaxConf.data.formdata, true),
                method: AjaxConf.data.method,
                headers : AjaxConf.data.headers,
                cookie: AjaxConf.cookie,
                onload: function (result) {
                    log('-Ajax Get- ', result);
                    //用于比较请求地址与响应地址是否一致
                    console.table({'sourcesUrl': AjaxConf.urls, 'finalUrl': result.finalUrl, reHost: AjaxConf.HostRuleConf.reHost});


                    if(AjaxConf.urls!==result.finalUrl) { //请求地址与响应地址不一致,进行更新之后再重新请求
                        AjaxConf.OriginalUrl=AjaxConf.urls; //备份原始地址
                        AjaxConf.urls=result.finalUrl;
                        console.log(`替换URL为:${AjaxConf.urls}`);
                        ImageHostAjaxCore(AjaxConf);
                        return false;
                    }

                    if(AjaxConf['onload']) {
                        AjaxConf['onload'](result, AjaxConf);
                    }
                    // * 此属性为 ImageHostAjaxCore 核心处理结果,如果要使用站点自有的 onload 方法,请在站点配置(AjaxConf)时设置 onload 属性或 process 属性
                    // *

                    //let doc = parsetext(result.responseText), //转换可被jQuery识别的对象结构

                    console.log(result.responseText, $(result.responseText));
                    let doc = result.responseText, //转换可被jQuery识别的对象结构
                        webTitle = $(doc).find('title').text(); //获取网页标题

                    if(webTitle.search('安全检查')>-1) { //检查网页标题
                        $('img[alt="'+AjaxConf.urls+'"]').attr('alt','需访问一次网站,通过安全检查');
                        GM_notification(webTitle, '需访问一次网站,通过安全检查', '');
                        console.log('需访问一次网站,通过安全检查');
                        return false;
                    }

                    //console.log('123123', doc);
                    console.log('AjaxConf.form', AjaxConf.form);
                    if(AjaxConf.form) { //执行二次请求才能获取图片
                        if(typeof AjaxConf.form=='boolean') { //初始化 form 数据
                            console.log('需要主动生成 form 表单数据');
                            AjaxConf.form={};
                            AjaxConf.form.method='post';
                            AjaxConf.form.header={
                                'Content-Type': 'application/x-www-form-urlencoded',
                            }
                        }
                        console.log(' 发现 form 表单', $(parsetext(doc)).find('form'), $(parsetext(doc)).find('form').length);
                        let docForm=$(parsetext(doc)).find('form');
                        if(docForm.length>0) { //存在可提交表单时
                            //AjaxConf.form();

                            let formCookie; //formCookie提取缓存
                            if(AjaxConf.form.cookie) {
                                //获取请求的Cookie
                                $(doc).filter('script:contains($.cookie)').each(function(i, e){
                                    console.log(this);
                                    let cookieArr=this.textContent.match(/\$.cookie\('([^\']+)'\s*,\s*'([^\']+)'\s*,\s*.+\)/),
                                        cookie_name=cookieArr[1],
                                        cookie_value=cookieArr[2];
                                    formCookie=cookie_name+"="+cookie_value+'; ';
                                });
                                //融合 Cookie 值

                                $.map(AjaxConf.form.cookie, function(value, name) {
                                    console.log(docForm.find(value).length);
                                    if(docForm.find(value).length>0) //选择器有结果时
                                        formCookie+=name+"="+docForm.find(value).val()+'; ';
                                    else //选择器没有结果,直接赋值
                                        formCookie+=name+"="+value;
                                });
                                //AjaxConf.form.cookie+=Fn_xmlCookies([['file_code', docForm.find('[name="id"]').val()], ['fcode', docForm.find('[name="id"]').val()]]);
                                console.warn('表单Cookie:', AjaxConf.form.cookie, formCookie);
                            }

                            let PostData=$(doc).filter('form').serialize();
                            if(AjaxConf.form.reCaptcha) {
                                //PostData+="&g-recaptcha-response="+$(docForm).find('.g-recaptcha').data('sitekey');

                                notifyMe('机器人检测提醒,需要输入验证码', `遇到机器人检测,请点击通知访问网站,手动输入验证码后,再刷新本页面。\n${result.finalUrl}`, function(){
                                    GM_openInTab(result.finalUrl, false);
                                })

                                $('[data-ajaxsrc="'+result.finalUrl+'"]').on('mouseover', function(){
                                    if(!$(this).attr('src')) {
                                        ImageHostAjaxCore(AjaxConf);
                                    }
                                });
                                return false;
                            }

                            console.log('PostData: ', PostData);
                            GM_xmlhttpRequest({
                                url: result.finalUrl,
                                data : PostData, //获取表单数据
                                cookie: formCookie||AjaxConf.form.cookie||'',
                                method: AjaxConf.form.method||'post',
                                synchronous: false,
                                headers : AjaxConf.form.headers||{
                                    'Set-Cookie': 'widget_session='+AjaxConf.host,
                                    'SameSite': 'None',
                                    'Content-Type': 'application/x-www-form-urlencoded',
                                },
                                onload: function(data){
                                    if(data.finalUrl.search('op=login')>0)
                                        console.warn('请求失败');
                                    else {
                                        console.log('二次 form 请求成功', data)
                                        let formDoc = data.responseText; //转换可被jQuery识别的对象结构
                                        Ajax_onload(formDoc, '二次 form 请求');
                                    }
                                }
                            });
                        } else { //免 form 提交数据
                            console.warn('不存在可提交表单');
                            Ajax_onload(doc, '免 form 提交数据');
                        }
                    } else {
                        Ajax_onload(doc, '通用方案');
                    }
                },
                onerror: function(e){
                    console.error('e error:', e);
                },
                onreadystatechange : function(e){
                    //console.log('onreadystatechange: ', e);
                }
            });
        }
    }

    function es(text){
        if(!document.querySelector('#everything')) $('body').after($('<a>').attr({'id':'everything','href':'es://'}).hide());
        $('#everything').attr('href','es://'+text);
        document.querySelector('#everything').click();
    }

    function parsetext(text){
        let doc = null;
        try {
            doc = document.implementation.createHTMLDocument("");
            doc.documentElement.innerHTML = text;
            return doc;
        }
        catch (e) {
            alert("parse error");
        }
    };

    function smallToBig(src){
        return src.replace(/\/small\//i,'/big/');
    }
    // Your code here...


    function msg(title, obj, css){
        //console.log('arguments:', arguments.length)

        for(let arg of arguments) {
            //console.log(arg);
            if(Array.isArray(arg)) { //数组模型下的内容
                if(arg.length==2) console.log(arg[0], arg[1]);
                else console.log(arg);
            } else if(typeof(arg)=='object') {
                if(arg.type) {
                    switch(arg.type) {
                        case 'title':
                            console.group('%c -----***** ' + arg.title + ' *****-----', arg.css||'');
                            break;
                        case 'table':
                            console.table(arg.text);
                        case 'warn':
                            console.warn('%c '+arg.title, arg.css||'', arg.text);
                    }
                } else if(typeof(arg.text)=='object') {
                    console.log('%c '+ arg.title +": ", arg.css||'', arg.text);
                }
                else {
                    console.log('%c '+ arg.title +": " + arg.text, arg.css||'');
                }
            }
        }
        console.groupEnd();
    }

    function Fn_xmlCookies(arr){//[[],[]]采用二维数组+对象的模式传递数据
        let xmlCookie='';
        $.each(arr, function(i, e){
            console.log(i, e);
            xmlCookie+=e[0]+"="+e[1]+"; ";
        });
        return xmlCookie;
    }

    function getUrlParam(name, url, option, newVal) {//筛选参数,url 参数为数字时
        ;
        let search = new URLSearchParams(url ? new URL(url).search : location.search);
        //log('URLSearchParams', name, url, search, search.get(name));

        return search.get(name);
    }

    //网红关注管理模块
    function Follow(){

    }

    function MObserver(selector, callback, kill, option){
        let watch = document.querySelector(selector);
        if (!watch) {
            return;
        }
        let observer = new MutationObserver(function(mutations){
            kill = callback(mutations, observer);
            if(kill) {
                console.log('停止'+selector+'的监控');
                observer.disconnect();
            }
        });
        observer.observe(watch, option||{childList: true, subtree: true});
    }

    function reCAPTCHA(){ //获取身份验证信息g-recaptcha-response

    }

    function log(...arg){
        if(log_control)
            if(arg.length>2) {
                console.group('--- arg ---');
                console.log(arg);
                console.groupEnd();
            }
            else
                console.log(arg);
    }

    function notifyMe(title, option, click) {//option {text:'', renotify:false, tag:'', requireInteraction:false, sound:'', silent:''}
        if(typeof(option)=='object'){
            title=title||option.title||document.title;
            click=option.onclick||click;

            option.requireInteraction=option.requireInteraction||false; //保持通知活动,知道确认或关闭
            option.renotify=option.renotify||option.read||false; //默认覆盖通知
            option.tag=option.tag||option.renotify?'renotify':'';
            option.sound=option.sound||"https://s3-ap-northeast-1.amazonaws.com/ssb-av-resource/resource/1573215339389b95ce2bda3c64026b8c899c4897cbcc7/1/15732153393904f02e59fcb984068b160a88cb04c6c05.mp3?v=appresource";
            option.body=option.text=option.body||option.text||'';
            option.silent=option.silent||false;
        } else { //option 为纯文本的时候
            var text=!option?title:option;
            title=!option?document.title:title;
            option={body: text, icon:GM.info.script.icon||''};
            console.log(GM.info.script.icon)
        }


        // 先检查浏览器是否支持
        if (!("Notification" in window)) {
            alert("当前浏览器不支持桌面通知,将使用 GM 通知接口");

            if(GM_notification) {
                console.log('使用GM通知接口', GM_notification)
                if(/^http/i.test(title)){
                    let title_host=title.match(/\/\/([^/]+)/)[1];
                    if(!sessionStorage[title_host]) {
                        GM_notification(title, text, '', click);
                        sessionStorage[title_host]=true;
                    }
                } else {
                    GM_notification(title, text, '', click);
                }
            }
        }

        // 检查用户是否同意接受通知
        else if (Notification.permission === "granted") {
            // If it's okay let's create a notification
            var notification = new Notification(title, option);
            if(click) notification.onclick = click;
        }

        // 否则我们需要向用户获取权限
        else if (Notification.permission !== 'denied') {
            Notification.requestPermission(function (permission) {
                // 如果用户同意,就可以向他们发送通知
                if (permission === "granted") {
                    var notification = new Notification(title, option);
                    //notification.title = title;
                    //notification.body = text;
                    //notification.icon = icon;
                    if(click) notification.onclick = click;
                }
            });
        } else if(Notification.permission == 'denied') {
            Notification.requestPermission();
        }


        // 最后,如果执行到这里,说明用户已经拒绝对相关通知进行授权
        // 出于尊重,我们不应该再打扰他们了
    }

    GM_registerMenuCommand('强制加载小图片', );

})();