import { JSDOM } from 'jsdom'; import { RequestInit, Response } from 'node-fetch'; import RenaiError, { Errors } from '../../types/error'; import fetch from './web-crawler'; const url = 'https://nhentai.net/'; const paths = { books: 'g/', login: 'login/', favorites: 'favorites/', }; const usernameInput = 'username_or_email'; const passwordInput = 'password'; interface ILoginMeta { [key: string]: string; } interface ILoginAuth { [usernameInput]: string; [passwordInput]: string; } interface ILoginParams extends ILoginMeta, ILoginAuth {} function login(name: string, password: string): Promise { return getLoginMeta() .then((meta: ILoginMeta) => { const loginParams: ILoginParams = { ...meta, ...{ // tslint:disable-next-line: object-literal-sort-keys username_or_email: name, password, }, }; return postNHentai(paths.login, { body: encodeURI( Object.keys(loginParams) .map((key: keyof ILoginParams) => `${key}=${loginParams[key]}`) .join('&') ), headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); }) .then(() => {}) .catch(() => Promise.reject(new RenaiError(Errors.ELOGINFAIL))); } function getNHentai(path: string): Promise { return fetch(`${url}${path}`) .then((res: Response) => { return res.text(); }) .then((text: string) => { const { document } = new JSDOM(text).window; return document; }); } function postNHentai(path: string, init: RequestInit = {}): Promise { return fetch(`${url}${path}`, { ...init, ...{ method: 'post' } }); } function getLoginMeta(): Promise { return getNHentai(paths.login).then((document: Document) => { // tslint:disable-next-line: prefer-for-of for (let i = 0; i < document.forms.length; i++) { const form: HTMLFormElement = document.forms[i]; const valueStore: ILoginMeta = {}; let isLoginForm = false; // tslint:disable-next-line: prefer-for-of for (let j = 0; j < form.elements.length; j++) { const input = form.elements[j]; const name = input.getAttribute('name'); if (name === usernameInput || name === passwordInput) { isLoginForm = true; } else if (name) { valueStore[name] = input.getAttribute('value'); } } if (isLoginForm) { return valueStore; } } return Promise.reject(new RenaiError(Errors.ENOLOGIN)); }); } export default { login, };