Guest User

Untitled

a guest
Jul 6th, 2018
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.70 KB | None | 0 0
  1. import { Promise } from 'es6-promise';
  2. import * as request from 'request-promise';
  3. import * as md5 from 'md5';
  4. import { URL } from 'url';
  5.  
  6. // TODO: TRY ADDING PROXIES
  7. export class TextNowRegistration {
  8. private readonly API_BASE = 'https://api.textnow.me/api2.0';
  9. private readonly API_SECRET =
  10. '851a9f2bad15843c1a922890c061830e8ce50e86840575d17e61ef0becdc3576';
  11. private readonly SITE_KEY = '6LcU4gkTAAAAAM4SyYTmXlKvqwWLuaFLy-30rzBn';
  12. private readonly AREA_CODE = 540;
  13. private readonly CAPTCHA_SERVICE_KEY = '7c8145707915f4ba0cb32db0747b75d0';
  14.  
  15. private username: string;
  16. private password: string;
  17. private email: string;
  18. private clientId: string;
  19. private captchaToken: string;
  20. private captchaLink: string;
  21. // private onCaptchaReceived: (siteKey: string) => Promise<string>;
  22.  
  23. constructor(
  24. username: string,
  25. password: string,
  26. email: string,
  27. // onCaptchaReceived: (siteKey: string) => Promise<string>,
  28. ) {
  29. this.username = username;
  30. this.password = password;
  31. this.email = email;
  32. // this.onCaptchaReceived = onCaptchaReceived;
  33. this.clientId = null;
  34. this.captchaToken = null;
  35. this.captchaLink = null;
  36. }
  37.  
  38. private buildSignature(method: string, uri: string, json: any): string {
  39. // strip base uri
  40. let path = uri.replace(this.API_BASE + '/', '');
  41.  
  42. // prepare json payload
  43. let stringified = '';
  44. if (json) {
  45. stringified = JSON.stringify(json);
  46. }
  47.  
  48. // hash the payload
  49. return md5(this.API_SECRET + method + path + stringified);
  50. }
  51.  
  52. private buildUrl(path: string): string {
  53. return this.API_BASE + path;
  54. }
  55.  
  56. public register(): Promise<string> {
  57. return new Promise<string>((resolve, reject) => {
  58. this.checkUsername()
  59. .then((usernameExists: boolean) => {
  60. // check fif username already exists
  61. if (usernameExists)
  62. throw new Error(
  63. 'the user could not be created as the username is not available',
  64. );
  65. return this.checkEmail();
  66. })
  67. .then((emailExists: boolean) => {
  68. // check if email already exists
  69. if (emailExists)
  70. throw new Error(
  71. 'the user could not be created as the email is already registered',
  72. );
  73. return this.signUp();
  74. })
  75. .then(() => {
  76. return this.validateCaptcha();
  77. })
  78. .then(() => {
  79. return this.claimPhoneNumber(this.AREA_CODE);
  80. })
  81. .then((phoneNumber: string) => {
  82. return resolve(phoneNumber);
  83. })
  84. .catch(reject);
  85. });
  86. }
  87.  
  88. private checkUsername(): Promise<boolean> {
  89. return new Promise<boolean>((resolve, reject) => {
  90. // prepare json request
  91. this.makeRequest({
  92. uri: this.buildUrl(
  93. `/users/${
  94. this.username
  95. }?idfa=&idfv=&client_type=TN_IOS_FREE`,
  96. ),
  97. method: 'HEAD',
  98. })
  99. .then((data: any) => {
  100. console.log('Username is taken!');
  101. return resolve(true);
  102. })
  103. .catch((err: any) => {
  104. console.log('Username is not taken.');
  105. console.log(err)
  106. return resolve(false);
  107. });
  108. });
  109. }
  110.  
  111. private sleep(ms) {
  112. return new Promise(resolve => setTimeout(resolve, ms));
  113. }
  114.  
  115. private onCaptchaReceived(siteKey): Promise<string> {
  116. return new Promise<string>((resolve, reject) => {
  117. // TODO: ADD PROXY SUPPORT
  118. let getURL = `http://2captcha.com/in.php?key=${
  119. this.CAPTCHA_SERVICE_KEY
  120. }&method=userrecaptcha&googlekey=${siteKey}&pageurl=${
  121. this.captchaLink
  122. }`;
  123. this.makeRequest({
  124. uri: getURL,
  125. method: 'GET',
  126. })
  127. .then((tokenKey: string) => {
  128. if (tokenKey.substr(0, 2) != 'OK') {
  129. return resolve('CAPTCHA NOT RECEIVED');
  130. }
  131. let captchaID = tokenKey.substr(3);
  132. let curToken = undefined;
  133.  
  134. for (let i = 0; i < 24; i++) {
  135. this.makeRequest({
  136. uri: `http://2captcha.com/res.php?key=${
  137. this.CAPTCHA_SERVICE_KEY
  138. }&action=get&id=${captchaID}`,
  139. method: 'GET',
  140. }).then((token: string) => {
  141. if (token.substr(0, 2) == 'OK') {
  142. curToken = token.substring(3);
  143. console.log(
  144. 'CAPTCHA TOKEN RECEIVED: ' +
  145. token.substr(0, 10),
  146. );
  147. resolve();
  148. }
  149. });
  150. this.sleep(5);
  151. }
  152. return resolve(curToken);
  153. })
  154. .catch(reject);
  155. });
  156. }
  157.  
  158. private checkEmail(): Promise<boolean> {
  159. return new Promise<boolean>((resolve, reject) => {
  160. // prepare json request
  161. this.makeRequest({
  162. uri: this.buildUrl(
  163. `/emails/${this.email.replace(
  164. '@',
  165. '%40'
  166. )}?idfa=&idfv=&client_type=TN_IOS_FREE`,
  167. ),
  168. method: 'HEAD',
  169. })
  170. .then((data: any) => {
  171. console.log('Email is taken!');
  172. return resolve(true);
  173. })
  174. .catch((err: any) => {
  175. console.log('Email is not taken.');
  176. // console.log(err)
  177. return resolve(false);
  178. });
  179. });
  180. }
  181.  
  182. private signUp(): Promise<string> {
  183. return new Promise<string>((resolve, reject) => {
  184. // prepare json request
  185. let bonusInfo = {
  186. TimeZone: '-25200',
  187. time: 1530670138,
  188. Language: 'en-US',
  189. ga: 'GA1.2.196167121.1528432309',
  190. };
  191. let body = {
  192. dob: '2018-07-05',
  193. password: this.password,
  194. email: this.email,
  195. bonus_info: JSON.stringify(bonusInfo),
  196. };
  197. console.log('Made signup request...');
  198. // make the code verification request
  199. this.makeRequest({
  200. uri: this.buildUrl(
  201. `/users/${
  202. this.username
  203. }?idfa=&idfv=&client_type=TN_IOS_FREE`,
  204. ),
  205. method: 'PUT',
  206. body: body,
  207. })
  208. // TODO: CONVERT TO PYTHON CODE
  209. .then((data: any) => {
  210. // check if registration was successfull
  211. if (!data.result || !data.result.id) {
  212. console.log('Could not register user!');
  213. throw new Error(
  214. 'there was an error trying to register the user',
  215. );
  216. }
  217. // the user was successfully created
  218. this.clientId = data.result.id;
  219. this.captchaLink = data.result.captcha_link;
  220. let url = new URL(data.result.captcha_link);
  221. this.captchaToken = url.searchParams.get('token');
  222. console.log('Signed up!');
  223. return resolve(this.clientId);
  224. })
  225. .catch(reject => {
  226. console.log(reject);
  227. });
  228. });
  229. }
  230.  
  231. private claimPhoneNumber(areaCode: number): Promise<string> {
  232. return new Promise<string>((resolve, reject) => {
  233. // make the phone number claim request
  234. this.makeRequest({
  235. uri: this.buildUrl(
  236. `/users/${this.username}/phone?idfa=&idfv=&client_id=${
  237. this.clientId
  238. }&client_type=TN_IOS_FREE`,
  239. ),
  240. method: 'PUT',
  241. body: {
  242. area_code: areaCode,
  243. },
  244. })
  245. .then((phone: any) => {
  246. const phoneNumber: string = '+1' + phone;
  247. console.log('Phone number claimed: ' + phoneNumber);
  248. return resolve(phoneNumber);
  249. })
  250. .catch(reject);
  251. });
  252. }
  253.  
  254. private validateCaptcha(): Promise<void> {
  255. return new Promise<void>((resolve, reject) => {
  256. // wait for the captcha to be returned
  257. this.onCaptchaReceived(this.SITE_KEY)
  258. .then((token: string) => {
  259. // prepare json payload
  260. let body = {
  261. u: this.captchaToken,
  262. c: token,
  263. };
  264. // prepare request
  265. return request({
  266. uri: 'https://www.textnow.com/api/identity/validate',
  267. method: 'POST',
  268. form: {
  269. json: JSON.stringify(body),
  270. },
  271. json: true,
  272. headers: {
  273. 'User-Agent':
  274. 'TextNowSwift-Free/8.29.0 (iPhone; iOS 12.0; Scale/2.00)',
  275. },
  276. });
  277. })
  278. .then((data: any) => {
  279. // check if the validation was successful
  280. if (data.error_code !== null) {
  281. console.log('Could not validate captcha!');
  282. throw new Error(
  283. 'there was an error validating the captcha',
  284. );
  285. }
  286. console.log('Successfully validated captcha!');
  287. // the validation was successful
  288. return resolve();
  289. })
  290. .catch(reject);
  291. });
  292. }
  293.  
  294. private makeRequest(
  295. options: request.OptionsWithUri,
  296. ): request.RequestPromise {
  297. // modify and add required headers
  298. //options.proxy = 'http://localhost:8888';
  299. options.json = true;
  300. options.headers = {
  301. 'User-Agent':
  302. 'TextNowSwift-Free/8.29.0 (iPhone; iOS 12.0; Scale/2.00)',
  303. 'Accept-Language': 'en-US;q=1',
  304. };
  305. // add signature
  306. options.uri =
  307. options.uri +
  308. '&signature=' +
  309. this.buildSignature(
  310. options.method,
  311. options.uri as string,
  312. options.body,
  313. );
  314. // make request
  315. return request(options);
  316. }
  317. }
  318.  
  319. new TextNowRegistration(
  320. 'USERNAsdfOSNGFDS',
  321. 'abc1ffg23df',
  322. 'EMAILsdfdsfGFDS@gmail.com',
  323. ).register();
Add Comment
Please, Sign In to add comment