帕秋莉

Pixiv 搜寻/浏览 工具

当前为 2017-12-01 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name              Patchouli
// @name:ja           パチュリー
// @name:zh-CN        帕秋莉
// @name:zh-TW        帕秋莉
// @namespace         https://github.com/FlandreDaisuki
// @description       An image searching/browsing tool on Pixiv
// @description:ja    Pixiv 検索機能強化
// @description:zh-CN Pixiv 搜寻/浏览 工具
// @description:zh-TW Pixiv 搜尋/瀏覽 工具
// @include           *://www.pixiv.net/*
// @require           https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js
// @require           https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js
// @icon              http://i.imgur.com/VwoYc5w.png
// @noframes
// @author            FlandreDaisuki
// @license           The MIT License (MIT) Copyright (c) 2016-2017 FlandreDaisuki
// @compatible        firefox >=52
// @compatible        chrome >=55
// @version           3.0.4
// @grant             none
// ==/UserScript==

(function () {
'use strict';

function __$styleInject( css ) {
    if(!css) return ;

    if(typeof(window) == 'undefined') return ;
    let style = document.createElement('style');

    style.innerHTML = css;
    document.head.appendChild(style);
    return css;
}

const _msg_following = "following";
const _msg_bookmark_tooltip = "$bookmark_count$ bookmarks";
const _msg_koakuma_processed = "$processed_count$ pics processed";
const _msg_koakuma_go = "Go";
const _msg_koakuma_pause = "Pause";
const _msg_koakuma_end = "End";
const _msg_fit_browser_width = "fit browser width";
const _msg_sort_by_bookmark_count = "sort by bookmark count";
const _msg_tag_filter_placeholder = "tag filter e.g.: flandre|sister";
var en = {
	_msg_following: _msg_following,
	_msg_bookmark_tooltip: _msg_bookmark_tooltip,
	_msg_koakuma_processed: _msg_koakuma_processed,
	_msg_koakuma_go: _msg_koakuma_go,
	_msg_koakuma_pause: _msg_koakuma_pause,
	_msg_koakuma_end: _msg_koakuma_end,
	_msg_fit_browser_width: _msg_fit_browser_width,
	_msg_sort_by_bookmark_count: _msg_sort_by_bookmark_count,
	_msg_tag_filter_placeholder: _msg_tag_filter_placeholder
};

const _msg_following$1 = "フォロー中";
const _msg_bookmark_tooltip$1 = "$bookmark_count$件のブックマーク";
const _msg_koakuma_processed$1 = "$processed_count$ 件が処理された";
const _msg_koakuma_go$1 = "捜す";
const _msg_koakuma_pause$1 = "中断";
const _msg_koakuma_end$1 = "終了";
const _msg_fit_browser_width$1 = "全幅";
const _msg_sort_by_bookmark_count$1 = "ブックマーク数順";
const _msg_tag_filter_placeholder$1 = "タグフィルター 例: フランドール|妹様";
var ja = {
	_msg_following: _msg_following$1,
	_msg_bookmark_tooltip: _msg_bookmark_tooltip$1,
	_msg_koakuma_processed: _msg_koakuma_processed$1,
	_msg_koakuma_go: _msg_koakuma_go$1,
	_msg_koakuma_pause: _msg_koakuma_pause$1,
	_msg_koakuma_end: _msg_koakuma_end$1,
	_msg_fit_browser_width: _msg_fit_browser_width$1,
	_msg_sort_by_bookmark_count: _msg_sort_by_bookmark_count$1,
	_msg_tag_filter_placeholder: _msg_tag_filter_placeholder$1
};

const _msg_following$2 = "关注中";
const _msg_bookmark_tooltip$2 = "$bookmark_count$个收藏";
const _msg_koakuma_processed$2 = "已处理 $processed_count$ 张";
const _msg_koakuma_go$2 = "找";
const _msg_koakuma_pause$2 = "停";
const _msg_koakuma_end$2 = "完";
const _msg_fit_browser_width$2 = "自适应浏览器宽度";
const _msg_sort_by_bookmark_count$2 = "书签数排序";
const _msg_tag_filter_placeholder$2 = "标签过滤 例: 芙兰朵露|二小姐";
var zh = {
	_msg_following: _msg_following$2,
	_msg_bookmark_tooltip: _msg_bookmark_tooltip$2,
	_msg_koakuma_processed: _msg_koakuma_processed$2,
	_msg_koakuma_go: _msg_koakuma_go$2,
	_msg_koakuma_pause: _msg_koakuma_pause$2,
	_msg_koakuma_end: _msg_koakuma_end$2,
	_msg_fit_browser_width: _msg_fit_browser_width$2,
	_msg_sort_by_bookmark_count: _msg_sort_by_bookmark_count$2,
	_msg_tag_filter_placeholder: _msg_tag_filter_placeholder$2
};

const _msg_following$3 = "關注中";
const _msg_bookmark_tooltip$3 = "$bookmark_count$個收藏";
const _msg_koakuma_processed$3 = "已處理 $processed_count$ 張";
const _msg_koakuma_go$3 = "找";
const _msg_koakuma_pause$3 = "停";
const _msg_koakuma_end$3 = "完";
const _msg_fit_browser_width$3 = "自適應瀏覽器寬度";
const _msg_sort_by_bookmark_count$3 = "書籤數排序";
const _msg_tag_filter_placeholder$3 = "標籤過濾 例: 芙蘭朵露|二小姐";
var tw = {
	_msg_following: _msg_following$3,
	_msg_bookmark_tooltip: _msg_bookmark_tooltip$3,
	_msg_koakuma_processed: _msg_koakuma_processed$3,
	_msg_koakuma_go: _msg_koakuma_go$3,
	_msg_koakuma_pause: _msg_koakuma_pause$3,
	_msg_koakuma_end: _msg_koakuma_end$3,
	_msg_fit_browser_width: _msg_fit_browser_width$3,
	_msg_sort_by_bookmark_count: _msg_sort_by_bookmark_count$3,
	_msg_tag_filter_placeholder: _msg_tag_filter_placeholder$3
};

class L10N {
  constructor () {
    this.dict = {en, ja, zh, tw};
    this.lang = document.documentElement.lang;
    if (this.lang === 'zh-tw') {
      this.lang = 'tw';
    }
    if (!this.dict[this.lang]) {
      this.lang = 'en';
    }
  }
  get following () {
    return this.dict[this.lang]['_msg_following']
  }
  bookmarkTooltip (n) {
    return this.dict[this.lang]['_msg_bookmark_tooltip'].replace('$bookmark_count$', n)
  }
  koakumaProcessed (n) {
    return this.dict[this.lang]['_msg_koakuma_processed'].replace('$processed_count$', n)
  }
  get koakumaGo () {
    return this.dict[this.lang]['_msg_koakuma_go']
  }
  get koakumaPause () {
    return this.dict[this.lang]['_msg_koakuma_pause']
  }
  get koakumaEnd () {
    return this.dict[this.lang]['_msg_koakuma_end']
  }
  get fitBrowserWidth () {
    return this.dict[this.lang]['_msg_fit_browser_width']
  }
  get sortByBookmarkCount () {
    return this.dict[this.lang]['_msg_sort_by_bookmark_count']
  }
  get tagFilterPlaceholder () {
    return this.dict[this.lang]['_msg_tag_filter_placeholder']
  }
}

function $ (selector) {
  return document.querySelector(selector)
}
function $$ (selector) {
  return [...document.querySelectorAll(selector)]
}
function $$find (doc, selector) {
  return [...doc.querySelectorAll(selector)]
}
function $el (tag, attr = {}, cb = () => {}) {
  const el = document.createElement(tag);
  Object.assign(el, attr);
  cb(el);
  return el
}
function $log (...args) {
  console.log.apply(console, args);
}
function $error (...args) {
  console.error.apply(console, args);
}
(() => {
  Math.clamp = (val, min, max) => Math.min(Math.max(min, val), max);
  Number.toInt = (s) => (isNaN(~~s) ? 0 : ~~s);
  (function (arr) {
    arr.forEach(function (item) {
      if (item.hasOwnProperty('after')) {
        return
      }
      Object.defineProperty(item, 'after', {
        configurable: true,
        enumerable: true,
        writable: true,
        value: function after () {
          const argArr = Array.prototype.slice.call(arguments);
          const docFrag = document.createDocumentFragment();
          argArr.forEach(function (argItem) {
            const isNode = argItem instanceof Node;
            docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem)));
          });
          this.parentNode.insertBefore(docFrag, this.nextSibling);
        }
      });
    });
  })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
})();

