@rexxhayanasi/nhentai
Version:
A scraper for NHentai with types
188 lines (187 loc) • 9.41 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _NHentai_axios;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NHentai = void 0;
const axios_1 = __importDefault(require("axios"));
const cheerio_1 = require("cheerio");
const tough_cookie_1 = require("tough-cookie");
const http_1 = require("http-cookie-agent/http");
const Parser_1 = require("../../Parser");
const constants_1 = require("../constants");
const util_1 = require("../util");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
class NHentai {
/**
* Constructs an instance of the NHentai class
* @param _options Options of the NHentai class
*/
constructor(_options = {
site: 'https://nhentai.to'
}) {
this._options = _options;
_NHentai_axios.set(this, void 0);
/**
* Gets a random doujin
* @returns Info of the random doujin
*/
this.getRandom = () => __awaiter(this, void 0, void 0, function* () {
return yield __classPrivateFieldGet(this, _NHentai_axios, "f")
.get(`${this._options.site}/random`)
.then(({ data }) => __awaiter(this, void 0, void 0, function* () {
return (0, Parser_1.parseDoujinInfo)((0, cheerio_1.load)(data), this._options.site.split('nhentai.')[1], this._options.site.includes('net')
? yield (0, util_1.getAPIGalleryPages)(__classPrivateFieldGet(this, _NHentai_axios, "f"), data)
: undefined);
}))
.catch((err) => {
throw new Error(err.message);
});
});
/**
* Explores the list of doujin
* @param page Page number of the list
* @returns The doujin list
*/
this.explore = (page = 1) => __awaiter(this, void 0, void 0, function* () {
if (isNaN(page) || page < 1)
page = 1;
return yield __classPrivateFieldGet(this, _NHentai_axios, "f")
.get(`${this._options.site}?page=${page}`)
.then(({ data }) => (0, Parser_1.parseDoujinList)((0, cheerio_1.load)(data), this._options.site.split('nhentai.')[1]))
.catch((err) => {
throw new Error(err.message);
});
});
/**
* Searches for a doujin by a query
* @param query Query of the doujin to search
* @param options Options for searching
* @returns The result of the search
*/
this.search = (query, options) => __awaiter(this, void 0, void 0, function* () {
if (!query)
throw new Error("The 'query' parameter shouldn't be undefined");
let page = 1;
if ((options === null || options === void 0 ? void 0 : options.page) && options.page > 0)
page = options.page;
return yield __classPrivateFieldGet(this, _NHentai_axios, "f")
.get(`${this._options.site}/search?q=${query}&page=${page}`)
.then((res) => {
const results = (0, Parser_1.parseDoujinList)((0, cheerio_1.load)(res.data), this._options.site.split('nhentai.')[1]);
if (!results.data.length)
throw new Error('No doujin results found');
return results;
});
});
/**
* Gets the info of a doujin by its ID
* @param id ID of the doujin
* @returns Info of the doujin
*/
this.getDoujin = (id) => __awaiter(this, void 0, void 0, function* () {
if (!id)
throw new Error("The 'id' parameter shouldn't be undefined");
const valid = yield this.validate(id);
if (!valid)
throw new Error('Invalid doujin ID');
return yield __classPrivateFieldGet(this, _NHentai_axios, "f")
.get(`${this._options.site}/g/${id}`)
.then((res) => __awaiter(this, void 0, void 0, function* () {
return (0, Parser_1.parseDoujinInfo)((0, cheerio_1.load)(res.data), this._options.site.split('nhentai.')[1], this._options.site.includes('net')
? yield (0, util_1.getAPIGalleryPages)(__classPrivateFieldGet(this, _NHentai_axios, "f"), res.data)
: undefined);
}))
.catch((err) => {
throw new Error(err.message);
});
});
/**
* Validates the ID of a doujin
* @param id ID of the doujin to check
*/
this.validate = (id) => __classPrivateFieldGet(this, _NHentai_axios, "f")
.get(`${this._options.site}/g/${id}`)
.then(() => true)
.catch(() => false);
__classPrivateFieldSet(this, _NHentai_axios, axios_1.default, "f");
// Validasi domain
if (!constants_1.sites.includes(this._options.site
.replace('https:', '')
.replace(/\//g, '')))
this._options.site = 'https://nhentai.to';
if (!this._options.site.startsWith('https://'))
this._options.site =
`https://${this._options.site}`;
// ✅ Ambil cookie default dari file jika tidak diberikan user
let defaultCookie = '';
const cookiePath = path_1.default.resolve(__dirname, '../lib/cookies.txt');
if (fs_1.default.existsSync(cookiePath)) {
defaultCookie = fs_1.default.readFileSync(cookiePath, 'utf8').trim();
}
// ✅ Gunakan defaultCookie kalau site nhentai.net tapi user tidak kasih cookie
if (this._options.site.includes('nhentai.net') &&
(!this._options.cookie_value || !this._options.user_agent)) {
if (!this._options.cookie_value && defaultCookie) {
this._options.cookie_value = defaultCookie;
}
else {
throw new Error(`Assign the 'user_agent' in the instance of the class to use this site.`);
}
}
// Set cookie dan agent
if (this._options.cookie_value) {
const jar = new tough_cookie_1.CookieJar();
jar.setCookie(this._options.cookie_value, this._options.site);
const httpsAgent = new http_1.HttpsCookieAgent({ cookies: { jar } });
__classPrivateFieldSet(this, _NHentai_axios, axios_1.default.create({ httpsAgent }), "f");
}
if (this._options.user_agent)
__classPrivateFieldGet(this, _NHentai_axios, "f").defaults.headers.common['User-Agent'] =
this._options.user_agent;
}
/**
* Ganti cookie secara dinamis saat runtime
*/
setCookie(cookie) {
const jar = new tough_cookie_1.CookieJar();
jar.setCookieSync(cookie, this._options.site);
const httpsAgent = new http_1.HttpsCookieAgent({ cookies: { jar } });
__classPrivateFieldSet(this, _NHentai_axios, axios_1.default.create({ httpsAgent }), "f");
if (this._options.user_agent)
__classPrivateFieldGet(this, _NHentai_axios, "f").defaults.headers.common['User-Agent'] =
this._options.user_agent;
this._options.cookie_value = cookie;
}
/**
* Ganti user-agent secara dinamis
*/
setUserAgent(ua) {
__classPrivateFieldGet(this, _NHentai_axios, "f").defaults.headers.common['User-Agent'] = ua;
this._options.user_agent = ua;
}
}
exports.NHentai = NHentai;
_NHentai_axios = new WeakMap();