UNPKG

node-hitomi

Version:
2 lines (1 loc) 9.58 kB
"use strict";const e=require("crypto"),t=require("https"),n=["parody","artist","group","character"],a=new Set(n.slice(1).concat("type","language","series","male","female","tag")),r=["",!1,new Set],s="gold-usergeneratedcontent.net",i="ltn."+s;class l extends Error{constructor(e,...t){switch(e){case 0:super(t[0]+" must "+(1===t.length?"be valid":t[1])),this.name="INVALID_VALUE";break;case 1:super(t[0]+" must "+t[1]),this.name="INVALID_CALL";break;case 2:super(t[0]+" must not be duplicated"),this.name="DUPLICATED_ELEMENT";break;case 3:super(t[0]+" must have more elements"),this.name="LACK_OF_ELEMENT";break;case 4:super("Request to '"+t[0].replace(/'/g,"\\'")+"' was rejected"),this.name="REQEUST_REJECTED";break;default:throw null}this.name="HitomiError ["+this.name+"]"}}function o(e,n={}){return new Promise((function(a,r){const i=e.indexOf("/");t.request({hostname:e.slice(0,i),path:e.slice(i),method:"GET",port:"443",headers:Object.assign(n,{accept:"*/*",connection:"keep-alive",referer:"https://"+s})},(function(t){const n=[];let s=0;switch(t.statusCode){case 200:case 206:t.on("data",(function(e){n.push(e),s+=e.byteLength})).once("error",r).once("end",(function(){a(Buffer.concat(n,s))}));break;default:r(new l(4,"https://"+e))}})).once("error",r).end()}))}function c(e,t=!1){const n=new Set;n.isNegative=t;for(let t=0;t<e.byteLength;t+=4)n.add(e.readInt32BE(t));return n}function g(e,t){return o(i+"/galleriesindex/galleries."+t+".index",{range:"bytes="+e+"-"+(e+463n)}).then((function(e){return 0!==e.length?function(e){const t=[[],[],[]],n=e.readInt32BE(0);let a=4;for(let r=0;r<n;r++){const n=e.readInt32BE(a);if(!(n>0&&n<32))throw new l(0,"keySize","between 1 and 31");a+=4,t[0].push(e.subarray(a,a+n)),a+=n}const r=e.readInt32BE(a);a+=4;for(let n=0;n<r;n++)t[1].push([e.readBigUInt64BE(a),e.readInt32BE(a+8)]),a+=12;for(let n=0;n<17;n++)t[2].push(e.readBigUInt64BE(a)),a+=8;return t}(e):void 0}))}function u(e,t,n){if(0!==t[0].length){let a=-1,r=0;for(;r<t[0].length&&(a=e.compare(t[0][r]),!(a<=0));)r++;if(0===a)return Promise.resolve(t[1][r]);if(0n===t[2][r])return Promise.resolve();{let e=!0;for(let n=0;n<t[2].length;n++)if(0n!==t[2][n]){e=!1;break}if(e)return Promise.resolve()}return g(t[2][r],n).then((function(t){return"object"==typeof t?u(e,t,n):void 0}))}return Promise.resolve()}function f(e={}){let t="index",n="all";if("object"==typeof e.tag)switch(e.tag.type){case"male":case"female":t="tag/"+e.tag.type+":"+encodeURIComponent(e.tag.name);break;case"language":n=e.tag.name;break;default:t=e.tag.type+"/"+encodeURIComponent(e.tag.name)}else"string"==typeof e.popularityOrderBy&&(t="day"!==e.popularityOrderBy?e.popularityOrderBy:"today");return i+"/"+("string"!=typeof e.popularityOrderBy?"n":"popular")+"/"+t+"-"+n+".nozomi"}function h(e,t){const n="language"===e;if("string"==typeof t!==n){let a="ltn.",r="all";if(n)r="language_support";else{switch(a="",e){case"tag":case"male":case"female":r+="tags";break;case"artist":case"series":case"character":case"group":r+=e,e.endsWith("s")||(r+="s");break;default:throw new l(0,"type")}r+="-"+("0-9"!==t?t:"123")+".html"}return a+s+"/"+r}throw new l(0,"startsWith","not be used with language")}const p={getGallery:function(e){return o(i+"/galleries/"+e+".js").then((function(t){const a=JSON.parse(t.toString("utf-8").slice(18)),r=JSON.parse('{"id":'+e+',"title":{"display":"'+a.title.replace(/"/g,'\\"')+'","japanese":'+("string"==typeof a.japanese_title?'"'+a.japanese_title.replace(/"/g,'\\"')+'"':"null")+'},"type":"'+a.type+'","languageName":{"english":'+(null!==typeof a.language?'"'+a.language+'"':"null")+',"local":'+(null!==typeof a.language_localname?'"'+a.language_localname+'"':"null")+'},"artists":[],"groups":[],"series":[],"characters":[],"tags":[],"files":[],"publishedDate":null,"translations":[],"relatedIds":null}');for(let e=0;e<n.length;e++){const t=n[e]+"s";if(null!==a[t]){const s=t.startsWith("p")?"series":t;for(let i=0;i<a[t].length;i++)r[s].push(a[t][i][n[e]])}}if(Array.isArray(a.tags))for(let e=0;e<a.tags.length;e++){let t="tag";Boolean(a.tags[e].male)?t="male":Boolean(a.tags[e].female)&&(t="female"),r.tags.push({type:t,name:a.tags[e].tag})}for(let e=0;e<a.files.length;e++)r.files.push({index:e,hash:a.files[e].hash,name:a.files[e].name,hasAvif:1===a.files[e].hasavif,hasWebp:0!==a.files[e].haswebp,hasJxl:1===a.files[e].hasjxl,width:a.files[e].width,height:a.files[e].height});r.publishedDate=new Date(a.datepublished);for(let e=0;e<a.languages.length;e++)r.translations.push({id:Number(a.languages[e].galleryid),languageName:{english:a.languages[e].name,local:a.languages[e].language_localname}});return r.relatedIds=a.related,r}))},getGalleryIds:function(t={}){return o(i+"/galleriesindex/version").then((function(n){const a="string"==typeof t.title,r=Array.isArray(t.tags)&&0!==t.tags.length,s="object"==typeof t.range,h=s&&(a||r),p=n.toString("utf-8"),d=[];if(("string"==typeof t.popularityOrderBy||s||r&&t.tags[0].isNegative)&&d.push(o(f({popularityOrderBy:t.popularityOrderBy}),h?void 0:{range:"bytes="+("number"==typeof t.range.start?4*t.range.start:"0")+"-"+("number"==typeof t.range.end?4*t.range.end-1:"")}).then(c)),a){t.title=t.title.toLocaleLowerCase()+" ";let n=0,a=t.title.indexOf(" ");for(;-1!==a;){if(a-n==0)return Promise.reject(new l(0,"options['title']","not contain continuous or edge space"));{const r=e.createHash("sha256").update(t.title.slice(n,a)).digest().subarray(0,4);d.push(g(0n,p).then((function(e){return"object"==typeof e?u(r,e,p):void 0})).then((function(e){return Array.isArray(e)?o(i+"/galleriesindex/galleries."+p+".data",{range:"bytes="+(e[0]+4n)+"-"+(e[0]+BigInt(e[1])-1n)}):void 0})).then((function(e){return c("object"==typeof e?e:Buffer.from([]))})))}n=a+1,a=t.title.indexOf(" ",n)}}if(r)for(let e=0;e<t.tags.length;e++)d.push(o(f({tag:t.tags[e]})).then((function(n){return c(n,t.tags[e].isNegative)})));return d.reduce((function(e,t){return e.then((function(e){return t.then((function(t){for(const n of e)t.isNegative===t.has(n)&&e.delete(n);return e}))}))}),o(f()).then(c)).then((function(e){const n=Array.from(e);return h?n.slice(t.range.start,t.range.end):n}))}))},getParsedTags:function(e){const t=[],n=new Set;let r=0,s=(e+=" ").indexOf(" ");for(;-1!==s;){const i=e.indexOf(":",r);if(!(-1!==i&&i<s))throw new l(0,"'"+e.slice(r,s)+"'");{const o=e.startsWith("-",r),c={type:e.slice(r+(o?1:0),i),name:e.slice(i+1,s),isNegative:o};if(!a.has(c.type)){let e="be one of ";for(const t of a)e+="'"+t+"', ";throw new l(0,"'"+c.type+"'",e.slice(0,-2))}if(!/^[a-z0-9][a-z0-9-_.]*$/.test(c.name))throw new l(0,"'"+c.name+"'","match /^[a-z0-9][a-z0-9-_.]*$/");{const e=c.type+":"+c.name;if(n.has(e))throw new l(2,"'"+e+"'");c.name=c.name.replace(/_/g," "),t.push(c),n.add(e)}}r=s+1,s=e.indexOf(" ",r)}return t},getTags:function(e,t){const n="type"===e,a="language"===e;return"string"==typeof t!==(n||a)?n?Promise.resolve([{type:"type",name:"doujinshi"},{type:"type",name:"manga"},{type:"type",name:"artistcg"},{type:"type",name:"gamecg"},{type:"type",name:"imageset"},{type:"type",name:"anime"}]):o(h(e,t)).then((function(t){const n=t.toString("utf-8"),r=[];let s,i;if(a){const e=n.indexOf("}");for(s=n.indexOf(":")+2,i=n.indexOf('"',s);i<e;)r.push({type:"language",name:n.slice(s,i)}),s=n.indexOf(":",i)+2,i=n.indexOf('"',s)}else{let t='href="/';switch(e){case"male":case"female":t+="tag/"+e+"%3A";break;default:t+=e+"/"}const a=t.length-1;if(s=n.indexOf(t)+t.length,i=n.indexOf(".",s),"tag"!==e)for(;s!==a;)r.push({type:e,name:decodeURIComponent(n.slice(s,i-4))}),s=n.indexOf(t,i)+t.length,i=n.indexOf(".",s);else for(;s!==a;)n.startsWith("male",s)||n.startsWith("female",s)||r.push({type:e,name:decodeURIComponent(n.slice(s,i-4))}),s=n.indexOf(t,i)+t.length,i=n.indexOf(".",s)}return r})):Promise.reject(new l(0,"startsWith","not be used only with type and language"))},getNozomiUri:f,getTagUri:h,getVideoUri:function(e){if("anime"===e.type)return"streaming."+s+"/videos/"+e.title.display.toLowerCase().replace(/\s/g,"-")+".mp4";throw new l(0,"gallery['type']","be 'anime'")},getGalleryUri:function(e){return(s+"/"+("artistcg"!==e.type?e.type:"cg")+"/"+encodeURIComponent(Buffer.from(e.title.japanese||e.title.display).subarray(0,200).toString("utf-8")).replace(/\(|\)|'|%(2[0235F]|3[CEF]|5[BD]|7[BD])/g,"-")+(null!==e.languageName.local?"-"+encodeURIComponent(e.languageName.local):"")+"-"+e.id+".html").toLocaleLowerCase()},ImageUriResolver:class{static synchronize(){return o(i+"/gg.js").then((function(e){const t=e.toString("utf-8");let n=0,a=t.indexOf("\n");for(r[2].clear();-1!==a;){switch(t[n]){case"b":r[0]=t.slice(n+4,a-2);break;case"o":r[1]="0"===t[n+4];break;case"c":r[2].add(Number(t.slice(n+5,a-1)))}n=a+1,a=t.indexOf("\n",n)}if(0===r[0].length||0===r[2].size||r[2].has(NaN)){const e=r[2].size;throw r[2].clear(),new l(0,"ImageUriResolver { [Symbol(pathCode)]: '"+r[0]+"', [Symbol(startsWithA)]: "+r[1]+", [Symbol(subdomainCodes)]: Set("+e+") }")}}))}static getImageUri(e,t,n={}){if(0!==r[2].size){switch(t){case"webp":case"avif":case"jxl":if(e["has"+t[0].toUpperCase()+t.slice(1)])break;default:throw new l(0,"extension")}const a=Number.parseInt(e.hash.slice(-1)+e.hash.slice(-3,-1),16);let i=t[0],o="";if(n.isThumbnail){if(n.isSmall){if("avif"!==t)throw new l(0,"options['isSmall']","be used with avif");o+="small"}o+="bigtn/"+e.hash.slice(-1)+"/"+e.hash.slice(-3,-1)+"/"+e.hash,i="tn"}else o+=r[0]+"/"+a+"/"+e.hash;return i+(r[2].has(a)===r[1]?"1":"2")+"."+s+"/"+o+"."+t}throw new l(1,"ImageUriResolver.getImageUri()","be called after ImageUriResolver.synchronize()")}}},d=Object.assign(p,{default:p});module.exports=d;