class Pixiv {
  constructor () {
    this.tt = $('input[name="tt"]').value;
  }
  async fetch (url) {
    try {
      if (url) {
        const res = await axios.get(url);
        if (res.statusText !== 'OK') {
          throw new Error(res.statusText)
        } else {
          return res.data
        }
      } else {
        $error('Pixiv#fetch has no url');
      }
    } catch (error) {
      $error(error);
    }
  }
  async getLegacyPageHTMLIllustIds (url, options = {}) {
    const opt = Object.assign({
      needBookmarkId: false
    }, options);
    try {
      const html = await this.fetch(url);
      const nextTag = html.match(/class="next"[^\/]*/);
      let nextUrl = '';
      if (nextTag) {
        const nextHref = nextTag[0].match(/href="([^"]+)"/);
        if (nextHref) {
          const query = nextHref[1].replace(/&/g, '&');
          if (query) {
            nextUrl = `${location.pathname}${query}`;
          }
        }
      }
      const iidHTMLs = html.match(/;illust_id=\d+"\s*class="work/g) || [];
      const illustIds = [];
      for (const dataid of iidHTMLs) {
        const iid = dataid.replace(/\D+(\d+).*/, '$1');
        if (!illustIds.includes(iid) && iid !== '0') {
          illustIds.push(iid);
        }
      }
      const ret = {
        next_url: nextUrl,
        illust_ids: illustIds
      };
      if (opt.needBookmarkId) {
        ret.bookmark_ids = {};
        const bimHTMLs = html.match(/name="book_id[^;]+;illust_id=\d+/g) || [];
        for (const bim of bimHTMLs) {
          const [illustId, bookmarkId] = bim.replace(/\D+(\d+)\D+(\d+)/, '$2 $1').split(' ');
          if (illustIds.includes(illustId)) {
            ret.bookmark_ids[illustId] = {illust_id: illustId, bookmark_id: bookmarkId};
          }
        }
      }
      return ret
    } catch (e) {
      $error(e);
    }
  }
  async getPageHTMLIllustIds (url) {
    try {
      const html = await this.fetch(url);
      const nextTag = html.match(/class="next"[^\/]*/);
      let nextUrl = '';
      if (nextTag) {
        const nextHref = nextTag[0].match(/href="([^"]+)"/);
        if (nextHref) {
          const query = nextHref[1].replace(/&/g, '&');
          if (query) {
            nextUrl = `${location.pathname}${query}`;
          }
        }
      }
      const iidHTMLs = html.match(/illustId":"(\d+)"/g) || [];
      const illustIds = [];
      for (const dataid of iidHTMLs) {
        const iid = dataid.replace(/\D+(\d+).*/, '$1');
        if (!illustIds.includes(iid) && iid !== '0') {
          illustIds.push(iid);
        }
      }
      const ret = {
        next_url: nextUrl,
        illust_ids: illustIds
      };
      return ret
    } catch (error) {
      $error(error);
    }
  }
  async getBookmarkHTMLDetail (illustId) {
    const url = `/bookmark_detail.php?illust_id=${illustId}`;
    try {
      const html = await this.fetch(url);
      const _a = html.match(/sprites-bookmark-badge[^\d]+(\d+)/);
      const bookmarkCount = _a ? parseInt(_a[1]) : 0;
      const _b = html.match(/<ul class="tags[^>]+>.*?(?=<\/ul>)/);
      const _c = _b ? _b[0].match(/>[^<]+?(?=<\/a>)/g) : [];
      const tags = _c ? _c.map(x => x.slice(1)) : [];
      return {
        bookmark_count: bookmarkCount,
        illust_id: illustId,
        tags
      }
    } catch (error) {
      $error(error);
    }
  }
  async getBookmarkHTMLDetails (illustIds) {
    const fn = this.getBookmarkHTMLDetail.bind(this);
    const bookmarkDetails = await Promise.all(illustIds.map(fn));
    const details = {};
    for (const detail of bookmarkDetails) {
      details[detail.illust_id] = detail;
    }
    return details
  }
  async getIllustsAPIDetail (illustIds) {
    const iids = illustIds.join(',');
    const url = `/rpc/index.php?mode=get_illust_detail_by_ids&illust_ids=${iids}&tt=${this.tt}`;
    try {
      const json = await this.fetch(url);
      if (json.error) {
        throw new Error(json.message)
      }
      const details = json.body;
      for (const [key, detail] of Object.entries(details)) {
        if (detail.error) {
          delete details[key];
        }
      }
      return details
    } catch (error) {
      $error(error);
    }
  }
  async getUsersAPIDetail (userIds) {
    const uids = userIds.join(',');
    const url = `/rpc/get_profile.php?user_ids=${uids}&tt=${this.tt}`;
    try {
      const json = await this.fetch(url);
      if (json.error) {
        throw new Error(json.message)
      }
      const details = {};
      for (const u of json.body) {
        details[u.user_id] = {
          user_id: u.user_id,
          is_follow: u.is_follow
        };
      }
      return details
    } catch (error) {
      $error(error);
    }
  }
  async getRecommendationsAPIDetails (illustIds = 'auto', numRecommendations = 500) {
    const searchParams = {
      type: 'illust',
      sample_illusts: illustIds,
      num_recommendations: numRecommendations,
      tt: this.tt
    };
    const url = `/rpc/recommender.php?${searchParams.entries.map(p => p.join('=')).join('&')}`;
    try {
      const data = await this.fetch(url);
      return data.recommendations.map(x => `${x}`)
    } catch (error) {
      $error(error);
    }
  }
  async postBookmarkAdd (illustId) {
    const searchParams = {
      mode: 'save_illust_bookmark',
      illust_id: illustId,
      restrict: 0,
      comment: '',
      tags: '',
      tt: this.tt
    };
    const data = searchParams.entries.map(p => p.join('=')).join('&');
    const config = {
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    };
    try {
      const res = await axios.post('/rpc/index.php', data, config);
      if (res.statusText === 'OK') {
        return !res.data.error
      } else {
        throw new Error(res.statusText)
      }
    } catch (error) {
      $error(error);
    }
  }
  static removeAnnoyings (doc = document) {
    const annoyings = [
      'iframe',
      '.ad',
      '.ads_area',
      '.ad-footer',
      '.ads_anchor',
      '.ads-top-info',
      '.comic-hot-works',
      '.user-ad-container',
      '.ads_area_no_margin',
      '.hover-item',
      '.ad-printservice',
      '.bookmark-ranges',
      '.require-premium',
      '.showcase-reminder',
      '.sample-user-search',
      '.popular-introduction',
      '._premium-lead-tag-search-bar',
      '._premium-lead-popular-d-body'
    ];
    for (const selector of annoyings) {
      for (const el of $$find(doc, selector)) {
        el.remove();
      }
    }
  }
}

const PageType = {
  SEARCH: Symbol('SEARCH'),
  NEW_ILLUST: Symbol('NEW_ILLUST'),
  NO_SUPPORT: Symbol('NO_SUPPORT'),
  MY_BOOKMARK: Symbol('MY_BOOKMARK'),
  MEMBER_ILLIST: Symbol('MEMBER_ILLIST')
};

class Global {
  constructor () {
    this.l10n = new L10N();
    this.api = new Pixiv();
    this.library = [];
    this.filters = {
      limit: 0,
      orderBy: 'illust_id',
      tag: new RegExp('', 'i')
    };
    this.conf = {
      fitwidth: 1,
      sort: 0
    };
    const storeNamespace = this.constructor.NAME;
    this.store = {
      get: (key = null) => {
        const obj = JSON.parse(localStorage.getItem(storeNamespace) || '{}');
        if (key) {
          return obj[key]
        }
        return obj
      },
      set: (obj) => {
        const storable = JSON.stringify(obj);
        localStorage.setItem(storeNamespace, storable);
      }
    };
    this.classifyPagetype();
  }
  applyConf () {
    if (this.pagetype !== PageType.NO_SUPPORT) {
      if (this.conf.fitwidth) {
        $('.ω').classList.add('↔');
      } else {
        $('.ω').classList.remove('↔');
      }
      if (this.conf.sort) {
        this.filters.orderBy = 'bookmark_count';
      } else {
        this.filters.orderBy = 'illust_id';
      }
      if (this.pagetype === PageType.MY_BOOKMARK) {
        for (const marker of $$('.js-legacy-mark-all, .js-legacy-unmark-all')) {
          marker.addEventListener('click', () => {
            $$('input[name="book_id[]"]').forEach(el => {
              el.checked = marker.classList.contains('js-legacy-mark-all');
            });
          });
        }
      }
    }
  }
  classifyPagetype () {
    const path = location.pathname;
    const searchParam = new URLSearchParams(location.search);
    const spId = searchParam.get('id');
    const spType = searchParam.get('type');
    switch (path) {
      case '/search.php':
        this.pagetype = PageType.SEARCH;
        break
      case '/bookmark_new_illust.php':
      case '/new_illust.php':
      case '/mypixiv_new_illust.php':
      case '/new_illust_r18.php':
      case '/bookmark_new_illust_r18.php':
        this.pagetype = PageType.NEW_ILLUST;
        break
      case '/member_illust.php':
        this.pagetype = spId ? PageType.MEMBER_ILLIST : PageType.NO_SUPPORT;
        break
      case '/bookmark.php': {
        if (spId) {
          this.pagetype = PageType.NEW_ILLUST;
        } else if (!spType || spType === 'illust_all') {
          this.pagetype = PageType.MY_BOOKMARK;
        } else {
          this.pagetype = PageType.NO_SUPPORT;
        }
        break
      }
      default:
        this.pagetype = PageType.NO_SUPPORT;
        break
    }
    if (this.pagetype !== PageType.NO_SUPPORT) {
      $('#wrapper').classList.add('ω');
      this.koakumaMountPoint = $el('div', {className: 'koakumaMountPoint'}, (el) => {
        $('header._global-header').after(el);
      });
      if (this.pagetype === PageType.SEARCH) {
        this.patchouliMountPoint = $('#js-react-search-mid');
      } else {
        const _a = $('li.image-item');
        const _b = $('ul._image-items');
        this.patchouliMountPoint = _a ? _a.parentElement : _b;
      }
    }
  }
  static get VERSION () {
    return GM_info.script.version
  }
  static get NAME () {
    return GM_info.script.name
  }
}

class Crawler {
  constructor (global) {
    this.library = global.library;
    this.api = global.api;
    this.pagetype = global.pagetype;
    this.next_url = location.href;
    this.isPaused = true;
    this.isEnded = false;
  }
  async startNextUrlBased (opt) {
    this.isPaused = false;
    while (this.canContinue() && opt.times) {
      let page = null;
      if (this.pagetype === PageType.SEARCH) {
        page = await this.api.getPageHTMLIllustIds(this.next_url);
      } else {
        page = await this.api.getLegacyPageHTMLIllustIds(this.next_url, {
          needBookmarkId: this.pagetype === PageType.MY_BOOKMARK
        });
      }
      this.next_url = page.next_url;
      const illustAPIDetails = await this.api.getIllustsAPIDetail(page.illust_ids);
      if (this.pagetype === PageType.MY_BOOKMARK) {
        const myBookmarkAPIDetails = page.bookmark_ids;
        for (const [illustId, illustDetail] of Object.entries(illustAPIDetails)) {
          const bookmarkId = page.bookmark_ids[illustId].bookmark_id;
          if (bookmarkId) {
            illustDetail.bookmark_id = bookmarkId;
          }
        }
      }
      const bookmarkHTMLDetails = await this.api.getBookmarkHTMLDetails(Object.keys(illustAPIDetails));
      const userIds = Object.values(illustAPIDetails).map(d => d.user_id);
      const userAPIDetails = await this.api.getUsersAPIDetail(userIds);
      const libraryData = this.makeLibraryData({illustAPIDetails, bookmarkHTMLDetails, userAPIDetails});
      this.library.push(...libraryData);
      opt.times -= 1;
      if (!opt.times) {
        this.pause();
      }
      if (!this.next_url) {
        this.stop();
      }
    }
  }
  async start (options) {
    const opt = Object.assign({times: Infinity}, options);
    if (this.isEnded || opt.times <= 0) {
      return
    }
    switch (this.pagetype) {
      case PageType.SEARCH:
      case PageType.NEW_ILLUST:
      case PageType.MY_BOOKMARK:
      case PageType.MEMBER_ILLIST:
        await this.startNextUrlBased(opt);
        break
      default:
        break
    }
  }
  pause () {
    this.isPaused = true;
  }
  stop () {
    this.pause();
    this.isEnded = true;
  }
  canContinue () {
    return !(this.isEnded || this.isPaused)
  }
  makeLibraryData ({illustAPIDetails, bookmarkHTMLDetails, userAPIDetails}) {
    if (!illustAPIDetails || !Object.keys(illustAPIDetails).length) {
      throw new Error('Crawler#makeLibraryData: illustAPIDetails is falsy.')
    }
    const vLibrary = [];
    for (const [illustId, illustDetail] of Object.entries(illustAPIDetails)) {
      const d = {
        illust_id: illustId,
        bookmark_count: bookmarkHTMLDetails[illustId].bookmark_count,
        tags: bookmarkHTMLDetails[illustId].tags.join(', '),
        illust_title: illustDetail.illust_title,
        illust_page_count: Number.toInt(illustDetail.illust_page_count),
        user_id: illustDetail.user_id,
        user_name: illustDetail.user_name,
        is_follow: userAPIDetails[illustDetail.user_id].is_follow,
        is_bookmarked: illustDetail.is_bookmarked,
        is_ugoira: !!illustDetail.ugoira_meta,
        profile_img: illustDetail.profile_img,
        url: {
          big: illustDetail.url.big,
          sq240: illustDetail.url['240mw'].replace('240x480', '240x240')
        }
      };
      if (this.pagetype === PageType.MY_BOOKMARK) {
        d.bookmark_id = illustDetail.bookmark_id;
      }
      vLibrary.push(d);
    }
    return vLibrary
  }
}

__$styleInject(".ω.↔,\n.ω.↔ .layout-a,\n.ω.↔ .layout-body {\n    width: initial !important;\n}\n.ω.↔ .layout-a {\n    display: flex;\n    flex-direction: row-reverse;\n}\n.ω.↔ .layout-column-2{\n    flex: 1;\n    margin-left: 20px;\n}\n.ω.↔ .layout-body,\n.ω.↔ .layout-a {\n    margin: 10px 20px;\n}\n");

var DefaultImageItemImage = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"image-item-image"},[_c('a',{attrs:{"href":_vm.illustPageUrl,"rel":"noopener"}},[(_vm.illustPageCount > 1)?_c('div',{staticClass:"multiple"},[_c('span'),_vm._v(" "+_vm._s(_vm.illustPageCount)+" ")]):_vm._e(),_vm._v(" "),_c('img',{attrs:{"data-src":_vm.imgUrl,"src":_vm.imgUrl}}),_vm._v(" "),(_vm.isUgoira)?_c('div',{staticClass:"ugoira"}):_vm._e()]),_vm._v(" "),_c('div',{staticClass:"bookmark _one-click-bookmark",class:{on:_vm.selfIsBookmarked},attrs:{"data-click-action":"illust","data-click-label":_vm.illustId,"data-type":"illust","data-id":_vm.illustId,"title":_vm.selfIsBookmarked},on:{"click":_vm.oneClickBookmarkAdd}}),_vm._v(" "),(_vm.bookmarkId)?_c('div',{staticClass:"bookmark-input-container"},[_c('input',{attrs:{"name":"book_id[]","type":"checkbox"},domProps:{"value":_vm.bookmarkId}})]):_vm._e()])},staticRenderFns: [],_scopeId: 'data-v-23ff0f22',
  name: "DefaultImageItemImage",
  props: {
    imgUrl: String,
    illustId: String,
    illustPageCount: Number,
    isUgoira: Boolean,
    isBookmarked: Boolean,
    bookmarkId: String
  },
  data() {
    return {
      selfIsBookmarked: this.isBookmarked
    };
  },
  computed: {
    illustPageUrl() {
      return `/member_illust.php?mode=medium&illust_id=${this.illustId}`;
    }
  },
  methods: {
    oneClickBookmarkAdd() {
      if (!selfIsBookmarked) {
        selfIsBookmarked = true;
      }
    }
  }
};
var DefaultImageItemTitle = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('figcaption',{staticClass:"image-item-title"},[_c('ul',[_c('li',{staticClass:"title-text"},[_c('a',{attrs:{"href":_vm.illustPageUrl,"title":_vm.illustTitle}},[_vm._v(_vm._s(_vm.illustTitle))])]),_vm._v(" "),(!_vm.isMemberIllistPage)?_c('li',[_c('a',{staticClass:"user-link ui-profile-popup",attrs:{"href":_vm.userPageUrl,"target":"_blank","title":_vm.userName,"data-user_id":_vm.userId,"data-user_name":_vm.userName}},[_c('span',{staticClass:"user-img",style:(_vm.profileImgStyle)}),_vm._v(" "),_c('span',[_vm._v(_vm._s(_vm.userName))])])]):_vm._e(),_vm._v(" "),(_vm.bookmarkCount > 0)?_c('li',[_c('ul',{staticClass:"count-list"},[_c('li',[_c('a',{staticClass:"_ui-tooltip bookmark-count",attrs:{"href":_vm.bookmarkDetailUrl,"data-tooltip":_vm.bookmarkTooltipMsg}},[_c('i',{staticClass:"_icon sprites-bookmark-badge"}),_vm._v(_vm._s(_vm.bookmarkCount))])])])]):_vm._e()])])},staticRenderFns: [],_scopeId: 'data-v-b9e9aa28',
  name: "DefaultImageItemTitle",
  props: {
    illustId: String,
    illustTitle: String,
    userName: String,
    userId: String,
    profileImgUrl: String,
    bookmarkCount: Number,
    bookmarkTooltipMsgFunc: Function,
    pagetype: Symbol
  },
  computed: {
    illustPageUrl() {
      return `/member_illust.php?mode=medium&illust_id=${this.illustId}`;
    },
    userPageUrl() {
      return `/member_illust.php?id=${this.userId}`;
    },
    bookmarkDetailUrl() {
      return `/bookmark_detail.php?illust_id=${this.illustId}`;
    },
    bookmarkTooltipMsg() {
      return this.bookmarkTooltipMsgFunc(this.bookmarkCount);
    },
    profileImgStyle() {
      return {
        backgroundImage: `url(${this.profileImgUrl})`
      };
    },
    isMemberIllistPage() {
      return this.pagetype.toString() === "Symbol(MEMBER_ILLIST)";
    }
  }
};
var DefaultImageItem = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"image-item"},[_c('figure',{staticClass:"image-item-inner"},[_c('DefaultImageItemImage',{attrs:{"imgUrl":_vm.imgUrl,"illustId":_vm.illustId,"illustPageCount":_vm.illustPageCount,"isUgoira":_vm.isUgoira,"isBookmarked":_vm.isBookmarked,"bookmarkId":_vm.bookmarkId}}),_vm._v(" "),_c('DefaultImageItemTitle',{attrs:{"illustId":_vm.illustId,"illustTitle":_vm.illustTitle,"userName":_vm.userName,"userId":_vm.userId,"profileImgUrl":_vm.profileImgUrl,"bookmarkCount":_vm.bookmarkCount,"bookmarkTooltipMsgFunc":_vm.bookmarkTooltipMsgFunc,"pagetype":_vm.pagetype}})],1)])},staticRenderFns: [],_scopeId: 'data-v-7313ace1',
  name: "DefaultImageItem",
  components: {
    DefaultImageItemImage,
    DefaultImageItemTitle
  },
  props: {
    imgUrl: String,
    illustId: String,
    illustTitle: String,
    illustPageCount: Number,
    isUgoira: Boolean,
    isBookmarked: Boolean,
    userName: String,
    userId: String,
    profileImgUrl: String,
    bookmarkCount: Number,
    bookmarkTooltipMsgFunc: Function,
    bookmarkId: { type: String, default: "" },
    pagetype: Symbol
  }
};
var _default = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{attrs:{"id":"patchouli"}},_vm._l((_vm.filteredLibrary),function(d){return _c('DefaultImageItem',{key:d.illust_id,attrs:{"imgUrl":d.url.sq240,"illustId":d.illust_id,"illustTitle":d.illust_title,"illustPageCount":d.illust_page_count,"isUgoira":d.is_ugoira,"userName":d.user_name,"userId":d.user_id,"profileImgUrl":d.profile_img,"bookmarkCount":d.bookmark_count,"bookmarkTooltipMsgFunc":_vm.bookmarkTooltipMsgFunc,"isBookmarked":d.is_bookmarked,"bookmarkId":d.bookmark_id,"pagetype":_vm.pagetype}})}))},staticRenderFns: [],_scopeId: 'data-v-186857e1',
  name: "Default",
  components: {
    DefaultImageItem
  },
  props: ["library", "l10n", "pagetype", "filters"],
  computed: {
    bookmarkTooltipMsgFunc() {
      return this.l10n.bookmarkTooltip.bind(this.l10n);
    },
    filteredLibrary() {
      const cloneLibrary = this.library.slice();
      return cloneLibrary
        .filter(el => el.bookmark_count >= this.filters.limit)
        .filter(el => el.tags.match(this.filters.tag))
        .sort(
          (a, b) =>
            Number.toInt(b[this.filters.orderBy]) -
            Number.toInt(a[this.filters.orderBy])
        );
    }
  }
};
var koakuma = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:_vm.statusClass,attrs:{"id":"koakuma"}},[_c('div',{staticClass:"processed"},[_vm._v(_vm._s(_vm.processedMsg))]),_vm._v(" "),_c('div',[_c('label',{staticClass:"bookmark-count",attrs:{"for":"koakuma-bookmark-sort-input"}},[_c('i',{staticClass:"_icon sprites-bookmark-badge"}),_vm._v(" "),_c('input',{attrs:{"id":"koakuma-bookmark-sort-input","type":"number","min":"0","step":"1"},domProps:{"value":_vm.filters.limit},on:{"wheel":function($event){$event.stopPropagation();$event.preventDefault();_vm.sortInputWheel($event);},"input":_vm.sortInputInput}}),_vm._v("↑ ")])]),_vm._v(" "),_c('div',[_c('input',{staticClass:"tag-filter",attrs:{"type":"text","placeholder":_vm.l10n.tagFilterPlaceholder},on:{"input":_vm.tagFilterInput}})]),_vm._v(" "),_c('div',[_c('button',{staticClass:"explosion",attrs:{"disabled":_vm.crawler.isEnded},on:{"click":_vm.clickExplosion}},[_vm._v(_vm._s(_vm.buttonMsg))])]),_vm._v(" "),_c('div',[_c('input',{attrs:{"type":"checkbox","id":"koakuma-options-fit-browser-width"},domProps:{"checked":_vm.conf.fitwidth},on:{"change":_vm.optionsChange}}),_vm._v(" "),_c('label',{attrs:{"for":"koakuma-options-fit-browser-width"}},[_vm._v(_vm._s(_vm.l10n.fitBrowserWidth))]),_vm._v(" "),_c('input',{attrs:{"type":"checkbox","id":"koakuma-options-sort-by-bookmark-count"},domProps:{"checked":_vm.conf.sort},on:{"change":_vm.optionsChange}}),_vm._v(" "),_c('label',{attrs:{"for":"koakuma-options-sort-by-bookmark-count"}},[_vm._v(_vm._s(_vm.l10n.sortByBookmarkCount))])])])},staticRenderFns: [],_scopeId: 'data-v-40b353ca',
  name: "Koakuma",
  props: ["crawler", "l10n", "filters", "store", "conf", "applyConf"],
  computed: {
    processedMsg() {
      return this.l10n.koakumaProcessed.call(
        this.l10n,
        this.crawler.library.length
      );
    },
    statusClass() {
      return {
        end: this.crawler.isEnded,
        paused: !this.crawler.isPaused && !this.crawler.isEnded,
        go: this.crawler.isPaused && !this.crawler.isEnded
      };
    },
    buttonMsg() {
      if (this.crawler.isEnded) {
        return this.l10n.koakumaEnd;
      } else if (this.crawler.isPaused) {
        return this.l10n.koakumaGo;
      } else {
        return this.l10n.koakumaPause;
      }
    }
  },
  methods: {
    clickExplosion() {
      if (this.crawler.isPaused) {
        this.crawler.start();
      } else {
        this.crawler.pause();
      }
    },
    sortInputWheel(event) {
      if (event.deltaY < 0) {
        this.filters.limit = Number.toInt(event.target.value) + 20;
      } else {
        this.filters.limit = Math.max(0, Number.toInt(event.target.value) - 20);
      }
    },
    sortInputInput(event) {
      if (this.debounceId0) {
        clearTimeout(this.debounceId0);
      }
      this.debounceId0 = setTimeout(() => {
        this.debounceId0 = null;
        this.filters.limit = Math.max(0, Number.toInt(event.target.value));
      }, 500);
    },
    optionsChange(event) {
      if (event.target.id === "koakuma-options-fit-browser-width") {
        this.conf.fitwidth = event.target.checked;
      } else {
        this.conf.sort = Number.toInt(event.target.checked);
      }
      this.store.set(this.conf);
      this.applyConf();
    },
    tagFilterInput(event) {
      if (this.debounceId1) {
        clearTimeout(this.debounceId1);
      }
      this.debounceId1 = setTimeout(() => {
        this.debounceId1 = null;
        this.filters.tag = new RegExp(event.target.value, "ig");
      }, 1500);
    }
  },
  data() {
    return {
      debounceId0: null,
      debounceId1: null
    };
  }
};

