- // ==UserScript==
- // @name la-image-extractor
- // @name:zh-CN la 图片地址复制
- // @description copy image source in hitomi.la notomi.la e-hentai.org to clipboard
- // @description:zh-CN 复制 hitoma.la notomi.la e-hentai 图片链接到剪贴板
- // @version 0.2.5
- // @author jferroal
- // @license GPL-3.0
- // @require https://greasyfork.org/scripts/31793-jmul/code/JMUL.js?version=209567
- // @include https://hitomi.la/reader/*
- // @include https://nozomi.la/tag/*
- // @include https://e-hentai.org/s/*
- // @grant GM_xmlhttpRequest
- // @run-at document-idle
- // @namespace https://greasyfork.org/users/34556-jferroal
- // ==/UserScript==
-
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
- class Button {
- constructor(label, eventHandlers = []) {
- this.element = document.createElement('div');
- this.addCss(Button.DefaultCss);
- this.element.innerText = label;
- this.listeners = {};
- this.listen(eventHandlers);
- this.parent = null;
- }
-
- onClick(handler) {
- this.listen({'click': handler});
- }
-
- listen(handlers) {
- for (const event in handlers) {
- if (handlers.hasOwnProperty(event)) {
- this.element.addEventListener(event, handlers[event]);
- }
- }
- }
-
- addCss(css) {
- for (const styleName in css) {
- if (css.hasOwnProperty(styleName)) {
- this.element.style[styleName] = css[styleName];
- }
- }
- }
-
- appendTo(element) {
- this.parent = element;
- element.appendChild(this.element);
- }
-
- removeFrom() {
- this.parent.removeChild(this.element);
- }
-
- removeListener() {
- for (const event in this.listeners) {
- if (this.listeners.hasOwnProperty(event)) {
- this.element.removeEventListener(event, this.listeners[event]);
- }
- }
- }
- }
-
- Button.DefaultCss = {
- textAlign: 'center',
- width: '120px',
- lineHeight: '40px',
- backgroundColor: 'skyblue',
- color: 'white',
- cursor: 'pointer',
- borderRadius: '8px',
- boxShadow: '0px 0px 8px 4px rgba(0, 0, 0, .2)',
- position: 'fixed',
- right: '80px',
- bottom: '80px'
- };
-
- module.exports = Button;
-
- },{}],2:[function(require,module,exports){
- const {createFullScreenElement, href, innerText, isEhentai} = require('./utils');
-
- let _EhentaiState = {};
-
- function constructImage(src) {
- const img = document.createElement('img');
- img.style.width = '100vw';
- img.style.maxWidth = '100vw';
- img.setAttribute('src', src);
- return img;
- }
-
- function loadMore() {
- _EhentaiState.ImageContainer.removeChild(_EhentaiState.LoadMoreBtn);
- const targets = _EhentaiState.ImageSources
- .slice(_EhentaiState.ImageAppendedCount, _EhentaiState.ImageAppendedCount + _EhentaiState.ImagePerPage);
- let i = 0;
- for (const src of targets) {
- let timer = setTimeout(() => {
- const img = constructImage(src);
- document.querySelector(_EhentaiState.ImageContainerSelector).appendChild(img);
- clearTimeout(timer);
- timer = null;
- }, i * _EhentaiState.ImageElementCreationDefer);
- _EhentaiState.ImageAppendedCount += 1;
- i += 1;
- }
- if (_EhentaiState.ImageAppendedCount < _EhentaiState.ImageSources.length) {
- _EhentaiState.ImageContainer.appendChild(_EhentaiState.LoadMoreBtn);
- }
- }
-
-
-
-
- module.exports = {
- initEhentai() {
- if (!isEhentai()) return;
- const [
- MainContainerSelector,
- TopPaginationSelector,
- ImageContainerSelector,
- BottomPaginationSelector,
- ImagesSelector,
- TitleSelector
- ] = ['#i1', '#i2', '#i3', '#i4', '#i3 img', 'title'];
- const NextPagePattern = /<div id="i3"><a onclick="return load_image\((\d+), '([\w\d]+)'\)"/gi;
- const ImageSourcePattern = /<img id="img" src="(.*)" style=".*?" onerror=".*?" \/>/gi;
- const ImageElementCreationDefer = 200;
- const ImagePerPage = 20;
- const PostId = href().split('/')[5].split('-')[0];
- _EhentaiState.ImageContainer = document.querySelector(ImageContainerSelector);
- _EhentaiState.LoadMoreBtn = document.createElement('div');
- _EhentaiState.LoadMoreBtn.style.width = '100%';
- _EhentaiState.LoadMoreBtn.style.lineHeight = '48px';
- _EhentaiState.LoadMoreBtn.style.margin = '24px 60px';
- _EhentaiState.LoadMoreBtn.style.cursor = 'pointer';
- _EhentaiState.LoadMoreBtn.style.backgroundColor = 'lightskyblue';
- _EhentaiState.LoadMoreBtn.style.borderRadius = '8px';
- _EhentaiState.LoadMoreBtn.innerText = 'LOAD MORE';
- _EhentaiState.LoadMoreBtn.addEventListener('click', loadMore);
- _EhentaiState.FetchAllRunning = false;
- _EhentaiState.ImageAppendedCount = 1;
- _EhentaiState.ImageSources = ['first_image_placeholder'];
-
- _EhentaiState = Object.assign(_EhentaiState, {
- MainContainerSelector,
- TopPaginationSelector,
- ImageContainerSelector,
- BottomPaginationSelector,
- ImagesSelector,
- TitleSelector,
- NextPagePattern,
- ImageSourcePattern,
- ImageElementCreationDefer,
- ImagePerPage,
- PostId,
- });
- },
- fetchEhentaiAll() {
- if (_EhentaiState.FetchAllRunning) return;
- _EhentaiState.FetchAllRunning = true;
-
- function getNextImage(page, hash) {
- const url = `https://e-hentai.org/s/${hash}/${_EhentaiState.PostId}-${page}`;
- const xmlhttp = new XMLHttpRequest();
- xmlhttp.open('GET', url);
- xmlhttp.onreadystatechange = function () {
- if (this.readyState !== 4) return;
- if (this.status === 200) {
- const [, p, h] = _EhentaiState.NextPagePattern.exec(this.responseText);
- _EhentaiState.NextPagePattern.lastIndex = -1;
- const hasNext = parseInt(p, 10) !== _EhentaiState.ImageSources.length;
- if (!hasNext) {
- const loadedElem = createFullScreenElement('ALL IMAGE SOURCES LOADED');
- document.body.appendChild(loadedElem);
- let timer = setTimeout(() => {
- document.body.removeChild(loadedElem);
- clearTimeout(timer);
- timer = null;
- }, 3000);
- _EhentaiState.FetchAllRunning = false;
- return;
- }
- const [, imageSource] = _EhentaiState.ImageSourcePattern.exec(this.responseText);
- _EhentaiState.ImageSourcePattern.lastIndex = -1;
- _EhentaiState.ImageSources.push(imageSource);
- if (_EhentaiState.ImageAppendedCount < _EhentaiState.ImagePerPage) {
- // load IMAGE PER PAGE COUNT image at first
- const img = constructImage(imageSource);
- _EhentaiState.ImageContainer.appendChild(img);
- _EhentaiState.ImageAppendedCount += 1;
- } else {
- _EhentaiState.ImageContainer.appendChild(_EhentaiState.LoadMoreBtn);
- }
- getNextImage(p, h);
- }
- };
- xmlhttp.send();
- }
-
- const mainContainer = document.querySelector(_EhentaiState.MainContainerSelector);
- window.addEventListener('resize', () => {
- document.querySelector(_EhentaiState.MainContainerSelector).style.maxWidth = '100vw';
- });
- mainContainer.style.width = '100vw';
- mainContainer.style.maxWidth = '100vw';
- document.querySelector(_EhentaiState.TopPaginationSelector).style.display = 'none';
- document.querySelector(_EhentaiState.BottomPaginationSelector).style.display = 'none';
- const [, page, hash] = _EhentaiState.NextPagePattern.exec(
- document.querySelector(_EhentaiState.MainContainerSelector).innerHTML
- );
- getNextImage(page, hash);
- },
-
- extractEhentaiImages() {
- const img = document.querySelector(_EhentaiState.ImagesSelector);
- const title = innerText(document.querySelector(_EhentaiState.TitleSelector));
- return `${title}\n${[img.src, ..._EhentaiState.ImageSources.slice(1)].join('\n')}\n${'= ='.repeat(20)}`;
- }
- };
-
- },{"./utils":6}],3:[function(require,module,exports){
- const {href, innerText, isHitomi} = require('./utils');
-
- let _HitomiState = {};
-
- module.exports = {
- initHitomi() {
- if (!isHitomi()) return;
- _HitomiState.ImgsSrcSelector = '.img-url';
- _HitomiState.TitleSelector = 'title';
- _HitomiState.Adapost = false;
- _HitomiState.NumberOfFrontEnds = 2;
-
- },
- extractHitomiImages() {
- const {ImgsSrcSelector, TitleSelector, Adapost, NumberOfFrontEnds} = _HitomiState;
- let images = Array.from(document.querySelectorAll(ImgsSrcSelector));
- let title = encodeURIComponent(innerText(document.querySelector(TitleSelector), '- | -').split(' | ')[0]);
- const mat = /\/\d*(\d)\.html/.exec(href());
- let lv = mat && parseInt(mat[1], 10);
- if (!lv || Number.isNaN(lv)) {
- lv = '1';
- }
- const magic = Adapost ? 'a' : String.fromCharCode(((lv === 1 ? 0 : lv) % NumberOfFrontEnds) + 97);
- images = images.map(s => s.innerText.replace('//g.hitomi.la', `https://${magic}a.hitomi.la`));
- return `${title}\n${images.join('\n')}\n${'= ='.repeat(20)}`;
- }
- };
-
- },{"./utils":6}],4:[function(require,module,exports){
- const {isHitomi, isNozomi, isEhentai, copyToClipboard} = require('./utils');
- const Button = require('./Button');
- const {initHitomi, extractHitomiImages} = require('./hitomi');
- const {initNozomi, extractNozomiImages, fetchNozomiAll} = require('./nozomi');
- const {initEhentai, extractEhentaiImages, fetchEhentaiAll} = require('./ehentai');
-
- (function () {
- initHitomi();
- initNozomi();
- initEhentai();
- // create button to click
- if (isNozomi() || isEhentai()) {
- const btn = new Button('Fetch All');
- btn.addCss({bottom: '160px', zIndex: '999'});
- btn.appendTo(document.body);
- btn.onClick(() => {
- if (isNozomi()) {
- fetchNozomiAll();
- }
- if (isEhentai()) {
- fetchEhentaiAll();
- }
- });
- }
- const btn = new Button('Copy Sources');
- btn.addCss({zIndex: '999'});
- btn.onClick(() => {
- // prepare str2Paste
- let str2paste = '';
- if (isHitomi()) {
- str2paste = extractHitomiImages();
- } else if (isNozomi()) {
- str2paste = extractNozomiImages();
- } else {
- str2paste = extractEhentaiImages();
- }
- copyToClipboard(str2paste);
- });
- btn.appendTo(document.body);
- })();
-
- },{"./Button":1,"./ehentai":2,"./hitomi":3,"./nozomi":5,"./utils":6}],5:[function(require,module,exports){
- const {innerText, createFullScreenElement} = require('./utils');
-
- // TODO: refactor
-
- const [
- ImgSrcSelector,
- TitleSelector,
- ContentSelector,
- ThumbnailDivsSelector
- ] = ['.tag-list-img', 'h1', '.content', '#thumbnail-divs'];
-
- function JSPack() {
- // Module-level (private) variables
- var el, bBE = false, m = this;
-
- // Raw byte arrays
- m._DeArray = function (a, p, l) {
- return [a.slice(p, p + l)];
- };
- m._EnArray = function (a, p, l, v) {
- for (var i = 0; i < l; a[p + i] = v[i] ? v[i] : 0, i++) ;
- };
-
- // ASCII characters
- m._DeChar = function (a, p) {
- return String.fromCharCode(a[p]);
- };
- m._EnChar = function (a, p, v) {
- a[p] = v.charCodeAt(0);
- };
-
- // Little-endian (un)signed N-byte integers
- m._DeInt = function (a, p) {
- var lsb = bBE ? (el.len - 1) : 0, nsb = bBE ? -1 : 1, stop = lsb + nsb * el.len, rv, i, f;
- for (rv = 0, i = lsb, f = 1; i != stop; rv += (a[p + i] * f), i += nsb, f *= 256) ;
- if (el.bSigned && (rv & Math.pow(2, el.len * 8 - 1))) { rv -= Math.pow(2, el.len * 8); }
- return rv;
- };
- m._EnInt = function (a, p, v) {
- var lsb = bBE ? (el.len - 1) : 0, nsb = bBE ? -1 : 1, stop = lsb + nsb * el.len, i;
- v = (v < el.min) ? el.min : (v > el.max) ? el.max : v;
- for (i = lsb; i != stop; a[p + i] = v & 0xff, i += nsb, v >>= 8) ;
- };
-
- // ASCII character strings
- m._DeString = function (a, p, l) {
- for (var rv = new Array(l), i = 0; i < l; rv[i] = String.fromCharCode(a[p + i]), i++) ;
- return rv.join('');
- };
- m._EnString = function (a, p, l, v) {
- for (var t, i = 0; i < l; a[p + i] = (t = v.charCodeAt(i)) ? t : 0, i++) ;
- };
-
- // Little-endian N-bit IEEE 754 floating point
- m._De754 = function (a, p) {
- var s, e, m, i, d, nBits, mLen, eLen, eBias, eMax;
- mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
-
- i = bBE ? 0 : (el.len - 1);
- d = bBE ? 1 : -1;
- s = a[p + i];
- i += d;
- nBits = -7;
- for (e = s & ((1 << (-nBits)) - 1), s >>= (-nBits), nBits += eLen; nBits > 0; e = e * 256 + a[p + i], i += d, nBits -= 8) ;
- for (m = e & ((1 << (-nBits)) - 1), e >>= (-nBits), nBits += mLen; nBits > 0; m = m * 256 + a[p + i], i += d, nBits -= 8) ;
-
- switch (e) {
- case 0:
- // Zero, or denormalized number
- e = 1 - eBias;
- break;
- case eMax:
- // NaN, or +/-Infinity
- return m ? NaN : ((s ? -1 : 1) * Infinity);
- default:
- // Normalized number
- m = m + Math.pow(2, mLen);
- e = e - eBias;
- break;
- }
- return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
- };
- m._En754 = function (a, p, v) {
- var s, e, m, i, d, c, mLen, eLen, eBias, eMax;
- mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
-
- s = v < 0 ? 1 : 0;
- v = Math.abs(v);
- if (isNaN(v) || (v === Infinity)) {
- m = isNaN(v) ? 1 : 0;
- e = eMax;
- }
- else {
- e = Math.floor(Math.log(v) / Math.LN2); // Calculate log2 of the value
- if (v * (c = Math.pow(2, -e)) < 1) {
- e--;
- c *= 2;
- } // Math.log() isn't 100% reliable
-
- // Round by adding 1/2 the significand's LSD
- if (e + eBias >= 1) { v += el.rt / c; } // Normalized: mLen significand digits
- else { v += el.rt * Math.pow(2, 1 - eBias); } // Denormalized: <= mLen significand digits
- if (v * c >= 2) {
- e++;
- c /= 2;
- } // Rounding can increment the exponent
-
- if (e + eBias >= eMax) {
- // Overflow
- m = 0;
- e = eMax;
- }
- else if (e + eBias >= 1) {
- // Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow
- m = (v * c - 1) * Math.pow(2, mLen);
- e = e + eBias;
- }
- else {
- // Denormalized - also catches the '0' case, somewhat by chance
- m = v * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
- e = 0;
- }
- }
-
- for (i = bBE ? (el.len - 1) : 0, d = bBE ? -1 : 1; mLen >= 8; a[p + i] = m & 0xff, i += d, m /= 256, mLen -= 8) ;
- for (e = (e << mLen) | m, eLen += mLen; eLen > 0; a[p + i] = e & 0xff, i += d, e /= 256, eLen -= 8) ;
- a[p + i - d] |= s * 128;
- };
-
-
- // Class data
- m._sPattern = '(\\d+)?([AxcbBhHsfdiIlL])';
- m._lenLut = {
- 'A': 1,
- 'x': 1,
- 'c': 1,
- 'b': 1,
- 'B': 1,
- 'h': 2,
- 'H': 2,
- 's': 1,
- 'f': 4,
- 'd': 8,
- 'i': 4,
- 'I': 4,
- 'l': 4,
- 'L': 4
- };
- m._elLut = {
- 'A': {en: m._EnArray, de: m._DeArray},
- 's': {en: m._EnString, de: m._DeString},
- 'c': {en: m._EnChar, de: m._DeChar},
- 'b': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: true, min: -Math.pow(2, 7), max: Math.pow(2, 7) - 1},
- 'B': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: false, min: 0, max: Math.pow(2, 8) - 1},
- 'h': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: true, min: -Math.pow(2, 15), max: Math.pow(2, 15) - 1},
- 'H': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: false, min: 0, max: Math.pow(2, 16) - 1},
- 'i': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
- 'I': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
- 'l': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
- 'L': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
- 'f': {en: m._En754, de: m._De754, len: 4, mLen: 23, rt: Math.pow(2, -24) - Math.pow(2, -77)},
- 'd': {en: m._En754, de: m._De754, len: 8, mLen: 52, rt: 0}
- };
-
- // Unpack a series of n elements of size s from array a at offset p with fxn
- m._UnpackSeries = function (n, s, a, p) {
- for (var fxn = el.de, rv = [], i = 0; i < n; rv.push(fxn(a, p + i * s)), i++) ;
- return rv;
- };
-
- // Pack a series of n elements of size s from array v at offset i to array a at offset p with fxn
- m._PackSeries = function (n, s, a, p, v, i) {
- for (var fxn = el.en, o = 0; o < n; fxn(a, p + o * s, v[i + o]), o++) ;
- };
-
- // Unpack the octet array a, beginning at offset p, according to the fmt string
- m.Unpack = function (fmt, a, p) {
- // Set the private bBE flag based on the format string - assume big-endianness
- bBE = (fmt.charAt(0) != '<');
-
- p = p ? p : 0;
- var re = new RegExp(this._sPattern, 'g'), m, n, s, rv = [];
- while (m = re.exec(fmt)) {
- n = ((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1]);
- s = this._lenLut[m[2]];
- if ((p + n * s) > a.length) {
- return undefined;
- }
- switch (m[2]) {
- case 'A':
- case 's':
- rv.push(this._elLut[m[2]].de(a, p, n));
- break;
- case 'c':
- case 'b':
- case 'B':
- case 'h':
- case 'H':
- case 'i':
- case 'I':
- case 'l':
- case 'L':
- case 'f':
- case 'd':
- el = this._elLut[m[2]];
- rv.push(this._UnpackSeries(n, s, a, p));
- break;
- }
- p += n * s;
- }
- return Array.prototype.concat.apply([], rv);
- };
-
- // Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
- m.PackTo = function (fmt, a, p, values) {
- // Set the private bBE flag based on the format string - assume big-endianness
- bBE = (fmt.charAt(0) !== '<');
-
- var re = new RegExp(this._sPattern, 'g'), m, n, s, i = 0, j;
- while (m = re.exec(fmt)) {
- n = ((m[1] === undefined) || (m[1] === '')) ? 1 : parseInt(m[1]);
- s = this._lenLut[m[2]];
- if ((p + n * s) > a.length) {
- return false;
- }
- switch (m[2]) {
- case 'A':
- case 's':
- if ((i + 1) > values.length) { return false; }
- this._elLut[m[2]].en(a, p, n, values[i]);
- i += 1;
- break;
- case 'c':
- case 'b':
- case 'B':
- case 'h':
- case 'H':
- case 'i':
- case 'I':
- case 'l':
- case 'L':
- case 'f':
- case 'd':
- el = this._elLut[m[2]];
- if ((i + n) > values.length) { return false; }
- this._PackSeries(n, s, a, p, values, i);
- i += n;
- break;
- case 'x':
- for (j = 0; j < n; j++) { a[p + j] = 0; }
- break;
- }
- p += n * s;
- }
- return a;
- };
-
- // Pack the supplied values into a new octet array, according to the fmt string
- m.Pack = function (fmt, values) {
- return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values);
- };
-
- // Determine the number of bytes represented by the format string
- m.CalcLength = function (fmt) {
- var re = new RegExp(this._sPattern, 'g'), m, sum = 0;
- while (m = re.exec(fmt)) {
- sum += (((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1])) * this._lenLut[m[2]];
- }
- return sum;
- };
- }
-
-
- var nozomiextension = '.nozomi';
- var nozomidir = 'nozomi';
- var domain = 'n.nozomi.la';
- var postdir = 'post';
-
- var results_array = {};
- var outstanding_requests = {};
- var number_of_outstanding_requests = 0;
- var nozomi, total_items;
- var tag, tag_for_hash = '', area, page_number;
- var nozomi_address;
-
-
- function dgebi(id) { return document.getElementById(id); }
-
- function path_from_postid(postid) {
- if (postid.length < 3) return postid;
-
- return postid.replace(/^(.*(..)(.))$/, '$3/$2/$1');
- }
-
- function resize_thumbnails() {
- var c = document.getElementsByClassName('content')[0];
- if (!c) {
- return;
- }
-
- var s = c.clientWidth;
-
- var n = Math.ceil(6.0 * s / 1000.0);
- var w = ((s - (10.0 * n + 10.0) - 0.5) / n) - 2.0;
-
- var divs = document.getElementsByClassName('thumbnail-div');
- for (var i = 0; i < divs.length; i++) {
- var div = divs[i];
- div.style.width = (w + 'px');
- div.style.height = (w + 'px');
- }
- }
-
- function check_dates() {
- var format = 'lll';
-
- var localize_title = function (el) {
- if (!el) {
- return;
- }
-
- var str = el.title;
- if (str) {
- var m = moment(str);
- el.title = m.format(format);
- }
- };
- //post view
- localize_title(document.querySelectorAll('.post img')[0]);
- }
-
- function urlencode(str) {
- return str.replace(/[;\/?:@=&]/g, function (c) {
- return '%' + c.charCodeAt(0).toString(16);
- return '%' + c.charCodeAt(0).toString(16);
- });
- }
-
- function fetch_nozomi(totalImageCount) {
- var filepath = decodeURIComponent(document.location.href.replace(/.*nozomi\.la\//, ''));
- if (!filepath) {
- tag = 'index';
- page_number = 1;
- } else {
- var elements = filepath.replace(/\.html$/, '').split('-');
- if (elements.length < 2) return;
- while (elements.length > 2) {
- elements[1] = elements[0] + '-' + elements[1];
- elements.shift();
- }
-
- tag = elements[0];
- if (tag.match(/\//)) {
- var area_elements = tag.split(/\//);
- if (area_elements.length !== 2) return;
-
- area = area_elements[0];
- if (!area || area.match(/[^A-Za-z0-9_]/)) return;
-
- tag = area_elements[1];
- }
- if (!tag || tag.match(/\//)) return;
-
- if (tag === 'index-Popular') {
- tag_for_hash = '-Popular';
- } else if (area) {
- tag_for_hash = tag;
- }
-
- page_number = parseInt(elements[1]);
- if (!page_number || page_number < 1) return;
- }
- nozomi_address = '//' + [domain, urlencode(tag)].join('/') + nozomiextension;
- if (area) {
- nozomi_address = '//' + [domain, nozomidir, urlencode(tag)].join('/') + nozomiextension;
- }
-
- var start_byte = 0;
- var end_byte = totalImageCount * 4 - 1;
- var xhr = new XMLHttpRequest();
- const loadingElement = createFullScreenElement();
- document.body.appendChild(loadingElement);
- xhr.open('GET', nozomi_address);
- xhr.responseType = 'arraybuffer';
- xhr.setRequestHeader('Range', 'bytes=' + start_byte.toString() + '-' + end_byte.toString());
- xhr.onreadystatechange = function (oEvent) {
- if (xhr.readyState === 4) {
- if (xhr.status === 200 || xhr.status === 206) {
- var arrayBuffer = xhr.response; // Note: not oReq.responseText
- if (arrayBuffer) {
- var arr = new Uint8Array(arrayBuffer); //e.g. [0x00, 0x5D, 0x39, 0x72, 0x00, 0x5D, 0x39, 0x82, ...]
- var jspack = new JSPack();
- var total = arr.length / 4; //32-bit unsigned integers
- nozomi = jspack.Unpack(total + 'I', arr);
- total_items = parseInt(xhr.getResponseHeader('Content-Range').replace(/^[Bb]ytes \d+-\d+\//, '')) / 4;
- get_jsons();
- document.body.removeChild(loadingElement);
- }
- }
- }
- };
- xhr.send();
- }
-
- function get_jsons() {
- var datas = [];
- for (var i in nozomi) {
- var postid = nozomi[i];
- if (postid in results_array) {
- datas.push(results_array[postid]);
- continue;
- }
- if (!outstanding_requests[postid]) {
- outstanding_requests[postid] = 1;
- ++number_of_outstanding_requests;
- get_json(postid); //calling a function is REQUIRED to give postid its own scope
- }
- }
- if (number_of_outstanding_requests) return;
-
- results_to_page(datas);
- }
-
- function get_json(postid) {
- var url = '//j.nozomi.la/' + postdir + '/' + path_from_postid(postid.toString()) + '.json';
-
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.open('GET', url);
- xmlhttp.onreadystatechange = function () {
- if (this.readyState === 4) {
- if (this.status === 200) {
- results_array[postid] = JSON.parse(this.responseText);
- } else {
- results_array[postid] = '';
- }
- delete outstanding_requests[postid];
- --number_of_outstanding_requests;
- get_jsons();
- }
- };
- xmlhttp.send();
- }
-
- function results_to_page(datas) {
- var tc = Object.create(null);
- var to = {};
-
- dgebi('thumbnail-divs').innerHTML = '';
-
- var ul = document.getElementsByClassName('title')[0].nextElementSibling;
- ul.innerHTML = '';
-
- var p = function (l) {
- var areas = ['general', 'artist', 'copyright', 'character'];
- for (var a in areas) {
- var area = areas[a];
- for (var i in l[area]) {
- var tag = l[area][i];
-
- if (tag.tag in tc === false) {
- tc[tag.tag] = 1;
- } else {
- tc[tag.tag]++;
- }
-
- to[tag.tag] = tag;
- }
- }
- };
-
- for (var d in datas) {
- var data = datas[d];
- if (!data) continue;
-
- var div = document.createElement('div');
- div.classList.add('thumbnail-div');
-
- var a = document.createElement('a');
- a.href = '/post/' + data.postid + '.html#' + tag_for_hash;
-
- var img = document.createElement('img');
- img.classList.add('tag-list-img');
- img.crossOrigin = 'Anonymous';
- img.src = data.imageurl.replace(/\/\/i\.nozomi\.la\//, '//tn.nozomi.la/') + '.jpg';
- img.title = data.date;
-
- a.appendChild(img);
- div.appendChild(a);
- dgebi('thumbnail-divs').appendChild(div);
-
- p(data);
- }
-
-
- resize_thumbnails();
- setTimeout(resize_thumbnails, 10);
-
- check_dates();
- }
-
-
- module.exports = {
- initNozomi() {
- return;
- },
- fetchNozomiAll() {
- const totalPage = parseInt(innerText(document.querySelector('.page-container li:last-child'), 1), 10);
- const totalImageCount = totalPage * 64;
- // prettify page
- const elementsToRemove = [
- document.querySelector('.page-container'),
- document.querySelector('.navbar'),
- document.querySelector('.sidebar')
- ];
- for (const elem of elementsToRemove) {
- elem.style.display = 'none';
- }
- const mainContent = document.querySelector('.content');
- mainContent.style.margin = '0 auto';
- const thumbnailsContainer = document.getElementById('thumbnail-divs');
- for (const e of Array.from(thumbnailsContainer.getElementsByClassName('thumbnail-div'))) {
- thumbnailsContainer.removeChild(e);
- }
- fetch_nozomi(totalImageCount);
- },
- extractNozomiImages() {
- let images = Array.from(document.querySelectorAll(ImgSrcSelector));
- let title = document.querySelector(TitleSelector).innerText;
- images = images.map(s => s.src.replace('//tn', '//i').split('.').slice(0, 4).join('.'));
- return `${title}\n${images.join('\n')}\n${'= ='.repeat(20)}`;
- }
- };
-
- },{"./utils":6}],6:[function(require,module,exports){
- module.exports = {
- isHitomi() {
- return window && window.location && /hitomi/gi.test(window.location.href);
- },
- isNozomi() {
- return window && window.location && /nozomi.la\/tag/gi.test(window.location.href);
- },
- isEhentai() {
- return window && window.location && /e-hentai.org\/s/gi.test(window.location.href);
- },
- copyToClipboard(content) {
- const el = document.createElement('textarea');
- el.value = content;
- document.body.appendChild(el);
- el.select();
- document.execCommand('copy');
- document.body.removeChild(el);
- },
- href(d = '') {
- return (window && window.location && window.location.href) || d;
- },
- innerText(elem, d = '') {
- return (elem && elem.innerText) || d;
- },
- matchAll(content, pat) {
- let matches = [];
- let match = pat.exec(content);
- while (match) {
- matches.push(match[1]);
- match = pat.exec(content);
- }
- pat.lastIndex = -1;
- return matches;
- },
- createFullScreenElement(text) {
- const elem = document.createElement('div');
- elem.style.position = 'fixed';
- elem.style.top = '0';
- elem.style.right = '0';
- elem.style.bottom = '0';
- elem.style.left = '0';
- elem.style.display = 'flex';
- elem.style.backgroundColor = 'rgba(0, 0, 0, 0.56)';
- elem.style.justifyContent = 'center';
- elem.style.alignItems = 'center';
- elem.style.fontSize = '72px';
- elem.style.zIndex = '999';
- elem.innerText = text;
- return elem;
- }
- };
-
- },{}]},{},[4]);