Browse Source

Change my_request to be more clean and try to fix the login issue.

Godzil 4 years ago
parent
commit
376ff09632
2 changed files with 165 additions and 174 deletions
  1. 9 9
      src/episode.ts
  2. 156 165
      src/my_request.ts

+ 9 - 9
src/episode.ts

@@ -336,15 +336,15 @@ function scrapePlayer(config: IConfig, address: string, id: number, done: (err:
     return done(new Error('Invalid address.'));
   }
 
-  my_request.post(config, {
-    form: {
-      current_page: address,
-      video_format: config.video_format,
-      video_quality: config.video_quality,
-      media_id: id
-    },
-    url: url[1] + '/xml/?req=RpcApiVideoPlayer_GetStandardConfig&media_id=' + id,
-  }, (err, result) =>
+  const postForm = {
+    current_page: address,
+    video_format: config.video_format,
+    video_quality: config.video_quality,
+    media_id: id
+  };
+
+  my_request.post(config, url[1] + '/xml/?req=RpcApiVideoPlayer_GetStandardConfig&media_id=' + id, postForm,
+    (err, result) =>
   {
     if (err)
     {

+ 156 - 165
src/my_request.ts

@@ -22,26 +22,10 @@ let isPremium = false;
 
 let j: request.CookieJar;
 
-const defaultHeaders =
-{
-  'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
-  'Connection': 'keep-alive',
-  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
-  'Referer': 'https://www.crunchyroll.com/login',
-  'Cache-Control': 'private',
-  'Accept-Language': 'en-US,en;q=0.9'
-};
-
-const defaultOptions =
-{
-  followAllRedirects: true,
-  decodeEmails: true,
-  challengesToSolve: 3,
-  gzip: true,
-};
-
 // tslint:disable-next-line:no-var-requires
-const cloudscraper = require('cloudscraper').defaults(defaultOptions);
+import cloudscraper = require('cloudscraper');
+let currentOptions: any;
+let optionsSet = false;
 
 function AuthError(msg: string): IAuthError
 {
@@ -98,19 +82,14 @@ function APIlogin(config: IConfig, sessionId: string, user: string, pass: string
   });
 }
 
-function checkIfUserIsAuth(config: IConfig, done: (err: Error) => void): void
+function checkIfUserIsAuth(config: IConfig, done: (err: any) => void): void
 {
-  if (j === undefined)
-  {
-    loadCookies(config);
-  }
-
   /**
    * The main page give us some information about the user
    */
   const url = 'http://www.crunchyroll.com/';
 
-  cloudscraper.get({gzip: true, uri: url}, (err: Error, rep: string, body: string) =>
+  cloudscraper.get(url, getOptions(config, null), (err: any, rep: Response, body: string) =>
   {
     if (err)
     {
@@ -204,24 +183,14 @@ export function eatCookies(config: IConfig)
 
 export function getUserAgent(): string
 {
-  return defaultHeaders['User-Agent'];
+  return currentOptions.headers['User-Agent'];
 }
 
 /**
  * Performs a GET request for the resource.
  */
-export function get(config: IConfig, options: string|any, done: (err: any, result?: string) => void)
+export function get(config: IConfig, url: string, done: (err: any, result?: string) => void)
 {
-  if (j === undefined)
-  {
-    loadCookies(config);
-  }
-
-  if (config.userAgent)
-  {
-    defaultHeaders['User-Agent'] = config.userAgent;
-  }
-
   authenticate(config, (err) =>
   {
     if (err)
@@ -229,7 +198,7 @@ export function get(config: IConfig, options: string|any, done: (err: any, resul
       return done(err);
     }
 
-    cloudscraper.get(modify(options), (error: any, response: any, body: any) =>
+    cloudscraper.get(url, getOptions(config, null), (error: any, response: any, body: any) =>
     {
       if (error) return done(error);
 
@@ -241,18 +210,8 @@ export function get(config: IConfig, options: string|any, done: (err: any, resul
 /**
  * Performs a POST request for the resource.
  */
-export function post(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void)
+export function post(config: IConfig, url: string, form: any, done: (err: any, result?: string) => void)
 {
-  if (j === undefined)
-  {
-    loadCookies(config);
-  }
-
-  if (config.userAgent)
-  {
-    defaultHeaders['User-Agent'] = config.userAgent;
-  }
-
   authenticate(config, (err) =>
   {
     if (err)
@@ -260,7 +219,7 @@ export function post(config: IConfig, options: request.Options, done: (err: Erro
       return done(err);
     }
 
-    cloudscraper.post(modify(options), (error: Error, response: any, body: any) =>
+    cloudscraper.post(url, getOptions(config, form), (error: Error, response: any, body: any) =>
     {
       if (error)
       {
@@ -271,78 +230,53 @@ export function post(config: IConfig, options: request.Options, done: (err: Erro
   });
 }
 
-/**
- * Authenticates using the configured pass and user.
- */
-function authenticate(config: IConfig, done: (err: Error) => void)
+function authUsingCookies(config: IConfig, done: (err: any) => void)
 {
-  if (isAuthenticated)
-  {
-    return done(null);
-  }
+  j.setCookie(request.cookie('c_userid=' + config.crUserId + '; Domain=crunchyroll.com; HttpOnly; hostOnly=false;'),
+    CR_COOKIE_DOMAIN);
+  j.setCookie(request.cookie('c_userkey=' + config.crUserKey + '; Domain=crunchyroll.com; HttpOnly; hostOnly=false;'),
+    CR_COOKIE_DOMAIN);
 
-  /* First of all, check if the user is not already logged via the cookies */
-  checkIfUserIsAuth(config, (errCheckAuth) =>
+  checkIfUserIsAuth(config, (errCheckAuth2) =>
   {
     if (isAuthenticated)
     {
       return done(null);
     }
-
-    /* So if we are here now, that mean we are not authenticated so do as usual */
-    if ((!config.logUsingApi && !config.logUsingCookie) && (!config.pass || !config.user))
+    else
     {
-      log.error('You need to give login/password to use Crunchy');
-      process.exit(-1);
+      return done(errCheckAuth2);
     }
+  });
+}
 
-    log.info('Seems we are not currently logged. Let\'s login!');
+function authUsingApi(config: IConfig, done: (err: any) => void)
+{
+  if (!config.pass || !config.user)
+  {
+    log.error('You need to give login/password to use Crunchy');
+    process.exit(-1);
+  }
 
-    if (config.logUsingApi)
-    {
-      if (config.crDeviceId === undefined)
-      {
-        config.crDeviceId = uuid.v4();
-      }
+  if (config.crDeviceId === undefined)
+  {
+    config.crDeviceId = uuid.v4();
+  }
 
-      if (!config.crSessionUrl || !config.crDeviceType || !config.crAPIVersion ||
-          !config.crLocale || !config.crLoginUrl)
-      {
-        return done(AuthError('Invalid API configuration, please check your config file.'));
-      }
+  if (!config.crSessionUrl || !config.crDeviceType || !config.crAPIVersion ||
+    !config.crLocale || !config.crLoginUrl)
+  {
+    return done(AuthError('Invalid API configuration, please check your config file.'));
+  }
 
-      startSession(config)
-      .then((sessionId: string) =>
-      {
-        // defaultHeaders['Cookie'] = `sess_id=${sessionId}; c_locale=enUS`;
-        return APIlogin(config, sessionId, config.user, config.pass);
-      })
-      .then((userData) =>
-      {
-        checkIfUserIsAuth(config, (errCheckAuth2) =>
-        {
-          if (isAuthenticated)
-          {
-            return done(null);
-          }
-          else
-          {
-            return done(errCheckAuth2);
-          }
-        });
-      })
-      .catch((errInChk) =>
-      {
-        return done(AuthError(errInChk.message));
-      });
-    }
-    else if (config.logUsingCookie)
+  startSession(config)
+    .then((sessionId: string) =>
+    {
+      // defaultHeaders['Cookie'] = `sess_id=${sessionId}; c_locale=enUS`;
+      return APIlogin(config, sessionId, config.user, config.pass);
+    })
+    .then((userData) =>
     {
-      j.setCookie(request.cookie('c_userid=' + config.crUserId + '; Domain=crunchyroll.com; HttpOnly; hostOnly=false;'),
-                  CR_COOKIE_DOMAIN);
-      j.setCookie(request.cookie('c_userkey=' + config.crUserKey + '; Domain=crunchyroll.com; HttpOnly; hostOnly=false;'),
-                  CR_COOKIE_DOMAIN);
-
       checkIfUserIsAuth(config, (errCheckAuth2) =>
       {
         if (isAuthenticated)
@@ -354,80 +288,137 @@ function authenticate(config: IConfig, done: (err: Error) => void)
           return done(errCheckAuth2);
         }
       });
-    }
-    else
+    })
+    .catch((errInChk) =>
     {
-      /* First get https://www.crunchyroll.com/login to get the login token */
-      const options =
-      {
-        // jar: j,
-        uri: 'https://www.crunchyroll.com/login'
-      };
+      return done(AuthError(errInChk.message));
+    });
+}
 
-      cloudscraper.get(options, (err: Error, rep: string, body: string) =>
-      {
-        if (err) return done(err);
+function authUsingForm(config: IConfig, done: (err: any) => void)
+{
+  /* So if we are here now, that mean we are not authenticated so do as usual */
+  if (!config.pass || !config.user)
+  {
+    log.error('You need to give login/password to use Crunchy');
+    process.exit(-1);
+  }
 
-        const $ = cheerio.load(body);
+  /* First get https://www.crunchyroll.com/login to get the login token */
+  cloudscraper.get('https://www.crunchyroll.com/login', getOptions(config, null), (err: any, rep: Response, body: string) =>
+  {
+    if (err) return done(err);
 
-        /* Get the token from the login page */
-        const token = $('input[name="login_form[_token]"]').attr('value');
-        if (token === '')
-        {
-            return done(AuthError('Can\'t find token!'));
-        }
+    const $ = cheerio.load(body);
 
-        /* Now call the page again with the token and credentials */
-        const options =
-        {
-          form:
-          {
+    /* Get the token from the login page */
+    const token = $('input[name="login_form[_token]"]').attr('value');
+    if (token === '')
+    {
+      return done(AuthError('Can\'t find token!'));
+    }
+
+    /* Now call the page again with the token and credentials */
+    const paramForm =
+    {
             'login_form[name]': config.user,
             'login_form[password]': config.pass,
             'login_form[redirect_url]': '/',
             'login_form[_token]': token
-          },
-          // jar: j,
-          url: 'https://www.crunchyroll.com/login'
-        };
+    };
+
+    cloudscraper.post('https://www.crunchyroll.com/login', getOptions(config, paramForm), (err: any, rep: Response, body: string) =>
+    {
+      if (err)
+      {
+        return done(err);
+      }
 
-        cloudscraper.post(options, (err: Error, rep: string, body: string) =>
+      /* Now let's check if we are authentificated */
+      checkIfUserIsAuth(config, (errCheckAuth2) =>
+      {
+        if (isAuthenticated)
+        {
+          return done(null);
+        }
+        else
         {
-          if (err)
-          {
-              return done(err);
-          }
-
-          /* Now let's check if we are authentificated */
-          checkIfUserIsAuth(config, (errCheckAuth2) =>
-          {
-            if (isAuthenticated)
-            {
-              return done(null);
-            }
-            else
-            {
-              return done(errCheckAuth2);
-            }
-          });
-        });
+          return done(errCheckAuth2);
+        }
       });
-    }
+    });
   });
 }
 
 /**
- * Modifies the options to use the authenticated cookie jar.
+ * Authenticates using the configured pass and user.
  */
-function modify(options: string|any): any
+function authenticate(config: IConfig, done: (err: any) => void)
 {
-  if (typeof options !== 'string')
+  if (isAuthenticated)
   {
-    options.jar = j;
-    return options;
+    return done(null);
   }
-  return {
-    jar: j,
-    url: options.toString(),
-  };
+
+  /* First of all, check if the user is not already logged via the cookies */
+  checkIfUserIsAuth(config, (errCheckAuth) =>
+  {
+    if (isAuthenticated)
+    {
+      return done(null);
+    }
+
+    log.info('Seems we are not currently logged. Let\'s login!');
+
+    if (config.logUsingApi)
+    {
+      return authUsingApi(config, done);
+    }
+    else if (config.logUsingCookie)
+    {
+      return authUsingCookies(config, done);
+    }
+    else
+    {
+      return authUsingForm(config, done);
+    }
+  });
 }
+
+function getOptions(config: IConfig, form: any)
+{
+  if (!optionsSet)
+  {
+    currentOptions = {};
+    currentOptions.headers = {};
+
+    if (config.userAgent)
+    {
+      currentOptions.headers['User-Agent'] = config.userAgent;
+    }
+    else
+    {
+      currentOptions.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0';
+    }
+
+    if (j === undefined)
+    {
+      loadCookies(config);
+    }
+
+    currentOptions.decodeEmails = true;
+    currentOptions.jar = j;
+
+    optionsSet = true;
+  }
+
+  currentOptions.form = {};
+
+  if (form !== null)
+  {
+    currentOptions.form = form;
+  }
+
+
+  return currentOptions;
+}