From b96efacbd23462d23f5f437afc3a41eaafefb7eb Mon Sep 17 00:00:00 2001 From: Godzil Date: Tue, 7 Feb 2017 20:22:01 +0000 Subject: [PATCH] - Revert login using the token method - Use the cloudscraper layer on top of request to pass through the cloudfare browser check - switch from tsd to typings --- package.json | 7 ++-- src/request.ts | 88 ++++++++++++++++++++++++++++++++++---------------- tsd.json | 33 ------------------- typings.json | 13 ++++++++ 4 files changed, 77 insertions(+), 64 deletions(-) delete mode 100644 tsd.json create mode 100644 typings.json diff --git a/package.json b/package.json index 5a9a03e..5df6954 100644 --- a/package.json +++ b/package.json @@ -19,19 +19,20 @@ "dependencies": { "big-integer": "1.4.4", "cheerio": "0.22.0", + "cloudscraper": "1.4.1", "commander": "2.6.0", "mkdirp": "0.5.0", "request": "2.74.0", "xml2js": "0.4.5" }, "devDependencies": { - "tsd": "0.5.7", + "typing": "2.1.0", "tslint": "2.3.0-beta", "typescript": "1.5.0-beta" }, "scripts": { - "prepublish": "npm run tsd && tsc", + "prepublish": "npm run types && tsc", "test": "node ts --only-test", - "tsd": "tsd reinstall -o -s" + "types": "typings install" } } diff --git a/src/request.ts b/src/request.ts index df795a9..07793af 100644 --- a/src/request.ts +++ b/src/request.ts @@ -1,8 +1,8 @@ 'use strict'; import request = require('request'); import cheerio = require('cheerio'); -import log = require('./log'); - +import log = require('./log'); +var cloudscraper = require('cloudscraper'); var isAuthenticated = false; var isPremium = false; @@ -17,7 +17,7 @@ var defaultHeaders: request.Headers = { export function get(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) { authenticate(config, err => { if (err) return done(err); - request.get(modify(options), (err: Error, response: any, body: any) => { + cloudscraper.request(modify(options, 'GET'), (err: Error, response: any, body: any) => { if (err) return done(err); done(null, typeof body === 'string' ? body : String(body)); }); @@ -30,7 +30,7 @@ export function get(config: IConfig, options: request.Options, done: (err: Error export function post(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) { authenticate(config, err => { if (err) return done(err); - request.post(modify(options), (err: Error, response: any, body: any) => { + cloudscraper.request(modify(options, 'POST'), (err: Error, response: any, body: any) => { if (err) return done(err); done(null, typeof body === 'string' ? body : String(body)); }); @@ -49,41 +49,72 @@ function authenticate(config: IConfig, done: (err: Error) => void) { headers: defaultHeaders, jar: true, gzip: false, - url: 'https://www.crunchyroll.com/?a=formhandler&formname=RpcApiUser_Login&name=' + config.user + '&password=' + config.pass + method: 'GET', + url: 'https://www.crunchyroll.com/login' }; - request(options, (err: Error, rep: string, body: string) => + // request(options, (err: Error, rep: string, body: string) => + cloudscraper.request(options, (err: Error, rep: string, body: string) => { if (err) return done(err); - /* The page return with a meta based redirection, as we wan't to check that everything is fine, reload - * the main page. A bit convoluted, but more sure. - */ + + var $ = cheerio.load(body); + + /* Get the token from the login page */ + var token = $('input[name="login_form[_token]"]').attr('value'); + if (token === '') return done(new Error('Can`t find token!')); + var options = { headers: defaultHeaders, + form: + { + 'login_form[redirect_url]': '/', + 'login_form[name]': config.user, + 'login_form[password]': config.pass, + 'login_form[_token]': token + }, jar: true, - url: 'http://www.crunchyroll.com/' + gzip: false, + method: 'POST', + url: 'https://www.crunchyroll.com/login' }; - request(options, (err: Error, rep: string, body: string) => + // request.post(options, (err: Error, rep: string, body: string) => + cloudscraper.request(options, (err: Error, rep: string, body: string) => { if (err) return done(err); - var $ = cheerio.load(body); - /* Check if auth worked */ - var regexps = /ga\(\'set\', \'dimension[5-8]\', \'([^']*)\'\);/g; - var dims = regexps.exec($('script').text()); - for (var i = 1; i < 5; i++) + /* The page return with a meta based redirection, as we wan't to check that everything is fine, reload + * the main page. A bit convoluted, but more sure. + */ + var options = { - if ((dims[i] !== undefined) && (dims[i] !== '') && (dims[i] !== 'not-registered')) { isAuthenticated = true; } - if ((dims[i] === 'premium') || (dims[i] === 'premiumplus')) { isPremium = true; } - } - if (isAuthenticated === false) + headers: defaultHeaders, + jar: true, + url: 'http://www.crunchyroll.com/', + method: 'GET' + }; + + cloudscraper.request(options, (err: Error, rep: string, body: string) => { - var error = $('ul.message, li.error').text(); - return done(new Error('Authentication failed: ' + error)); - } - if (isPremium === false) { log.warn('Do not use this app without a premium account.'); } - else { log.info('You have a premium account! Good!'); } - done(null); + if (err) return done(err); + var $ = cheerio.load(body); + /* Check if auth worked */ + var regexps = /ga\(\'set\', \'dimension[5-8]\', \'([^']*)\'\);/g; + var dims = regexps.exec($('script').text()); + for (var i = 1; i < 5; i++) + { + if ((dims[i] !== undefined) && (dims[i] !== '') && (dims[i] !== 'not-registered')) { isAuthenticated = true; } + if ((dims[i] === 'premium') || (dims[i] === 'premiumplus')) { isPremium = true; } + } + if (isAuthenticated === false) + { + var error = $('ul.message, li.error').text(); + return done(new Error('Authentication failed: ' + error)); + } + if (isPremium === false) { log.warn('Do not use this app without a premium account.'); } + else { log.info('You have a premium account! Good!'); } + done(null); + }); }); }); } @@ -91,11 +122,12 @@ function authenticate(config: IConfig, done: (err: Error) => void) { /** * Modifies the options to use the authenticated cookie jar. */ -function modify(options: string|request.Options): request.Options { +function modify(options: string|request.Options, reqMethod: string): request.Options { if (typeof options !== 'string') { options.jar = true; options.headers = defaultHeaders; + options.method = reqMethod; return options; } - return {jar: true, headers: defaultHeaders, url: options.toString()}; + return { jar: true, headers: defaultHeaders, url: options.toString(), method: reqMethod}; } diff --git a/tsd.json b/tsd.json deleted file mode 100644 index 50208cc..0000000 --- a/tsd.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "version": "v4", - "repo": "borisyankov/DefinitelyTyped", - "ref": "master", - "path": "typings", - "bundle": "typings/tsd.d.ts", - "installed": { - "node/node.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "commander/commander.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "xml2js/xml2js.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "cheerio/cheerio.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "mkdirp/mkdirp.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "request/request.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "big-integer/big-integer.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - }, - "form-data/form-data.d.ts": { - "commit": "3882d337bb0808cde9fe4c08012508a48c135482" - } - } -} diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..1382668 --- /dev/null +++ b/typings.json @@ -0,0 +1,13 @@ +{ + "name": "crunchy", + "globalDependencies": { + "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "commander": "github:DefinitelyTyped/DefinitelyTyped/commander/commander.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "xml2js": "github:DefinitelyTyped/DefinitelyTyped/xml2js/xml2js.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "cheerio": "github:DefinitelyTyped/DefinitelyTyped/cheerio/cheerio.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "mkdirp": "github:DefinitelyTyped/DefinitelyTyped/mkdirp/mkdirp.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "request": "github:DefinitelyTyped/DefinitelyTyped/request/request.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "big-integer": "github:DefinitelyTyped/DefinitelyTyped/big-integer/big-integer.d.ts#3882d337bb0808cde9fe4c08012508a48c135482", + "form-data": "github:DefinitelyTyped/DefinitelyTyped/form-data/form-data.d.ts#3882d337bb0808cde9fe4c08012508a48c135482" + } +}