UNPKG

node-hitomi

Version:
177 lines (173 loc) 4.41 kB
'use strict'; const error = require('../structures/error.cjs'); const constants = require('../internal/constants.cjs'); const base = require('../internal/base.cjs'); const tag = require('../structures/tag.cjs'); const gallery = require('../structures/gallery.cjs'); const NameInitial = { A: 'a', B: 'b', C: 'c', D: 'd', E: 'e', F: 'f', G: 'g', H: 'h', I: 'i', J: 'j', K: 'k', L: 'l', M: 'm', N: 'n', O: 'o', P: 'p', Q: 'q', R: 'r', S: 's', T: 't', U: 'u', V: 'v', W: 'w', X: 'x', Y: 'y', Z: 'z', _123: '123' }; class TagManager extends base.Base { constructor(hitomi) { super(hitomi); } create(type, name, isNegative = false) { if(!name.length) { throw new error.HitomiError(error.ErrorCode.InvalidArgument, 'Name', 'empty', false); } return new tag.Tag(this.hitomi, type, name.replace(/_/g, ' '), isNegative); } parse(expression) { expression = expression.trim() + ' '; const tags = []; const rawTags = new Set(); let currentIndex = 0; let nextIndex; while((nextIndex = expression.indexOf(' ', currentIndex)) !== -1) { const colonIndex = expression.indexOf(':', currentIndex); if(colonIndex !== -1 && colonIndex < nextIndex) { const rawTag = expression.slice(currentIndex, nextIndex); const isNegative = expression[currentIndex] === '-'; if(!rawTags.has(rawTag)) { tags.push(new tag.Tag(this.hitomi, expression.slice(currentIndex + isNegative, colonIndex), expression.slice(colonIndex + 1, nextIndex).replace(/_/g, ' '), isNegative)); rawTags.add(rawTag); } } currentIndex = nextIndex + 1; } return tags; } async search(term) { const isNegative = term[0] === '-'; let i = term.indexOf(':') + 1; let path; if(i) { const type = term.slice(isNegative, i - 1); if(!tag.Tag.TYPES.has(type)) { throw error.HitomiError.invalidMember('Type', tag.Tag.TYPES); } path = '/' + type; } else { if(isNegative) { i++; } path = '/global'; } for(; i < term.length && term[i] !== ':'; i++) { path += '/'; switch(term[i]) { case '.': { path += 'dot'; break; } case '/': { path += 'slash'; break; } default: { path += term[i]; } } } const response = await this.hitomi.request(constants.TAG_INDEX_DOMAIN, path + '.json', 3); const tagAndCounts = []; for(i = 0; i < response.length; i++) { tagAndCounts.push([ new tag.Tag(this.hitomi, response[i][2], response[i][0]), response[i][1] ]); } return tagAndCounts; } async list(type, startsWith) { const tags = []; let names; switch(type) { case 'type': { names = gallery.Gallery.TYPES; } case 'language': { if(!names) { names = tag.Language.NAMES; } for(const name of names) { tags.push(new tag.Tag(this.hitomi, type, name)); } break; } default: { if(!startsWith) { throw new error.HitomiError(error.ErrorCode.InvalidCombination, 'StartsWith', 'provided except forlanguage and type'); } if(!TagManager.NAME_INITIALS.has(startsWith)) { throw error.HitomiError.invalidMember('StartsWith', TagManager.NAME_INITIALS); } let target = 'href="/' + type + '/'; let area; switch(type) { case 'male': case 'female': { target = 'href="/tag/' + type + '%3A'; } case 'tag': { area = 'tags'; break; } case 'series': { area = type; break; } case 'artist': case 'character': case 'group': { area = type + 's'; break; } default: { throw error.HitomiError.invalidMember('Type', tag.Tag.TYPES); } } const response = await this.hitomi.request(constants.FRONT_DOMAIN, '/all' + area + '-' + startsWith + '.html', 2); const endIndex = target.length - 1; let currentIndex; let nextIndex = 0; while((currentIndex = response.indexOf(target, nextIndex) + target.length) !== endIndex) { nextIndex = response.indexOf('.', currentIndex); if(type !== 'tag' || !response.startsWith('male', currentIndex) && !response.startsWith('female', currentIndex)) { tags.push(new tag.Tag(this.hitomi, type, decodeURIComponent(response.slice(currentIndex, nextIndex - 4)))); } } } } return tags; } } TagManager.NAME_INITIALS = new Set(Object.values(NameInitial)); exports.NameInitial = NameInitial; exports.TagManager = TagManager;