UNPKG

node-hitomi

Version:
98 lines (94 loc) 3.4 kB
'use strict'; const gallery = require('./managers/gallery.cjs'); const tag = require('./managers/tag.cjs'); const constants = require('./internal/constants.cjs'); const providers = require('./internal/providers.cjs'); const error = require('./structures/error.cjs'); const node = require('./platform/node.cjs'); const base = require('./internal/base.cjs'); class Hitomi { static getMaximumAge(options, key, defaultValue) { if(options[key] === 0) { return 0; } if(!options[key]) { return defaultValue; } if(!Number.isInteger(options[key]) || options[key] < 0) { throw new error.HitomiError(error.ErrorCode.InvalidArgument, 'Options.' + key, 'a non-negative integer'); } return options[key]; } static async fetchImageContext() { const response = await this.hitomi.request(constants.RESOURCE_DOMAIN, '/gg.js', 2); const context = [new Set(), false, '']; let currentIndex = 0; let nextIndex; while((currentIndex = response.indexOf('case ', currentIndex) + 5) !== 4 && (nextIndex = response.indexOf(':', currentIndex)) !== -1) { const subdomainCode = +response.slice(currentIndex, nextIndex); if(!Number.isInteger(subdomainCode)) { throw error.HitomiError.unparsableImageContext; } context[0].add(subdomainCode); currentIndex = nextIndex + 1; } if(!context[0].size) { throw error.HitomiError.unparsableImageContext; } currentIndex = response.indexOf('var o = ') + 8; const rawIsSuffix1 = +response.slice(currentIndex, response.indexOf(';', currentIndex)); if(!Number.isInteger(rawIsSuffix1)) { throw error.HitomiError.unparsableImageContext; } context[1] = !rawIsSuffix1; currentIndex = response.lastIndexOf('b: \'') + 4; if(currentIndex === 3) { throw error.HitomiError.unparsableImageContext; } context[2] = response.slice(currentIndex, response.indexOf('\'', currentIndex)); if(!context[2].length) { throw error.HitomiError.unparsableImageContext; } return context; } constructor(options = {}) { options = Object.assign({}, options); options.onRequest = options.agent ? function (context) { context.options.agent = options.agent; return context; } : options.onRequest; base.defineProperties(this, { request: options.transport ? async function (host, path, type, range) { const context = node.createContext(host, path, type, range); const buffer = await options.transport(await this.onRequest(context) || context); switch(type) { case 0: { return buffer; } case 1: { return new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); } case 2: { return node.toString(buffer); } case 3: { return JSON.parse(node.toString(buffer)); } } } : node.request, onRequest: options.onRequest || function () { }, hashTerm: options.computeHash ? async function (text) { return (await options.computeHash(text)).subarray(0, 4); } : node.hashTerm, indexMaximumAge: Hitomi.getMaximumAge(options, 'indexMaximumAge', 600000) }); this.galleries = new gallery.GalleryManager(this); this.tags = new tag.TagManager(this); base.defineProperties(this, { languageIndex: new providers.IndexProvider(this, 'languages'), imageContext: new providers.Provider(this, Hitomi.fetchImageContext, Hitomi.getMaximumAge(options, 'imageContextMaximumAge', 3600000)) }); } } exports.Hitomi = Hitomi;