request.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. 'use strict';
  2. import request = require('request');
  3. import cheerio = require('cheerio');
  4. var isAuthenticated = false;
  5. var isPremium = false;
  6. var defaultHeaders:request.Headers = {
  7. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
  8. 'Connection': 'keep-alive'
  9. };
  10. /**
  11. * Performs a GET request for the resource.
  12. */
  13. export function get(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
  14. authenticate(config, err => {
  15. if (err) return done(err);
  16. request.get(modify(options), (err: Error, response: any, body: any) => {
  17. if (err) return done(err);
  18. done(null, typeof body === 'string' ? body : String(body));
  19. });
  20. });
  21. }
  22. /**
  23. * Performs a POST request for the resource.
  24. */
  25. export function post(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
  26. authenticate(config, err => {
  27. if (err) return done(err);
  28. request.post(modify(options), (err: Error, response: any, body: any) => {
  29. if (err) return done(err);
  30. done(null, typeof body === 'string' ? body : String(body));
  31. });
  32. });
  33. }
  34. /**
  35. * Authenticates using the configured pass and user.
  36. */
  37. function authenticate(config: IConfig, done: (err: Error) => void) {
  38. if (isAuthenticated || !config.pass || !config.user) return done(null);
  39. /* First just request the login page */
  40. var options = {
  41. headers: defaultHeaders,
  42. jar: true,
  43. url: 'https://www.crunchyroll.com/login'
  44. }
  45. request(options, (err: Error, rep: any, body: any) =>
  46. {
  47. if (err) return done(err);
  48. var $ = cheerio.load(body);
  49. /* Get the token from the login page */
  50. var token = $('input[name="login_form[_token]"]').attr("value");
  51. if (token == "") return done(new Error("Can't find token!"));
  52. var options =
  53. {
  54. headers: defaultHeaders,
  55. form:
  56. {
  57. 'login_form[redirect_url]': '/',
  58. 'login_form[name]': config.user,
  59. 'login_form[password]': config.pass,
  60. 'login_form[_token]': token,
  61. },
  62. jar: true,
  63. gzip: false,
  64. url: 'https://www.crunchyroll.com/login'
  65. };
  66. request.post(options, (err: Error, rep: string, body: string) =>
  67. {
  68. if (err) return done(err);
  69. /* The page return with a meta based redirection, as we wan't to check that everything is fine, reload
  70. * the main page. A bit convoluted, but more sure.
  71. */
  72. var options =
  73. {
  74. headers: defaultHeaders,
  75. jar: true,
  76. url: 'http://www.crunchyroll.com/'
  77. }
  78. request(options, (err: Error, rep: string, body: string) =>
  79. {
  80. if (err) return done(err);
  81. var $ = cheerio.load(body);
  82. /* Check if auth worked */
  83. var regexps = /ga\(\'set\', \'dimension[5-8]\', \'([^']*)\'\);/g
  84. var dims = regexps.exec($('script').text())
  85. for(var i = 1; i < 5; i++)
  86. {
  87. if ((dims[i] != undefined) && (dims[i] != "") && (dims[i] != "not-registered")) { isAuthenticated = true; }
  88. if ((dims[i] == "premium") || (dims[i] == "premiumplus")) { isPremium = true; }
  89. }
  90. if (isAuthenticated == false)
  91. {
  92. var error = $('ul.message, li.error').text();
  93. return done(new Error("Authentication failed: " + error));
  94. }
  95. if (isPremium == false) { console.info("Do not use this app without a premium account."); }
  96. else { console.info("You have a premium account! Good!"); }
  97. done(null);
  98. })
  99. })
  100. })
  101. }
  102. /**
  103. * Modifies the options to use the authenticated cookie jar.
  104. */
  105. function modify(options: string|request.Options): request.Options {
  106. if (typeof options !== 'string') {
  107. options.jar = true;
  108. options.headers = defaultHeaders;
  109. return options;
  110. }
  111. return {jar: true, headers: defaultHeaders, url: options.toString()};
  112. }