一键批量加载页面[EX绅士][exhentai]

一键批量加载所有后续页面内容

Verzia zo dňa 17.04.2022. Pozri najnovšiu verziu.

// ==UserScript==
// @name         一键批量加载页面[EX绅士][exhentai]
// @namespace    exhentaigetallpage
// @version     0.6.2
// @description  一键批量加载所有后续页面内容
// @author       allence_frede
// @match     *://exhentai.org/tag/*
// @match     *://exhentai.org/*f_search*
// @match     *://exhentai.org/g/*
// @grant        none
// @require    http://code.jquery.com/jquery-1.11.0.min.js
// @license    GNU GPLv3
// ==/UserScript==

var exhentaiGetAllPage = function ($) {
  let cfg = {
    load_pages_in_once: 20,
    all_page_count: 0,
    load_page_count: 1,
    load_page_url: [],
    load_pages_at_first_open: false,
  }
  let db = null

  return {
    init: function () {
      //去除购买广告入口
      $('#spa').remove()
      //初始化
      initTool()
      initDB()
      let cfg_old = get('load_pages_in_once')
      if (Object.keys(cfg_old)) {
        Object.assign(cfg, cfg_old)
      }
      cfg_old = get('load_pages_at_first_open')
      if (Object.keys(cfg_old)) {
        cfg_old.load_pages_at_first_open = cfg_old.load_pages_at_first_open ? cfg_old.load_pages_at_first_open.bool() : false
        Object.assign(cfg, cfg_old)
      }
      loadPanel()
      openInNewTab(null)
      setNewCss()
      autoLoadPage()
    },
    pageLoadMore: function () {
      pageLoadMore()
    },
    pageViewSwitch: function () {
      pageViewSwitch()
    },
    autoLoadPageBtnText: function () {
      return autoLoadPageBtnText
    }
  }

  /**
   * 获取功能按钮文字-首次打开自动加载后续页面
   */
  function autoLoadPageBtnText() {
    return cfg.load_pages_at_first_open ? '开启首次打开自动加载' : '关闭首次打开自动加载'
  }

  /**
   * 开关首次打开自动加载后续页面
   */
  function setAutoLoadPageAtFirst() {
    cfg.load_pages_at_first_open = !cfg.load_pages_at_first_open
    set('load_pages_at_first_open', cfg.load_pages_at_first_open)
  }

  /**
   * 加载页面时识别首次打开自动加载后续页面
   */
  function autoLoadPage() {
    if(cfg.load_pages_at_first_open){
      pageLoadMore()
    }
  }
  /**
   * 注入面板
   */
  function loadPanel() {
    setPageAllCount()
    setPageNow()
    setLoadPageUrlList()
    setPanelEl()
    setPanelCss()
    setMethod()
  }

  /**
   * 读取可加载总页数
   */
  function setPageAllCount() {
    let num = $('table.ptt td').eq(-2).text()
    cfg.all_page_count = Number(num)
  }

  /**
   * 设置当前读取的页数
   */
  function setPageNow() {
    let count = 1
    let count1 = /page=(\d+)|p=(\d+)/.exec(window.location.href)
    let count2 = /\/(\d+)$/.exec(window.location.pathname)
    if (!count1 && !count2) {
      return false
    } else if (count1) {
      if (count1[1]) {
        count = count1[1]
      }
      if (count1[2]) {
        count = count1[2]
      }
    } else if (count2) {
      count = count2[1]
    }
    cfg.load_page_count = Number(count) + 1
  }

  /**
   * 设置加载页面URL列表
   */
  function setLoadPageUrlList() {
    let url_list = []
    if (cfg.all_page_count > 1) {
      let url_base = ''
      if (/\/tag\//.test(window.location.href)) {
        url_base = window.location.href.replace(/\/\d+$|\/\d+\?from=.*$/,'')+'/{p}'
      } else {
        let glup = '?'
        if(window.location.href.indexOf(glup) !== false) {
          glup = '&'
        }
        url_base = window.location.href + glup + 'p={p}&page={p}'
      }
      for (let i = cfg.load_page_count; i < cfg.all_page_count; i++) {
        url_list.push(url_base.replaceAll('{p}', i))
      }
      url_list = url_list.chunk(cfg.load_pages_in_once)
    }
    cfg.load_page_url = url_list
  }

  /**
   * 设置面板界面
   */
  function setPanelEl() {
    let el = '<div id="egap">\
      <div class="item" method="pageLoadMore">一键加载后续<span id="page-load">' + cfg.load_pages_in_once + '</span>个页面</div>\
      <div class="item page-info cursor-clear">当前已加载 \
        <span class="page-now">' + cfg.load_page_count + '</span> / ' + cfg.all_page_count + '\
      </div>\
      <div class="item" method="pageViewSwitch">图墙列表倒序</div>\
      <div class="item" method="goToTop">回到顶部</div>\
      <div class="item" method="setLoadPagesInOnce" value="设置每次加载后续页数">设置每次加载后续页数</div>\
      <div class="item" method="setAutoLoadPageAtFirst">'+autoLoadPageBtnText()+'</div>\
    </div>'
    $('body').prepend(el)
  }

  /**
   * 设置面板样式
   */
  function setPanelCss() {
    let css = '<style>\
      #egap{\
        position: fixed;\
        top:10px;\
        left:10px;\
        z-index: 5000;\
        opacity: 0.3;\
        -webkit-user-select:none;\
        -moz-user-select:none;\
        -ms-user-select:none;\
        user-select:none;\
      }\
      #egap:hover{\
        opacity:1;\
      }\
      #egap .item{\
        min-width:120px;\
        height:30px;\
        line-height:30px;\
        color:#EEEEEE;\
        background: #4f535b;\
        border: 1px solid #000000;\
        text-align: center;\
        font-size:14px;\
        cursor:pointer;\
        box-sizing: border-box;\
        padding: 0 6px;\
        margin-top: 10px;\
      }\
      #egap #newLoadPagesInOnce{\
        width: 120px;\
      }\
      #egap .cursor-clear{\
        cursor: default !important;\
      }\
    </style>'
    $('body').append(css)
  }

  /**
   * 面板绑定触发方法
   */
  function setMethod() {
    $('div[method="pageLoadMore"]').on('click', function () {
      pageLoadMore()
    })
    $('div[method="pageViewSwitch"]').on('click', function () {
      pageViewSwitch()
    })
    $('div[method="goToTop"]').on('click', function () {
      goToTop()
    })
    $('div[method="setLoadPagesInOnce"]').on('dblclick', function () {
      $(this).html('<input type="number" id="newLoadPagesInOnce">')
      $('input#newLoadPagesInOnce').on('blur', function () {
        let num = $(this).val()
        if (num) {
          var re = /^[0-9]+$/ ;
          if (re.test(num)) {
            num = Number(num)
            if (num <= 0) {
              alert('至少填写 1 !!!')
            } else {
              setLoadPagesInOnce(num)
              $('div[method="setLoadPagesInOnce"]').html($('div[method="setLoadPagesInOnce"]').attr('value'))
            }
          } else {
            alert('请输入一个正整数!!!')
          }
        } else {
          $('div[method="setLoadPagesInOnce"]').html($('div[method="setLoadPagesInOnce"]').attr('value'))
        }
      })
    })
    $('div[method="setAutoLoadPageAtFirst"]').on('dblclick', function () {
      setAutoLoadPageAtFirst()
      $(this).text(autoLoadPageBtnText())
    })
  }

  /**
   * 设置新的样式效果
   * 主要用于适配 高分辨屏幕 和 竖屏
   */
  function setNewCss() {
    $('#gdt .c').remove()
    let style = '\
      <style type="text/css">\
        #gdt{\
          max-width: none !important;\
          display:  grid !important;\
        }\
        @media screen and (max-width:2200px) and (min-width:1080px) {\
          .ido{\
            max-width: 100% !important;\
          }\
          .gdtl {\
            width: auto !important;\
            max-width: 239px !important;\
            min-width: 214px !important;\
          }\
          .gld {\
            display: grid;\
            grid-template-columns:repeat(5,1fr)\
          }\
        }\
        @supports(display: grid) {\
          @media screen and (min-width:2171px) and (max-width:2611px){\
            .gld {\
              grid-template-columns:repeat(8,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(10,1fr) !important;\
            }\
          }\
          @media screen and (min-width:1951px) and (max-width:2171px) {\
            .gld {\
              grid-template-columns:repeat(7,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(9,1fr) !important;\
            }\
          }\
          @media screen and (min-width:1740px) and (max-width:1951px) {\
            .gld {\
              grid-template-columns:repeat(6,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(8,1fr) !important;\
            }\
          }\
          @media screen and (min-width:1531px) and (max-width:1740px) {\
            .gld {\
              grid-template-columns:repeat(5,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(7,1fr) !important;\
            }\
          }\
          @media screen and (min-width:1360px) and (max-width:1531px) {\
            .gld {\
              grid-template-columns:repeat(5,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(5,1fr) !important;\
            }\
          }\
          @media screen and (min-width:1080px) and (max-width:1360px) {\
            .gld {\
              grid-template-columns:repeat(4,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(5,1fr) !important;\
            }\
          }\
          @media screen and (min-width:0px) and (max-width:1080px) {\
            .gld {\
              grid-template-columns:repeat(4,1fr) !important;\
            }\
            #gdt {\
              grid-template-columns:repeat(4,1fr) !important;\
            }\
          }\
        }\
      </style>'
    style = $(style);
    $("body").append(style);
  }

  /**
   * 读取下一页
   */
  function pageLoadMore() {
    if (cfg.load_page_url.length > 0) {
      let url_list = cfg.load_page_url[0]
      for (let url of url_list) {
        getDataList(url.webApi())
      }
      cfg.load_page_url.shift()
    }
  }

  /**
   * 列表是否倒序显示
   */
  function pageViewSwitch() {
    let clear = ''
    // 结果页倒序
    if ($('.gl1t').length) {
      let lists = $('.gl1t').toArray().reverse()
      $('.itg.gld').empty()
      for (let i in lists) {
        $('.itg.gld').append(lists[i])
      }
      $('.itg.gld').append(clear)
    }
    // 详情页倒序
    if ($('.gdtl').length) {
      let lists = $('.gdtl').toArray().reverse()
      $('#gdt').empty()
      for (let i in lists) {
        $('#gdt').append(lists[i])
      }
      $('.itg.gld').append(clear)
    }
  }

  /**
   * 从网页内容解析出数据列表
   * @param string content 文本内容
   */
  function getDataList(content) {
    let target_in_detail = content.match(/<div id="gdt">(.*)<div class="c"><\/div><\/div><div class="gtb">/)
    let target_in_gallery = content.match(/<div class="itg gld">(.*)<\/div><table class="ptb"/)

    if (target_in_detail) {
      let target = openInNewTab(target_in_detail[1])
      $('#gdt').append(target)
      setLoadPageCount()
    }
    if (target_in_gallery) {
      let target = openInNewTab(target_in_gallery[1])
      $('.itg.gld').append(target)
      setLoadPageCount()
    }
  }

  /**
   * 在新窗口打开结果/图片
   * @param string el 查询结果字符串
   */
  function openInNewTab(el) {
    if (el === null) {
      $('.gl1t a,.gdtl a').attr('target', '_blank')
      return true
    }

    el = el.replaceAll('<a', '<a target="_blank"')
    return el
  }

  /**
   * 回到顶部
   */
  function goToTop() {
    $('html , body').animate({scrollTop: 0},'fast');
  }

  /**
   * 设置当前读取的页面数
   */
  function setLoadPageCount() {
    cfg.load_page_count += 1
    $('.page-now').text(cfg.load_page_count)
  }

  /**
   * 设置一次性读取的后续页数
   * @param number num 新数值
   */
  function setLoadPagesInOnce(num) {
    cfg.load_pages_in_once = num
    $('#page-load').text(cfg.load_pages_in_once)
    set('load_pages_in_once', cfg.load_pages_in_once)
  }

  /**
   * 注入工具函数
   */
  function initTool() {
    String.prototype.bool = function() {
      return (/^true$/i).test(this)
    }
    // 数组分块
    Array.prototype.chunk = function (n) {
      let l = this.length
      if (l === 0) return []
      if (l > n) {
        let chunks = []
        for(let i=0; i<l; i=i+n){
          chunks.push(this.slice(i, i+n));
        }
        return chunks
      } else {
        return [this]
      }
    }
    // 网络请求函数
    String.prototype.webApi = function () {
      let res = null
      $.ajaxSettings.async = false
      $.get(this, function (response) {
        res = response
      })
      return res
    }
  }

  /**
   * 初始化本地数据库
   */
  function initDB() {
    if (db === null) {
      if (!window.localStorage) {
        console.error('本浏览器不支持 IndexedDB')
        return false
      }
      db = window.localStorage
      return true
    }
    return true
  }

  /**
   * 读取数据
   */
  function get(name = null) {
    let all = {}
    if (name) {
      all[name] = db[name]
    } else {
      for (const k in window.localStorage) {
        all[k] = window.localStorage[k]
      }
    }
    return all
  }

  /**
   * 添加数据
   * @param string name 配置名
   * @param string content 配置值
   */
  function set(name, content) {
    localStorage.setItem(name, content);
  }
}(jQuery)

// 执行初始化
exhentaiGetAllPage.init()