__$styleInject("#patchouli[data-v-186857e1] {\n  display: flex;\n  flex-flow: wrap;\n  justify-content: space-around;\n}\n.image-item[data-v-7313ace1] {\n  display: flex;\n  justify-content: center;\n  margin: 0 0 30px 0;\n  padding: 10px;\n  height: auto;\n  width: 200px;\n}\n.image-item-inner[data-v-7313ace1] {\n  display: flex;\n  flex-flow: column;\n  max-width: 100%;\n}\n.image-item-image[data-v-23ff0f22] {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  position: relative;\n}\n.image-item-image > a[data-v-23ff0f22] {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  max-width: 200px;\n  max-height: 200px;\n  border: 1px solid rgba(0, 0, 0, 0.04);\n}\n.image-item-image > a > img[data-v-23ff0f22] {\n  max-height: 200px;\n  max-width: 200px;\n  object-fit: cover;\n}\n.multiple[data-v-23ff0f22] {\n  position: absolute;\n  right: 0;\n  top: 0;\n  background: rgba(0, 0, 0, 0.4);\n  padding: 6px;\n  color: #fff;\n  border-radius: 0 0 0 4px;\n  font-weight: 700;\n}\n.multiple > span[data-v-23ff0f22] {\n  background: url(https://source.pixiv.net/www/js/bundle/0d96c2a49f75a8fa27d0424549169573.svg);\n  width: 10px;\n  height: 10px;\n  display: inline-block;\n}\n.ugoira[data-v-23ff0f22] {\n  background: url(https://source.pixiv.net/www/js/bundle/70ae15bac4e2e134bbf9d5727859f1fc.svg);\n  position: absolute;\n  width: 40px;\n  height: 40px;\n}\n.bookmark[data-v-23ff0f22] {\n  right: 0;\n}\n.bookmark-input-container[data-v-23ff0f22] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  background: rgba(0, 0, 0, 0.4);\n  padding: 6px;\n  border-radius: 0 0 4px 0;\n}\n.image-item-title[data-v-b9e9aa28] {\n  max-width: 100%;\n}\n.title-text[data-v-b9e9aa28] {\n  font-weight: 700;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n.user-link[data-v-b9e9aa28] {\n  font-size: 12px;\n  display: inline-flex;\n  align-items: center;\n}\n.user-img[data-v-b9e9aa28] {\n  width: 20px;\n  height: 20px;\n  display: inline-block;\n  background-size: cover;\n  border-radius: 50%;\n  margin-right: 4px;\n}\n#koakuma[data-v-40b353ca] {\n  display: flex;\n  justify-content: center;\n  position: sticky;\n  top: 0;\n  z-index: 3;\n  background-color: #e77;\n  box-shadow: 0 1px 3px #000000;\n  padding: 4px;\n  color: #fff;\n  font-size: 16px;\n}\n#koakuma > div[data-v-40b353ca] {\n  margin: 0 10px;\n}\n.bookmark-count[data-v-40b353ca] {\n  display: inline-flex !important;\n  align-items: center;\n}\n#koakuma-bookmark-sort-input[data-v-40b353ca] {\n  -moz-appearance: textfield;\n  border: none;\n  background-color: transparent;\n  padding: 0px;\n  color: inherit;\n  font-size: 16px;\n  display: inline-block;\n  cursor: ns-resize;\n  text-align: center;\n  max-width: 50px;\n}\n.tag-filter[data-v-40b353ca] {\n  min-width: 300px;\n}\n.explosion[data-v-40b353ca] {\n  border: none;\n  padding: 2px 14px;\n  border-radius: 3px;\n  font-size: 16px;\n}\n.explosion[data-v-40b353ca]:enabled:hover {\n  box-shadow: 1px 1px;\n}\n.explosion[data-v-40b353ca]:enabled:active {\n  box-shadow: 1px 1px inset;\n}\n.go .explosion[data-v-40b353ca] {\n  background-color: #64ffda;\n}\n.paused .explosion[data-v-40b353ca] {\n  background-color: #ffd600;\n}\n.end .explosion[data-v-40b353ca] {\n  background-color: #455a64;\n  color: #fff;\n  opacity: 0.9;\n}");

const global = new Global();
$log(`[${Global.NAME}] version: ${Global.VERSION}`);
const storeVersion = global.store.get('version');
if (!storeVersion || Global.VERSION > storeVersion) {
  global.store.set(Object.assign({
    version: Global.VERSION
  }, global.conf));
} else {
  Object.assign(global.conf, global.store.get());
}
global.applyConf();
Pixiv.removeAnnoyings();
if (global.pagetype !== PageType.NO_SUPPORT) {
  const crawler = new Crawler(global);
  const patchouli = new Vue({
    components: {Default: _default},
    data: {
      l10n: global.l10n,
      library: global.library,
      pagetype: global.pagetype,
      filters: global.filters
    },
    template: '<Default :l10n="l10n" :library="library" :pagetype="pagetype" :filters="filters" />'
  });
  const koakuma$$1 = new Vue({
    components: {Koakuma: koakuma},
    data: {
      l10n: global.l10n,
      filters: global.filters,
      store: global.store,
      conf: global.conf,
      applyConf: global.applyConf.bind(global),
      crawler
    },
    template: '<Koakuma :l10n="l10n" :crawler="crawler" :filters="filters" :store="store" :conf="conf" :applyConf="applyConf"/>'
  });
  crawler.start({times: 1}).then(() => {
    patchouli.$mount(global.patchouliMountPoint);
    koakuma$$1.$mount(global.koakumaMountPoint);
  }).catch(error => {
    $error(error);
  });
}

}());