Browse Source

Moved MTProto to worker

master
morethanwords 4 years ago
parent
commit
93fc836f25
  1. 9
      package-lock.json
  2. 1
      package.json
  3. 3
      src/components/chatInput.ts
  4. 8
      src/components/emoticonsDropdown.ts
  5. 1
      src/components/misc.ts
  6. 5
      src/components/wrappers.ts
  7. 7
      src/lib/appManagers/apiUpdatesManager.ts
  8. 3
      src/lib/appManagers/appImManager.ts
  9. 1
      src/lib/appManagers/appMediaViewer.ts
  10. 7
      src/lib/appManagers/appMessagesManager.ts
  11. 25
      src/lib/appManagers/appPhotosManager.ts
  12. 5
      src/lib/appManagers/appSharedMediaManager.ts
  13. 3
      src/lib/appManagers/appSidebarLeft.ts
  14. 3
      src/lib/appManagers/appStickersManager.ts
  15. 3
      src/lib/appManagers/appUsersManager.ts
  16. 320
      src/lib/config.js
  17. 75
      src/lib/config.ts
  18. 46
      src/lib/crypto/crypto_methods.ts
  19. 88
      src/lib/crypto/cryptoworker.ts
  20. 11
      src/lib/filemanager.ts
  21. 41
      src/lib/idb.ts
  22. 3
      src/lib/mtproto/apiFileManager.ts
  23. 19
      src/lib/mtproto/apiManager.ts
  24. 7
      src/lib/mtproto/authorizer.ts
  25. 11
      src/lib/mtproto/dcConfigurator.ts
  26. 15
      src/lib/mtproto/mtproto.ts
  27. 41
      src/lib/mtproto/mtproto.worker.js
  28. 15
      src/lib/mtproto/mtproto_config.ts
  29. 150
      src/lib/mtproto/mtprotoworker.ts
  30. 70
      src/lib/mtproto/networker.ts
  31. 14
      src/lib/mtproto/networkerFactory.ts
  32. 16
      src/lib/mtproto/passwordManager.ts
  33. 4
      src/lib/mtproto/rsaKeysManager.ts
  34. 5
      src/lib/mtproto/schema.ts
  35. 1530
      src/lib/mtproto/tl_utils.ts
  36. 1
      src/lib/richtextprocessor.js
  37. 209
      src/lib/storage.ts
  38. 6
      src/lib/utils.js
  39. 14
      src/pages/pageAuthCode.ts
  40. 45
      src/pages/pagePassword.ts
  41. 26
      src/pages/pageSignIn.ts
  42. 3
      src/pages/pageSignUp.ts
  43. 26517
      stats.json
  44. 2
      tsconfig.json
  45. 12
      webpack.common.js

9
package-lock.json generated

@ -5633,6 +5633,15 @@
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
"dev": true "dev": true
}, },
"ifdef-loader": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/ifdef-loader/-/ifdef-loader-2.1.5.tgz",
"integrity": "sha512-GMUW5L8ZjsKRGABV3iXLdNFe2l7qFp9jeGYS55I6RNZLgQpicKxUfdH5oLDJ1cu+udb0hZiglwW6nX2kzgy86w==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0"
}
},
"iferr": { "iferr": {
"version": "0.1.5", "version": "0.1.5",
"resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",

1
package.json

@ -36,6 +36,7 @@
"fastdom": "^1.0.9", "fastdom": "^1.0.9",
"file-loader": "^4.3.0", "file-loader": "^4.3.0",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"ifdef-loader": "^2.1.5",
"install": "^0.13.0", "install": "^0.13.0",
"jest": "^24.9.0", "jest": "^24.9.0",
"leemon": "^6.2.0", "leemon": "^6.2.0",

3
src/components/chatInput.ts

@ -1,7 +1,8 @@
import Scrollable from "./scrollable"; import Scrollable from "./scrollable";
import LazyLoadQueue from "./lazyLoadQueue"; import LazyLoadQueue from "./lazyLoadQueue";
import { RichTextProcessor } from "../lib/richtextprocessor"; import { RichTextProcessor } from "../lib/richtextprocessor";
import apiManager from "../lib/mtproto/apiManager"; //import apiManager from "../lib/mtproto/apiManager";
import apiManager from "../lib/mtproto/mtprotoworker";
import appWebPagesManager from "../lib/appManagers/appWebPagesManager"; import appWebPagesManager from "../lib/appManagers/appWebPagesManager";
import appImManager from "../lib/appManagers/appImManager"; import appImManager from "../lib/appManagers/appImManager";
import { calcImageInBox, getRichValue } from "../lib/utils"; import { calcImageInBox, getRichValue } from "../lib/utils";

8
src/components/emoticonsDropdown.ts

@ -6,13 +6,15 @@ import Scrollable from "./scrollable";
import { findUpTag, whichChild, calcImageInBox } from "../lib/utils"; import { findUpTag, whichChild, calcImageInBox } from "../lib/utils";
import { RichTextProcessor } from "../lib/richtextprocessor"; import { RichTextProcessor } from "../lib/richtextprocessor";
import appStickersManager, { MTStickerSet } from "../lib/appManagers/appStickersManager"; import appStickersManager, { MTStickerSet } from "../lib/appManagers/appStickersManager";
import apiManager from '../lib/mtproto/apiManager'; //import apiManager from '../lib/mtproto/apiManager';
import CryptoWorker from '../lib/crypto/cryptoworker'; import apiManager from '../lib/mtproto/mtprotoworker';
//import CryptoWorker from '../lib/crypto/cryptoworker';
import LazyLoadQueue from "./lazyLoadQueue"; import LazyLoadQueue from "./lazyLoadQueue";
import { MTDocument, wrapSticker } from "./wrappers"; import { MTDocument, wrapSticker } from "./wrappers";
import appWebpManager from "../lib/appManagers/appWebpManager"; import appWebpManager from "../lib/appManagers/appWebpManager";
import appDocsManager from "../lib/appManagers/appDocsManager"; import appDocsManager from "../lib/appManagers/appDocsManager";
import ProgressivePreloader from "./preloader"; import ProgressivePreloader from "./preloader";
import Config from "../lib/config";
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown'; export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
@ -369,7 +371,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
reader.addEventListener('loadend', async(e) => { reader.addEventListener('loadend', async(e) => {
// @ts-ignore // @ts-ignore
const text = e.srcElement.result; const text = e.srcElement.result;
let json = await CryptoWorker.gzipUncompress<string>(text, true); let json = await apiManager.gzipUncompress<string>(text, true);
let animation = await lottieLoader.loadAnimation({ let animation = await lottieLoader.loadAnimation({
container: li, container: li,

1
src/components/misc.ts

@ -1,4 +1,5 @@
import { whichChild, findUpTag } from "../lib/utils"; import { whichChild, findUpTag } from "../lib/utils";
import Config from "../lib/config";
let rippleClickID = 0; let rippleClickID = 0;
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) { export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) {

5
src/components/wrappers.ts

@ -1,5 +1,6 @@
import appPhotosManager from '../lib/appManagers/appPhotosManager'; import appPhotosManager from '../lib/appManagers/appPhotosManager';
import CryptoWorker from '../lib/crypto/cryptoworker'; //import CryptoWorker from '../lib/crypto/cryptoworker';
import apiManager from '../lib/mtproto/mtprotoworker';
import LottieLoader from '../lib/lottieLoader'; import LottieLoader from '../lib/lottieLoader';
import appStickersManager from "../lib/appManagers/appStickersManager"; import appStickersManager from "../lib/appManagers/appStickersManager";
import appDocsManager from "../lib/appManagers/appDocsManager"; import appDocsManager from "../lib/appManagers/appDocsManager";
@ -709,7 +710,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
console.time('render sticker' + doc.id); console.time('render sticker' + doc.id);
// @ts-ignore // @ts-ignore
const text = e.srcElement.result; const text = e.srcElement.result;
let json = await CryptoWorker.gzipUncompress<string>(text, true); let json = await apiManager.gzipUncompress<string>(text, true);
console.timeEnd('decompress sticker' + doc.id); console.timeEnd('decompress sticker' + doc.id);

7
src/lib/appManagers/apiUpdatesManager.ts

@ -1,5 +1,6 @@
import apiManager from '../mtproto/apiManager'; //import apiManager from '../mtproto/apiManager';
import networkerFactory from '../mtproto/networkerFactory'; import apiManager from '../mtproto/mtprotoworker';
//import networkerFactory from '../mtproto/networkerFactory';
import { dT, $rootScope, tsNow } from "../utils"; import { dT, $rootScope, tsNow } from "../utils";
import appPeersManager from "./appPeersManager"; import appPeersManager from "./appPeersManager";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
@ -500,7 +501,7 @@ export class ApiUpdatesManager {
} }
public attach() { public attach() {
networkerFactory.setUpdatesProcessor(this.processUpdateMessage.bind(this)); apiManager.setUpdatesProcessor(this.processUpdateMessage.bind(this));
apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult: any) => { apiManager.invokeApi('updates.getState', {}, {noErrorBox: true}).then((stateResult: any) => {
this.updatesState.seq = stateResult.seq; this.updatesState.seq = stateResult.seq;
this.updatesState.pts = stateResult.pts; this.updatesState.pts = stateResult.pts;

3
src/lib/appManagers/appImManager.ts

@ -1,4 +1,5 @@
import apiManager from '../mtproto/apiManager'; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, langPack } from "../utils"; import { $rootScope, isElementInViewport, numberWithCommas, findUpClassName, formatNumber, placeCaretAtEnd, calcImageInBox, findUpTag, langPack } from "../utils";
import appUsersManager from "./appUsersManager"; import appUsersManager from "./appUsersManager";
import appMessagesManager from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";

1
src/lib/appManagers/appMediaViewer.ts

@ -1,5 +1,4 @@
import appPeersManager from "./appPeersManager"; import appPeersManager from "./appPeersManager";
import appDialogsManager from "./appDialogsManager";
import appPhotosManager from "./appPhotosManager"; import appPhotosManager from "./appPhotosManager";
import appMessagesManager from "./appMessagesManager"; import appMessagesManager from "./appMessagesManager";
import { RichTextProcessor } from "../richtextprocessor"; import { RichTextProcessor } from "../richtextprocessor";

7
src/lib/appManagers/appMessagesManager.ts

@ -17,7 +17,8 @@ import appImManager from "./appImManager";
import { MTDocument, MTPhotoSize } from "../../components/wrappers"; import { MTDocument, MTPhotoSize } from "../../components/wrappers";
import ProgressivePreloader from "../../components/preloader"; import ProgressivePreloader from "../../components/preloader";
import serverTimeManager from "../mtproto/serverTimeManager"; import serverTimeManager from "../mtproto/serverTimeManager";
import apiManager from "../mtproto/apiManager"; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import appWebPagesManager from "./appWebPagesManager"; import appWebPagesManager from "./appWebPagesManager";
import { CancellablePromise, deferredPromise } from "../polyfill"; import { CancellablePromise, deferredPromise } from "../polyfill";
@ -2925,9 +2926,9 @@ export class AppMessagesManager {
limit = Math.max(10, prerendered, unreadCount + 2); limit = Math.max(10, prerendered, unreadCount + 2);
unreadOffset = unreadCount; unreadOffset = unreadCount;
} }
} else if('Mobile' in Config) { }/* else if('Mobile' in Config) {
limit = 20; limit = 20;
} } */
} }
if(maxID > 0) { if(maxID > 0) {

25
src/lib/appManagers/appPhotosManager.ts

@ -4,7 +4,8 @@ import fileManager from '../filemanager';
import { bytesFromHex } from "../bin_utils"; import { bytesFromHex } from "../bin_utils";
import { MTPhotoSize } from "../../components/wrappers"; import { MTPhotoSize } from "../../components/wrappers";
import apiFileManager from "../mtproto/apiFileManager"; import apiFileManager from "../mtproto/apiFileManager";
import apiManager from "../mtproto/apiManager"; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
export type MTPhoto = { export type MTPhoto = {
_: 'photo' | 'photoEmpty' | string, _: 'photo' | 'photoEmpty' | string,
@ -89,7 +90,8 @@ export class AppPhotosManager {
} }
public choosePhotoSize(photo: any, width = 0, height = 0) { public choosePhotoSize(photo: any, width = 0, height = 0) {
if(Config.Navigator.retina) { //if(Config.Navigator.retina) {
if(window.devicePixelRatio > 1) {
width *= 2; width *= 2;
height *= 2; height *= 2;
} }
@ -104,8 +106,21 @@ export class AppPhotosManager {
b crop 320x320 b crop 320x320
c crop 640x640 c crop 640x640
d crop 1280x1280 */ d crop 1280x1280 */
let bestPhotoSize: MTPhotoSize = {_: 'photoSizeEmpty'}; let bestPhotoSize: MTPhotoSize = {_: 'photoSizeEmpty'};
let sizes = (photo.sizes || photo.thumbs) as typeof bestPhotoSize[];
for(let photoSize of sizes) {
if(!photoSize.w || !photoSize.h) continue;
bestPhotoSize = photoSize;
let {w, h} = calcImageInBox(photoSize.w, photoSize.h, width, height);
if(w == width || h == height) {
break;
}
}
/* let bestPhotoSize: MTPhotoSize = {_: 'photoSizeEmpty'};
let bestDiff = 0xFFFFFF; let bestDiff = 0xFFFFFF;
//console.log('choosePhotoSize', photo); //console.log('choosePhotoSize', photo);
@ -123,9 +138,9 @@ export class AppPhotosManager {
} }
//console.log('diff', diff, photoSize, bestPhotoSize); //console.log('diff', diff, photoSize, bestPhotoSize);
}); }); */
//console.log('choosing', photo, width, height, bestPhotoSize); console.log('choosing', photo, width, height, bestPhotoSize);
return bestPhotoSize; return bestPhotoSize;
} }

5
src/lib/appManagers/appSharedMediaManager.ts

@ -1,5 +0,0 @@
class AppSharedMediaManager {
}
export default new AppSharedMediaManager();

3
src/lib/appManagers/appSidebarLeft.ts

@ -2,7 +2,8 @@
import appDialogsManager from "./appDialogsManager"; import appDialogsManager from "./appDialogsManager";
import { $rootScope } from "../utils"; import { $rootScope } from "../utils";
import appImManager from "./appImManager"; import appImManager from "./appImManager";
import apiManager from "../mtproto/apiManager"; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import AppSearch, { SearchGroup } from "../../components/appSearch"; import AppSearch, { SearchGroup } from "../../components/appSearch";
class AppSidebarLeft { class AppSidebarLeft {

3
src/lib/appManagers/appStickersManager.ts

@ -1,6 +1,7 @@
import AppStorage from '../storage'; import AppStorage from '../storage';
import { MTDocument } from '../../components/wrappers'; import { MTDocument } from '../../components/wrappers';
import apiManager from '../mtproto/apiManager'; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import apiFileManager from '../mtproto/apiFileManager'; import apiFileManager from '../mtproto/apiFileManager';
import appDocsManager from './appDocsManager'; import appDocsManager from './appDocsManager';

3
src/lib/appManagers/appUsersManager.ts

@ -1,7 +1,8 @@
import { SearchIndexManager, safeReplaceObject, isObject, tsNow, copy, $rootScope } from "../utils"; import { SearchIndexManager, safeReplaceObject, isObject, tsNow, copy, $rootScope } from "../utils";
import { RichTextProcessor } from "../richtextprocessor"; import { RichTextProcessor } from "../richtextprocessor";
import appChatsManager from "./appChatsManager"; import appChatsManager from "./appChatsManager";
import apiManager from "../mtproto/apiManager"; //import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import serverTimeManager from "../mtproto/serverTimeManager"; import serverTimeManager from "../mtproto/serverTimeManager";
export class AppUsersManager { export class AppUsersManager {

320
src/lib/config.js

File diff suppressed because one or more lines are too long

75
src/lib/config.ts

File diff suppressed because one or more lines are too long

46
src/lib/crypto/crypto_methods.ts

@ -0,0 +1,46 @@
import { convertToArrayBuffer, convertToByteArray } from "../bin_utils";
export default abstract class CryptoWorkerMethods {
abstract performTaskWorker<T>(task: string, ...args: any[]): Promise<T>;
public sha1Hash(bytes: number[] | ArrayBuffer | Uint8Array): Promise<Uint8Array> {
return this.performTaskWorker<Uint8Array>('sha1-hash', bytes);
}
public sha256Hash(bytes: any) {
return this.performTaskWorker<number[]>('sha256-hash', bytes);
}
public pbkdf2(buffer: Uint8Array, salt: Uint8Array, iterations: number) {
return this.performTaskWorker<ArrayBuffer>('pbkdf2', buffer, salt, iterations);
}
public aesEncrypt(bytes: any, keyBytes: any, ivBytes: any) {
return this.performTaskWorker<ArrayBuffer>('aes-encrypt', convertToArrayBuffer(bytes),
convertToArrayBuffer(keyBytes), convertToArrayBuffer(ivBytes));
}
public aesDecrypt(encryptedBytes: any, keyBytes: any, ivBytes: any): Promise<ArrayBuffer> {
return this.performTaskWorker<ArrayBuffer>('aes-decrypt',
encryptedBytes, keyBytes, ivBytes)
.then(bytes => convertToArrayBuffer(bytes));
}
public rsaEncrypt(publicKey: {modulus: string, exponent: string}, bytes: any): Promise<number[]> {
return this.performTaskWorker<number[]>('rsa-encrypt', publicKey, bytes);
}
public factorize(bytes: any) {
bytes = convertToByteArray(bytes);
return this.performTaskWorker<[number[], number[], number]>('factorize', bytes);
}
public modPow(x: any, y: any, m: any) {
return this.performTaskWorker<number[]>('mod-pow', x, y, m);
}
public gzipUncompress<T>(bytes: ArrayBuffer, toString?: boolean) {
return this.performTaskWorker<T>('unzip', bytes, toString);
}
}

88
src/lib/crypto/cryptoworker.ts

@ -1,7 +1,5 @@
import {convertToArrayBuffer, convertToByteArray, dT} from '../bin_utils'; import {dT} from '../bin_utils';
import CryptoWorkerMethods from './crypto_methods';
// @ts-ignore
//import Worker from './crypto.worker.js';
type Task = { type Task = {
taskID: number, taskID: number,
@ -9,7 +7,7 @@ type Task = {
args: any[] args: any[]
}; };
class CryptoWorker { class CryptoWorker extends CryptoWorkerMethods {
private webWorker: Worker | boolean = false; private webWorker: Worker | boolean = false;
private taskID = 0; private taskID = 0;
private awaiting: { private awaiting: {
@ -22,13 +20,35 @@ class CryptoWorker {
private pending: Array<Task> = []; private pending: Array<Task> = [];
private debug = false; private debug = false;
private utils: {[name: string]: (...args: any[]) => any} = {};
constructor() { constructor() {
super();
console.log(dT(), 'CW constructor'); console.log(dT(), 'CW constructor');
if(window.Worker/* && 1 == 2 */) { /// #if MTPROTO_WORKER
import('./crypto.worker.js').then((CryptoWebWorker: any) => { Promise.all([
//console.log(CryptoWebWorker); import('./crypto_utils').then(utils => {
var tmpWorker = new CryptoWebWorker.default(); Object.assign(this.utils, {
'sha1-hash': utils.sha1HashSync,
'sha256-hash': utils.sha256HashSync,
'pbkdf2': utils.hash_pbkdf2,
'aes-encrypt': utils.aesEncryptSync,
'aes-decrypt': utils.aesDecryptSync,
'rsa-encrypt': utils.rsaEncrypt,
'factorize': utils.pqPrimeFactorization,
'mod-pow': utils.bytesModPow
});
}),
import('../bin_utils').then(utils => {
this.utils.unzip = utils.gzipUncompress;
})
]);
/// #else
if(window.Worker) {
import('./crypto.worker.js').then((worker: any) => {
var tmpWorker = new worker.default();
//var tmpWorker = new Worker(); //var tmpWorker = new Worker();
tmpWorker.onmessage = (e: any) => { tmpWorker.onmessage = (e: any) => {
if(!this.webWorker) { if(!this.webWorker) {
@ -41,11 +61,12 @@ class CryptoWorker {
}; };
tmpWorker.onerror = (error: any) => { tmpWorker.onerror = (error: any) => {
console.error('CW error', error/* , error.stack */); console.error('CW error', error);
this.webWorker = false; this.webWorker = false;
}; };
}); });
} }
/// #endif
} }
private finalizeTask(taskID: number, result: any) { private finalizeTask(taskID: number, result: any) {
@ -60,6 +81,9 @@ class CryptoWorker {
public performTaskWorker<T>(task: string, ...args: any[]) { public performTaskWorker<T>(task: string, ...args: any[]) {
this.debug && console.log(dT(), 'CW start', task, args); this.debug && console.log(dT(), 'CW start', task, args);
/// #if MTPROTO_WORKER
return Promise.resolve<T>(this.utils[task](...args));
/// #else
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
this.awaiting[this.taskID] = {resolve, reject, taskName: task}; this.awaiting[this.taskID] = {resolve, reject, taskName: task};
@ -75,6 +99,7 @@ class CryptoWorker {
this.taskID++; this.taskID++;
}); });
/// #endif
} }
private releasePending() { private releasePending() {
@ -86,49 +111,8 @@ class CryptoWorker {
this.pending.length = 0; this.pending.length = 0;
} }
} }
public sha1Hash(bytes: number[] | ArrayBuffer | Uint8Array): Promise<Uint8Array> {
return this.performTaskWorker<Uint8Array>('sha1-hash', bytes);
}
public sha256Hash(bytes: any) {
return this.performTaskWorker<number[]>('sha256-hash', bytes);
}
public pbkdf2(buffer: Uint8Array, salt: Uint8Array, iterations: number) {
return this.performTaskWorker<ArrayBuffer>('pbkdf2', buffer, salt, iterations);
}
public aesEncrypt(bytes: any, keyBytes: any, ivBytes: any) {
return this.performTaskWorker<ArrayBuffer>('aes-encrypt', convertToArrayBuffer(bytes),
convertToArrayBuffer(keyBytes), convertToArrayBuffer(ivBytes));
}
public aesDecrypt(encryptedBytes: any, keyBytes: any, ivBytes: any): Promise<ArrayBuffer> {
return this.performTaskWorker<ArrayBuffer>('aes-decrypt',
encryptedBytes, keyBytes, ivBytes)
.then(bytes => convertToArrayBuffer(bytes));
}
public rsaEncrypt(publicKey: {modulus: string, exponent: string}, bytes: any): Promise<number[]> {
return this.performTaskWorker<number[]>('rsa-encrypt', publicKey, bytes);
}
public factorize(bytes: any) {
bytes = convertToByteArray(bytes);
return this.performTaskWorker<[number[], number[], number]>('factorize', bytes);
}
public modPow(x: any, y: any, m: any) {
return this.performTaskWorker<number[]>('mod-pow', x, y, m);
}
public gzipUncompress<T>(bytes: ArrayBuffer, toString?: boolean) {
return this.performTaskWorker<T>('unzip', bytes, toString);
}
} }
const cryptoWorker = new CryptoWorker(); const cryptoWorker = new CryptoWorker();
(window as any).CryptoWorker = cryptoWorker; //(window as any).CryptoWorker = cryptoWorker;
export default cryptoWorker; export default cryptoWorker;

11
src/lib/filemanager.ts

@ -1,11 +1,11 @@
import {bytesToArrayBuffer, blobSafeMimeType, blobConstruct, bytesToBase64} from './bin_utils'; import {blobSafeMimeType, blobConstruct, bytesToBase64} from './bin_utils';
import 'web-streams-polyfill/ponyfill'; /* import 'web-streams-polyfill/ponyfill';
// @ts-ignore // @ts-ignore
import streamSaver from 'streamsaver'; import streamSaver from 'streamsaver';
if(window.location.href.indexOf('localhost') === -1) { if(window.location.href.indexOf('localhost') === -1) {
streamSaver.mitm = 'mitm.html'; streamSaver.mitm = 'mitm.html';
} } */
class FileManager { class FileManager {
public blobSupported = true; public blobSupported = true;
@ -104,13 +104,14 @@ class FileManager {
} }
public chooseSaveFile(fileName: string, ext: string, mimeType: string, size?: number): any { public chooseSaveFile(fileName: string, ext: string, mimeType: string, size?: number): any {
let fileStream = streamSaver.createWriteStream(fileName, { throw new Error('no writer');
/* let fileStream = streamSaver.createWriteStream(fileName, {
size: size, size: size,
writableStrategy: undefined, writableStrategy: undefined,
readableStrategy: undefined readableStrategy: undefined
}); });
let writer = fileStream.getWriter(); let writer = fileStream.getWriter();
return writer; return writer; */
} }
public getFakeFileWriter(mimeType: string, saveFileCallback: any) { public getFakeFileWriter(mimeType: string, saveFileCallback: any) {

41
src/lib/idb.ts

@ -6,28 +6,11 @@ class IdbFileStorage {
public dbStoreName = 'files'; public dbStoreName = 'files';
public dbVersion = 2; public dbVersion = 2;
public openDbPromise: Promise<IDBDatabase>; public openDbPromise: Promise<IDBDatabase>;
public storageIsAvailable: boolean; public storageIsAvailable = true;
public storeBlobsAvailable: boolean; public storeBlobsAvailable = true;
public name = 'IndexedDB'; public name = 'IndexedDB';
constructor() { constructor() {
// @ts-ignore
//window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB;
// @ts-ignore
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction;
this.storageIsAvailable = window.indexedDB !== undefined && window.IDBTransaction !== undefined;
// IndexedDB is REALLY slow without blob support in Safari 8, no point in it
if(this.storageIsAvailable &&
navigator.userAgent.indexOf('Safari') != -1 &&
navigator.userAgent.indexOf('Chrome') == -1 &&
navigator.userAgent.match(/Version\/[678]/)
) {
this.storageIsAvailable = false;
}
this.storeBlobsAvailable = this.storageIsAvailable || false;
this.openDatabase(); this.openDatabase();
} }
@ -103,8 +86,7 @@ class IdbFileStorage {
public deleteFile(fileName: string): Promise<void> { public deleteFile(fileName: string): Promise<void> {
return this.openDatabase().then((db) => { return this.openDatabase().then((db) => {
try { try {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readwrite')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
console.log('Delete file: `' + fileName + '`'); console.log('Delete file: `' + fileName + '`');
@ -137,8 +119,7 @@ class IdbFileStorage {
} }
try { try {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readwrite')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
var request = objectStore.put(blob, fileName); var request = objectStore.put(blob, fileName);
} catch(error) { } catch(error) {
@ -206,8 +187,7 @@ class IdbFileStorage {
public storagePutB64String(db: IDBDatabase, fileName: string, b64string: string) { public storagePutB64String(db: IDBDatabase, fileName: string, b64string: string) {
try { try {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readwrite')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
var request = objectStore.put(b64string, fileName); var request = objectStore.put(b64string, fileName);
} catch(error) { } catch(error) {
@ -230,8 +210,7 @@ class IdbFileStorage {
public getFile(fileName: string, size?: any): Promise<Blob> { public getFile(fileName: string, size?: any): Promise<Blob> {
return this.openDatabase().then((db) => { return this.openDatabase().then((db) => {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readonly')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
var request = objectStore.get(fileName); var request = objectStore.get(fileName);
@ -257,8 +236,7 @@ class IdbFileStorage {
public getAllKeys(): Promise<Array<string>> { public getAllKeys(): Promise<Array<string>> {
console.time('getAllEntries'); console.time('getAllEntries');
return this.openDatabase().then((db) => { return this.openDatabase().then((db) => {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readonly')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
var request = objectStore.getAllKeys(); var request = objectStore.getAllKeys();
@ -278,8 +256,7 @@ class IdbFileStorage {
public isFileExists(fileName: string): Promise<boolean> { public isFileExists(fileName: string): Promise<boolean> {
console.time('isFileExists'); console.time('isFileExists');
return this.openDatabase().then((db) => { return this.openDatabase().then((db) => {
// @ts-ignore var objectStore = db.transaction([this.dbStoreName], 'readonly')
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
.objectStore(this.dbStoreName); .objectStore(this.dbStoreName);
var request = objectStore.openCursor(fileName); var request = objectStore.openCursor(fileName);
@ -307,6 +284,6 @@ class IdbFileStorage {
const idbFileStorage = new IdbFileStorage(); const idbFileStorage = new IdbFileStorage();
(window as any).IdbFileStorage = idbFileStorage; //(window as any).IdbFileStorage = idbFileStorage;
export default idbFileStorage; export default idbFileStorage;

3
src/lib/mtproto/apiFileManager.ts

@ -2,7 +2,8 @@ import { nextRandomInt } from "../bin_utils";
import IdbFileStorage from "../idb"; import IdbFileStorage from "../idb";
import FileManager from "../filemanager"; import FileManager from "../filemanager";
import apiManager from "./apiManager"; //import apiManager from "./apiManager";
import apiManager from "./mtprotoworker";
import { logger, deferredPromise, CancellablePromise } from "../polyfill"; import { logger, deferredPromise, CancellablePromise } from "../polyfill";
export class ApiFileManager { export class ApiFileManager {

19
src/lib/mtproto/apiManager.ts

@ -6,10 +6,13 @@ import networkerFactory from './networkerFactory';
import { telegramMeWebService } from './mtproto'; import { telegramMeWebService } from './mtproto';
import authorizer from './authorizer'; import authorizer from './authorizer';
import { isObject, tsNow, $rootScope } from '../utils'; import { isObject, tsNow, $rootScope } from '../utils';
import * as Config from '../config'; import {App, Modes} from './mtproto_config';
import dcConfigurator from './dcConfigurator'; import dcConfigurator from './dcConfigurator';
import HTTP from './transports/http'; import HTTP from './transports/http';
import { logger } from '../polyfill'; import { logger } from '../polyfill';
import passwordManager from './passwordManager';
console.error('apiManager included!');
export class ApiManager { export class ApiManager {
public cachedNetworkers: {[x: number]: MTPNetworker} = {}; public cachedNetworkers: {[x: number]: MTPNetworker} = {};
@ -55,7 +58,7 @@ export class ApiManager {
public async logOut() { public async logOut() {
let storageKeys: Array<string> = []; let storageKeys: Array<string> = [];
let prefix = Config.Modes.test ? 't_dc' : 'dc'; let prefix = Modes.test ? 't_dc' : 'dc';
for(let dcID = 1; dcID <= 5; dcID++) { for(let dcID = 1; dcID <= 5; dcID++) {
storageKeys.push(prefix + dcID + '_auth_key'); storageKeys.push(prefix + dcID + '_auth_key');
@ -124,7 +127,7 @@ export class ApiManager {
// mtpGetNetworker // mtpGetNetworker
public async getNetworker(dcID: number, options: any = {}): Promise<MTPNetworker> { public async getNetworker(dcID: number, options: any = {}): Promise<MTPNetworker> {
let upload = (options.fileUpload || options.fileDownload) let upload = (options.fileUpload || options.fileDownload)
&& (dcConfigurator.chooseServer(dcID, true) instanceof HTTP || Config.Modes.multipleConnections); && (dcConfigurator.chooseServer(dcID, true) instanceof HTTP || Modes.multipleConnections);
let cache = upload ? this.cachedUploadNetworkers : this.cachedNetworkers; let cache = upload ? this.cachedUploadNetworkers : this.cachedNetworkers;
if(!dcID) { if(!dcID) {
@ -315,7 +318,7 @@ export class ApiManager {
this.getNetworker(dcID, options).then(performRequest, rejectPromise); this.getNetworker(dcID, options).then(performRequest, rejectPromise);
} else { } else {
AppStorage.get<number>('dc').then((baseDcID) => { AppStorage.get<number>('dc').then((baseDcID) => {
this.getNetworker(this.baseDcID = dcID = baseDcID || Config.App.baseDcID, options).then(performRequest, rejectPromise); this.getNetworker(this.baseDcID = dcID = baseDcID || App.baseDcID, options).then(performRequest, rejectPromise);
}); });
} }
}); });
@ -328,6 +331,14 @@ export class ApiManager {
return auth.id || 0; return auth.id || 0;
}); });
} }
public checkPassword(value: string): Promise<any> {
return passwordManager.getState()
.then(state => {
console.log(state);
return passwordManager.check(state, value);
});
}
} }
export default new ApiManager(); export default new ApiManager();

7
src/lib/mtproto/authorizer.ts

@ -1,4 +1,4 @@
import { TLSerialization, TLDeserialization } from "../tl_utils"; import { TLSerialization, TLDeserialization } from "./tl_utils";
import dcConfigurator from "./dcConfigurator"; import dcConfigurator from "./dcConfigurator";
import { dT, bytesToHex, bytesCmp, bytesFromHex, bytesXor } from "../bin_utils"; import { dT, bytesToHex, bytesCmp, bytesFromHex, bytesXor } from "../bin_utils";
import rsaKeysManager from "./rsaKeysManager"; import rsaKeysManager from "./rsaKeysManager";
@ -9,11 +9,6 @@ import timeManager from "./timeManager";
import { BigInteger } from "jsbn"; import { BigInteger } from "jsbn";
import CryptoWorker from "../crypto/cryptoworker"; import CryptoWorker from "../crypto/cryptoworker";
import {MTProto} from './mtproto';
/* const chromeMatches = navigator.userAgent.match(/Chrome\/(\d+(\.\d+)?)/);
const chromeVersion = (chromeMatches && parseFloat(chromeMatches[1])) || false;
const xhrSendBuffer = !('ArrayBufferView' in window) && (chromeVersion > 0 && chromeVersion < 30); */
/* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse(); /* let fNewNonce: any = bytesFromHex('8761970c24cb2329b5b2459752c502f3057cb7e8dbab200e526e8767fdc73b3c').reverse();
let fNonce: any = bytesFromHex('b597720d11faa5914ef485c529cde414').reverse(); let fNonce: any = bytesFromHex('b597720d11faa5914ef485c529cde414').reverse();

11
src/lib/mtproto/dcConfigurator.ts

@ -1,6 +1,7 @@
import Socket from './transports/websocket'; import Socket from './transports/websocket';
import MTTransport from './transports/transport'; import MTTransport from './transports/transport';
import HTTP from './transports/http'; import HTTP from './transports/http';
import { Modes } from './mtproto_config';
type Servers = { type Servers = {
[transport: string]: { [transport: string]: {
@ -20,7 +21,7 @@ type Servers = {
export class DcConfigurator { export class DcConfigurator {
private sslSubdomains = ['pluto', 'venus', 'aurora', 'vesta', 'flora']; private sslSubdomains = ['pluto', 'venus', 'aurora', 'vesta', 'flora'];
private dcOptions = Config.Modes.test private dcOptions = Modes.test
? [ ? [
{id: 1, host: '149.154.175.10', port: 80}, {id: 1, host: '149.154.175.10', port: 80},
{id: 2, host: '149.154.167.40', port: 80}, {id: 2, host: '149.154.167.40', port: 80},
@ -47,7 +48,7 @@ export class DcConfigurator {
}; };
public chooseServer(dcID: number, upload?: boolean, transport = 'websocket') { public chooseServer(dcID: number, upload?: boolean, transport = 'websocket') {
let servers = upload && (transport != 'websocket' || Config.Modes.multipleConnections) let servers = upload && (transport != 'websocket' || Modes.multipleConnections)
? this.chosenUploadServers[transport] ? this.chosenUploadServers[transport]
: this.chosenServers[transport]; : this.chosenServers[transport];
@ -56,14 +57,14 @@ export class DcConfigurator {
if(transport == 'websocket') { if(transport == 'websocket') {
let subdomain = this.sslSubdomains[dcID - 1]; let subdomain = this.sslSubdomains[dcID - 1];
let path = Config.Modes.test ? 'apiws_test' : 'apiws'; let path = Modes.test ? 'apiws_test' : 'apiws';
chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path; chosenServer = 'wss://' + subdomain + '.web.telegram.org/' + path;
return servers[dcID] = new Socket(dcID, chosenServer); return servers[dcID] = new Socket(dcID, chosenServer);
} }
if(Config.Modes.ssl || !Config.Modes.http || transport == 'https') { if(Modes.ssl || !Modes.http || transport == 'https') {
let subdomain = this.sslSubdomains[dcID - 1] + (upload ? '-1' : ''); let subdomain = this.sslSubdomains[dcID - 1] + (upload ? '-1' : '');
let path = Config.Modes.test ? 'apiw_test1' : 'apiw1'; let path = Modes.test ? 'apiw_test1' : 'apiw1';
chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path; chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path;
return servers[dcID] = new HTTP(dcID, chosenServer); return servers[dcID] = new HTTP(dcID, chosenServer);
} }

15
src/lib/mtproto/mtproto.ts

@ -1,9 +1,8 @@
import * as Config from '../config';
import AppStorage from '../storage'; import AppStorage from '../storage';
import {tsNow} from '../utils'; import {tsNow} from '../utils';
import { Modes, App } from './mtproto_config';
import PasswordManager from './passwordManager'; /* import PasswordManager from './passwordManager';
import DcConfigurator from './dcConfigurator'; import DcConfigurator from './dcConfigurator';
import RSAKeysManager from './rsaKeysManager'; import RSAKeysManager from './rsaKeysManager';
import TimeManager from './timeManager'; import TimeManager from './timeManager';
@ -11,11 +10,11 @@ import ServerTimeManager from './serverTimeManager';
import Authorizer from './authorizer'; import Authorizer from './authorizer';
import NetworkerFactory from './networkerFactory'; import NetworkerFactory from './networkerFactory';
import ApiManager from './apiManager'; import ApiManager from './apiManager';
import ApiFileManager from './apiFileManager'; import ApiFileManager from './apiFileManager'; */
export class TelegramMeWebService { export class TelegramMeWebService {
public disabled = Config.Modes.test || public disabled = Modes.test ||
Config.App.domains.indexOf(location.hostname) == -1 || App.domains.indexOf(location.hostname) == -1 ||
location.protocol != 'http:' && location.protocol != 'https:' || location.protocol != 'http:' && location.protocol != 'https:' ||
location.protocol == 'https:' && location.hostname != 'web.telegram.org'; location.protocol == 'https:' && location.hostname != 'web.telegram.org';
@ -54,7 +53,7 @@ export class TelegramMeWebService {
export const telegramMeWebService = new TelegramMeWebService(); export const telegramMeWebService = new TelegramMeWebService();
export namespace MTProto { /* export namespace MTProto {
//$($window).on('click keydown', rng_seed_time); // WARNING! //$($window).on('click keydown', rng_seed_time); // WARNING!
export const passwordManager = PasswordManager; export const passwordManager = PasswordManager;
@ -68,4 +67,4 @@ export namespace MTProto {
export const serverTimeManager = ServerTimeManager; export const serverTimeManager = ServerTimeManager;
} }
(window as any).MTProto = MTProto; //(window as any).MTProto = MTProto; */

41
src/lib/mtproto/mtproto.worker.js

@ -0,0 +1,41 @@
import apiManager from "./apiManager";
import AppStorage from '../storage';
import cryptoWorker from "../crypto/cryptoworker";
import networkerFactory from "./networkerFactory";
//const ctx: Worker = self as any;
const ctx = self;
console.error('INCLUDE !!!', new Error().stack);
networkerFactory.setUpdatesProcessor((obj, bool) => {
ctx.postMessage({update: {obj, bool}});
});
ctx.onmessage = function(e) {
var taskID = e.data.taskID;
if(e.data.useLs) {
AppStorage.finishTask(e.data.taskID, e.data.args);
return;
}
switch(e.data.task) {
case 'unzip':
return cryptoWorker.gzipUncompress.apply(cryptoWorker, e.data.args).then(result => {
ctx.postMessage({taskID: taskID, result: result});
});
default:
return apiManager[e.data.task].apply(apiManager, e.data.args).then(result => {
console.log(e.data.task + ' result:', result, taskID);
ctx.postMessage({taskID: taskID, result: result});
}).catch(err => {
console.error(e.data.task + ' err:', err, taskID);
ctx.postMessage({taskID: taskID, error: err});
});
//throw new Error('Unknown task: ' + e.data.task);
}
}
ctx.postMessage('ready');

15
src/lib/mtproto/mtproto_config.ts

@ -0,0 +1,15 @@
export const App = {
id: 1025907,
hash: '452b0359b988148995f22ff0f4229750',
version: '0.3.0',
domains: [] as string[],
baseDcID: 2
};
export const Modes = {
test: location.search.indexOf('test=1') > 0/* || true */,
debug: location.search.indexOf('debug=1') > 0,
http: location.search.indexOf('http=1') > 0,
ssl: location.search.indexOf('ssl=1') > 0 || location.protocol == 'https:' && location.search.indexOf('ssl=0') == -1,
multipleConnections: true
};

150
src/lib/mtproto/mtprotoworker.ts

@ -0,0 +1,150 @@
import {dT, isObject} from '../utils';
import AppStorage from '../storage';
import CryptoWorkerMethods from '../crypto/crypto_methods';
type Task = {
taskID: number,
task: string,
args: any[]
};
class ApiManagerProxy extends CryptoWorkerMethods {
private webWorker: Worker | boolean = false;
private taskID = 0;
private awaiting: {
[id: number]: {
resolve: any,
reject: any,
taskName: string
}
} = {} as any;
private pending: Array<Task> = [];
private debug = true;
public updatesProcessor: (obj: any, bool: boolean) => void = null;
constructor() {
super();
console.log(dT(), 'ApiManagerProxy constructor');
if(window.Worker) {
import('./mtproto.worker.js').then((worker: any) => {
var tmpWorker = new worker.default();
tmpWorker.onmessage = (e: any) => {
if(!this.webWorker) {
this.webWorker = tmpWorker;
console.info(dT(), 'ApiManagerProxy set webWorker');
this.releasePending();
}
if(!isObject(e.data)) {
return;
}
if(e.data.useLs) {
// @ts-ignore
AppStorage[e.data.task](...e.data.args).then(res => {
(this.webWorker as Worker).postMessage({useLs: true, taskID: e.data.taskID, args: res});
});
} else if(e.data.update) {
if(this.updatesProcessor) {
this.updatesProcessor(e.data.update.obj, e.data.update.bool);
}
} else {
this.finalizeTask(e.data.taskID, e.data.result, e.data.error);
}
};
tmpWorker.onerror = (error: any) => {
console.error('ApiManagerProxy error', error);
this.webWorker = false;
};
});
}
}
private finalizeTask(taskID: number, result: any, error: any) {
let deferred = this.awaiting[taskID];
if(deferred !== undefined) {
this.debug && console.log(dT(), 'ApiManagerProxy done', deferred.taskName, result, error);
result === undefined ? deferred.reject(error) : deferred.resolve(result);
delete this.awaiting[taskID];
}
}
public performTaskWorker<T>(task: string, ...args: any[]) {
this.debug && console.log(dT(), 'ApiManagerProxy start', task, args);
return new Promise<T>((resolve, reject) => {
this.awaiting[this.taskID] = {resolve, reject, taskName: task};
let params = {
task,
taskID: this.taskID,
args
};
//(this.webWorker as Worker).postMessage(params);
this.pending.push(params);
this.releasePending();
this.taskID++;
});
}
private releasePending() {
if(this.webWorker) {
this.pending.forEach(pending => {
(this.webWorker as Worker).postMessage(pending);
});
this.pending.length = 0;
}
}
public setUpdatesProcessor(callback: (obj: any, bool: boolean) => void) {
this.updatesProcessor = callback;
}
public invokeApi(method: string, params: any = {}, options: {
dcID?: number,
timeout?: number,
noErrorBox?: boolean,
fileUpload?: boolean,
ignoreErrors?: boolean,
fileDownload?: boolean,
createNetworker?: boolean,
singleInRequest?: boolean,
startMaxLength?: number,
waitTime?: number,
stopTime?: number,
rawError?: any
} = {}): Promise<any> {
return this.performTaskWorker('invokeApi', method, params, options);
}
public setUserAuth(userAuth: {id: number}) {
return this.performTaskWorker('setUserAuth', userAuth);
}
public getNetworker(dc_id: number) {
return this.performTaskWorker('getNetworker', dc_id);
}
public getUserID(): Promise<number> {
return this.performTaskWorker('getUserID');
}
public logOut(): Promise<void> {
return this.performTaskWorker('logOut');
}
public checkPassword(value: string): Promise<any> {
return this.performTaskWorker('checkPassword', value);
}
}
const apiManagerProxy = new ApiManagerProxy();
(window as any).apiManagerProxy = apiManagerProxy;
export default apiManagerProxy;

70
src/lib/mtproto/networker.ts

@ -2,10 +2,10 @@ import {tsNow, isObject} from '../utils';
import {convertToUint8Array, import {convertToUint8Array,
bufferConcat, nextRandomInt, bytesToHex, longToBytes, bufferConcat, nextRandomInt, bytesToHex, longToBytes,
bytesCmp, uintToInt, bigStringInt} from '../bin_utils'; bytesCmp, uintToInt, bigStringInt} from '../bin_utils';
import {TLDeserialization, TLSerialization} from '../tl_utils'; import {TLDeserialization, TLSerialization} from './tl_utils';
import CryptoWorker from '../crypto/cryptoworker'; import CryptoWorker from '../crypto/cryptoworker';
import AppStorage from '../storage'; import AppStorage from '../storage';
import * as Config from '../config'; import Schema from './schema';
import timeManager from './timeManager'; import timeManager from './timeManager';
import NetworkerFactory from './networkerFactory'; import NetworkerFactory from './networkerFactory';
@ -13,10 +13,9 @@ import dcConfigurator from './dcConfigurator';
import Socket from './transports/websocket'; import Socket from './transports/websocket';
import HTTP from './transports/http'; import HTTP from './transports/http';
import { logger } from '../polyfill'; import { logger } from '../polyfill';
import { Modes, App } from './mtproto_config';
/* const chromeMatches = navigator.userAgent.match(/Chrome\/(\d+(\.\d+)?)/); console.error('networker included!', new Error().stack);
const chromeVersion = chromeMatches && parseFloat(chromeMatches[1]) || false;
const xhrSendBuffer = !('ArrayBufferView' in window) && (chromeVersion > 0 && chromeVersion < 30);*/
type Message = { type Message = {
msg_id: string, msg_id: string,
@ -103,15 +102,11 @@ class MTPNetworker {
this.updateSession(); this.updateSession();
if(!NetworkerFactory.offlineInited) { // if(!NetworkerFactory.offlineInited) {
NetworkerFactory.offlineInited = true; // NetworkerFactory.offlineInited = true;
/* $rootScope.offline = true // /* $rootScope.offline = true
$rootScope.offlineConnecting = true */ // $rootScope.offlineConnecting = true */
} // }
if(Config.Navigator.mobile) {
this.setupMobileSleep();
}
this.transport = dcConfigurator.chooseServer(this.dcID, this.upload); this.transport = dcConfigurator.chooseServer(this.dcID, this.upload);
@ -131,25 +126,6 @@ class MTPNetworker {
//MTProto.secureRandom.nextBytes(this.sessionID); //MTProto.secureRandom.nextBytes(this.sessionID);
} }
public setupMobileSleep() {
/* $rootScope.$watch('idle.isIDLE', (isIDLE) => {
if(isIDLE) {
this.sleepAfter = tsNow() + 30000;
} else {
delete this.sleepAfter;
this.checkLongPoll();
}
})
$rootScope.$on('push_received', function() {
// this.log('push recieved', self.sleepAfter)
if(this.sleepAfter) {
this.sleepAfter = tsNow() + 30000;
this.checkLongPoll();
}
}) */
}
public updateSentMessage(sentMessageID: any) { public updateSentMessage(sentMessageID: any) {
var sentMessage = this.sentMessages[sentMessageID]; var sentMessage = this.sentMessages[sentMessageID];
if(!sentMessage) { if(!sentMessage) {
@ -202,7 +178,7 @@ class MTPNetworker {
body: serializer.getBytes() body: serializer.getBytes()
}; };
if(Config.Modes.debug) { if(Modes.debug) {
this.log('MT call', method, params, messageID, seqNo); this.log('MT call', method, params, messageID, seqNo);
} }
@ -221,7 +197,7 @@ class MTPNetworker {
body: serializer.getBytes() body: serializer.getBytes()
}; };
if(Config.Modes.debug) { if(Modes.debug) {
this.log('MT message', object, messageID, seqNo); this.log('MT message', object, messageID, seqNo);
} }
@ -251,32 +227,32 @@ class MTPNetworker {
if(!this.connectionInited) { // this will call once for each new session if(!this.connectionInited) { // this will call once for each new session
///////this.log('Wrap api call !this.connectionInited'); ///////this.log('Wrap api call !this.connectionInited');
let invokeWithLayer = Config.Schema.API.methods.find((m: any) => m.method == 'invokeWithLayer'); let invokeWithLayer = Schema.API.methods.find((m: any) => m.method == 'invokeWithLayer');
if(!invokeWithLayer) throw new Error('no invokeWithLayer!'); if(!invokeWithLayer) throw new Error('no invokeWithLayer!');
serializer.storeInt(+invokeWithLayer.id >>> 0, 'invokeWithLayer'); serializer.storeInt(+invokeWithLayer.id >>> 0, 'invokeWithLayer');
// @ts-ignore // @ts-ignore
serializer.storeInt(Config.Schema.API.layer, 'layer'); serializer.storeInt(Schema.layer, 'layer');
let initConnection = Config.Schema.API.methods.find((m: any) => m.method == 'initConnection'); let initConnection = Schema.API.methods.find((m: any) => m.method == 'initConnection');
if(!initConnection) throw new Error('no initConnection!'); if(!initConnection) throw new Error('no initConnection!');
serializer.storeInt(+initConnection.id >>> 0, 'initConnection'); serializer.storeInt(+initConnection.id >>> 0, 'initConnection');
serializer.storeInt(0x0, 'flags'); serializer.storeInt(0x0, 'flags');
serializer.storeInt(Config.App.id, 'api_id'); serializer.storeInt(App.id, 'api_id');
serializer.storeString(navigator.userAgent || 'Unknown UserAgent', 'device_model'); serializer.storeString(navigator.userAgent || 'Unknown UserAgent', 'device_model');
serializer.storeString(navigator.platform || 'Unknown Platform', 'system_version'); serializer.storeString(navigator.platform || 'Unknown Platform', 'system_version');
serializer.storeString(Config.App.version, 'app_version'); serializer.storeString(App.version, 'app_version');
serializer.storeString(navigator.language || 'en', 'system_lang_code'); serializer.storeString(navigator.language || 'en', 'system_lang_code');
serializer.storeString('', 'lang_pack'); serializer.storeString('', 'lang_pack');
serializer.storeString(navigator.language || 'en', 'lang_code'); serializer.storeString(navigator.language || 'en', 'lang_code');
//serializer.storeInt(0x0, 'proxy'); //serializer.storeInt(0x0, 'proxy');
/* serializer.storeMethod('initConnection', { /* serializer.storeMethod('initConnection', {
'flags': 0, 'flags': 0,
'api_id': Config.App.id, 'api_id': App.id,
'device_model': navigator.userAgent || 'Unknown UserAgent', 'device_model': navigator.userAgent || 'Unknown UserAgent',
'system_version': navigator.platform || 'Unknown Platform', 'system_version': navigator.platform || 'Unknown Platform',
'app_version': Config.App.version, 'app_version': App.version,
'system_lang_code': navigator.language || 'en', 'system_lang_code': navigator.language || 'en',
'lang_pack': '', 'lang_pack': '',
'lang_code': navigator.language || 'en' 'lang_code': navigator.language || 'en'
@ -284,7 +260,7 @@ class MTPNetworker {
} }
if(options.afterMessageID) { if(options.afterMessageID) {
let invokeAfterMsg = Config.Schema.API.methods.find((m: any) => m.method == 'invokeAfterMsg'); let invokeAfterMsg = Schema.API.methods.find((m: any) => m.method == 'invokeAfterMsg');
if(!invokeAfterMsg) throw new Error('no invokeAfterMsg!'); if(!invokeAfterMsg) throw new Error('no invokeAfterMsg!');
this.log('Api call options.afterMessageID!'); this.log('Api call options.afterMessageID!');
@ -307,7 +283,7 @@ class MTPNetworker {
isAPI: true isAPI: true
}; };
if(Config.Modes.debug/* || true */) { if(Modes.debug/* || true */) {
this.log('Api call', method, message, params, options); this.log('Api call', method, message, params, options);
} else { } else {
//////this.log('Api call', method); //////this.log('Api call', method);
@ -677,7 +653,7 @@ class MTPNetworker {
this.sentMessages[message.msg_id] = containerSentMessage; this.sentMessages[message.msg_id] = containerSentMessage;
if(Config.Modes.debug || true) { if(Modes.debug || true) {
this.log('Container', innerMessages, message.msg_id, message.seq_no); this.log('Container', innerMessages, message.msg_id, message.seq_no);
} }
} else { } else {
@ -698,7 +674,7 @@ class MTPNetworker {
self.toggleOffline(false); self.toggleOffline(false);
// this.log('parse for', message) // this.log('parse for', message)
self.parseResponse(result).then((response) => { self.parseResponse(result).then((response) => {
if(Config.Modes.debug) { if(Modes.debug) {
this.log('Server response', self.dcID, response); this.log('Server response', self.dcID, response);
} }
@ -1194,7 +1170,7 @@ class MTPNetworker {
} }
} else { } else {
if(deferred) { if(deferred) {
if(Config.Modes.debug) { if(Modes.debug) {
this.debug && this.log('Rpc response', message.result); this.debug && this.log('Rpc response', message.result);
} else { } else {
var dRes = message.result._; var dRes = message.result._;

14
src/lib/mtproto/networkerFactory.ts

@ -1,19 +1,11 @@
import { dT } from "../utils";
import { MTPNetworker } from "./networker"; import { MTPNetworker } from "./networker";
export class NetworkerFactory { export class NetworkerFactory {
public updatesProcessor: (obj: any, bool: boolean) => void = null; public updatesProcessor: (obj: any, bool: boolean) => void = null;
public offlineInited = false; //public offlineInited = false;
public akStopped = false; public akStopped = false;
constructor() { /* public startAll() {
/* $rootScope.retryOnline = function() {
$(document.body).trigger('online');
} */
}
public startAll() {
if(this.akStopped) { if(this.akStopped) {
this.akStopped = false; this.akStopped = false;
@ -27,7 +19,7 @@ export class NetworkerFactory {
public stopAll() { public stopAll() {
this.akStopped = true; this.akStopped = true;
} } */
public setUpdatesProcessor(callback: (obj: any, bool: boolean) => void) { public setUpdatesProcessor(callback: (obj: any, bool: boolean) => void) {
this.updatesProcessor = callback; this.updatesProcessor = callback;

16
src/lib/mtproto/passwordManager.ts

@ -1,9 +1,6 @@
import apiManager from "./apiManager"; import apiManager from "./apiManager";
import { bufferConcats, bytesToHex, bytesFromHex, bufferConcat, bytesXor } from "../bin_utils"; import { bufferConcats, bytesToHex, bytesFromHex, bufferConcat, bytesXor } from "../bin_utils";
import CryptoWorker from "../crypto/cryptoworker"; import CryptoWorker from "../crypto/cryptoworker";
import {str2bigInt, greater, isZero, import {str2bigInt, greater, isZero,
// @ts-ignore // @ts-ignore
bigInt2str, powMod, int2bigInt, mult, mod, sub, bitSize, negative, mult, add} from 'leemon'; bigInt2str, powMod, int2bigInt, mult, mod, sub, bitSize, negative, mult, add} from 'leemon';
@ -80,19 +77,6 @@ export class PasswordManager {
}, options); }, options);
} }
/* public makePasswordHash(salt: any, password: any) {
var passwordUTF8 = unescape(encodeURIComponent(password));
var buffer = new ArrayBuffer(passwordUTF8.length);
var byteView = new Uint8Array(buffer);
for(var i = 0, len = passwordUTF8.length; i < len; i++) {
byteView[i] = passwordUTF8.charCodeAt(i);
}
buffer = bufferConcat(bufferConcat(salt, byteView), salt);
return CryptoWorker.sha256Hash(buffer);
} */
public makePasswordHash(password: string, client_salt: Uint8Array, server_salt: Uint8Array) { public makePasswordHash(password: string, client_salt: Uint8Array, server_salt: Uint8Array) {
var passwordUTF8 = unescape(encodeURIComponent(password)); var passwordUTF8 = unescape(encodeURIComponent(password));

4
src/lib/mtproto/rsaKeysManager.ts

@ -1,7 +1,5 @@
import { TLSerialization } from "../tl_utils"; import { TLSerialization } from "./tl_utils";
import { bytesFromHex, bigStringInt, bytesToHex, bytesFromArrayBuffer } from "../bin_utils"; import { bytesFromHex, bigStringInt, bytesToHex, bytesFromArrayBuffer } from "../bin_utils";
import CryptoWorker from '../crypto/cryptoworker'; import CryptoWorker from '../crypto/cryptoworker';
export class RSAKeysManager { export class RSAKeysManager {

5
src/lib/mtproto/schema.ts

File diff suppressed because one or more lines are too long

1530
src/lib/tl_utils.ts → src/lib/mtproto/tl_utils.ts

File diff suppressed because it is too large Load Diff

1
src/lib/richtextprocessor.js

@ -1,4 +1,5 @@
import {encodeEntities, copy/* , emojiUnicode */} from './utils'; import {encodeEntities, copy/* , emojiUnicode */} from './utils';
import Config from './config';
var EmojiHelper = { var EmojiHelper = {
emojiMap: (code) => { return code; }, emojiMap: (code) => { return code; },

209
src/lib/storage.ts

@ -1,26 +1,205 @@
import {Storage as ConfigStorage, Modes} from './config'; import { Modes } from './mtproto/mtproto_config';
class ConfigStorage {
public keyPrefix = '';
public noPrefix = false;
private cache: {[key: string]: any} = {};
private useLs = true;
storageGetPrefix() {
if(this.noPrefix) {
this.noPrefix = false;
return '';
}
return this.keyPrefix;
}
get(keys: any, callback: any) {
var single = false;
if(!Array.isArray(keys)) {
keys = Array.prototype.slice.call(arguments);
callback = keys.pop();
single = keys.length == 1;
}
var result = [],
value;
var allFound = true;
var prefix = this.storageGetPrefix(),
i, key;
for(i = 0; i < keys.length; i++) {
key = keys[i] = prefix + keys[i];
if(key.substr(0, 3) != 'xt_' && this.cache[key] !== undefined) {
result.push(this.cache[key]);
} else if(this.useLs) {
try {
value = localStorage.getItem(key);
} catch(e) {
this.useLs = false;
}
try {
value = (value === undefined || value === null) ? false : JSON.parse(value);
} catch(e) {
value = false;
}
result.push(this.cache[key] = value);
} else {
allFound = false;
}
}
if(allFound) {
return callback(single ? result[0] : result);
}
}
set(obj: any, callback: any) {
var keyValues: any = {};
var prefix = this.storageGetPrefix(),
key, value;
//console.log('storageSetValue', obj, callback, arguments);
for(key in obj) {
if(obj.hasOwnProperty(key)) {
value = obj[key];
key = prefix + key;
this.cache[key] = value;
//value = value instanceof Uint8Array ? Array.from(value) : JSON.stringify(value);
value = JSON.stringify(value);
if(this.useLs) {
try {
//console.log('setItem', key, value);
localStorage.setItem(key, value);
} catch (e) {
this.useLs = false;
}
} else {
keyValues[key] = value;
}
}
}
if(this.useLs) {
if(callback) {
callback();
}
return;
}
}
remove(keys: any, callback: any) {
if(!Array.isArray(keys)) {
keys = Array.prototype.slice.call(arguments)
if(typeof keys[keys.length - 1] === 'function') {
callback = keys.pop();
}
}
var prefix = this.storageGetPrefix(),
i, key;
for(i = 0; i < keys.length; i++) {
key = keys[i] = prefix + keys[i];
delete this.cache[key];
if(this.useLs) {
try {
localStorage.removeItem(key);
} catch(e) {
this.useLs = false;
}
}
}
if(callback) {
callback();
}
}
clear(callback: any) {
if(this.useLs) {
try {
localStorage.clear();
} catch (e) {
this.useLs = false;
}
}
this.cache = {};
callback();
}
}
const configStorage = new ConfigStorage();
/* private cache: {[key: string]: any} = {};
private request: Promise<Cache>;
private cacheURL: string;
constructor(cacheName: string) {
this.request = new Promise((resolve, reject) => {
let promise = caches.open(cacheName);
promise.then(cache => {
cache.keys().then(requests => {
if(!requests.length) {
return cache.put(this.cacheURL = '/session/' + Date.now(), new Response('{}'));
} else {
this.cacheURL = requests[0].url;
return cache.match(requests[0]).then(response => response.json()).then(j => this.cache = j);
}
}).then(() => {
resolve(promise);
});
})
});
} */
class AppStorage { class AppStorage {
private isWebWorker: boolean;
private taskID = 0;
private tasks: {[taskID: number]: (result: any) => void} = {};
constructor() {
if(Modes.test) {
this.setPrefix('t_');
}
// @ts-ignore
this.isWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
}
public setPrefix(newPrefix: string) { public setPrefix(newPrefix: string) {
ConfigStorage.prefix(newPrefix); configStorage.keyPrefix = newPrefix;
} }
public noPrefix() { public noPrefix() {
ConfigStorage.noPrefix(); configStorage.noPrefix = true;
} }
private proxy<T>(methodName: string, ..._args: any[]) { public finishTask(taskID: number, result: any) {
let args = Array.prototype.slice.call(_args); this.tasks[taskID](result);
delete this.tasks[taskID];
}
let promise = new Promise<T>((resolve, reject) => { private proxy<T>(methodName: string, ..._args: any[]) {
args.push((result: T) => { return new Promise<T>((resolve, reject) => {
resolve(result); if(this.isWebWorker) {
}); this.tasks[this.taskID] = resolve;
// @ts-ignore
self.postMessage({useLs: true, task: methodName, taskID: this.taskID, args: _args});
this.taskID++;
} else {
let args = Array.prototype.slice.call(_args);
args.push((result: T) => {
resolve(result);
});
ConfigStorage[methodName].apply(ConfigStorage, args); // @ts-ignore
configStorage[methodName].apply(configStorage, args);
}
}); });
return promise;
} }
public get<T>(...args: any[]) { public get<T>(...args: any[]) {
@ -39,12 +218,6 @@ class AppStorage {
public clear<T>(...args: any[]) { public clear<T>(...args: any[]) {
return this.proxy<T>('clear', ...args); return this.proxy<T>('clear', ...args);
} }
constructor() {
if(Modes.test) {
this.setPrefix('t_');
}
}
} }
export default new AppStorage(); export default new AppStorage();

6
src/lib/utils.js

@ -394,8 +394,8 @@ export function isObject(object) {
} }
export function tsNow (seconds) { export function tsNow (seconds) {
var t = +new Date() + (window.tsOffset || 0) var t = +new Date();
return seconds ? Math.floor(t / 1000) : t return seconds ? Math.floor(t / 1000) : t;
} }
export function safeReplaceObject (wasObject, newObject) { export function safeReplaceObject (wasObject, newObject) {
@ -888,7 +888,7 @@ function versionCompare (ver1, ver2) {
cleanUsername: cleanUsername, cleanUsername: cleanUsername,
search: search search: search
}; };
window.SearchIndexManager = SearchIndexManager; //window.SearchIndexManager = SearchIndexManager;
export {SearchIndexManager}; export {SearchIndexManager};
//})(window) //})(window)

14
src/pages/pageAuthCode.ts

@ -2,10 +2,12 @@ import pageSignIn from './pageSignIn';
import pageSignUp from './pageSignUp'; import pageSignUp from './pageSignUp';
import pageIm from './pageIm'; import pageIm from './pageIm';
import pagePassword from './pagePassword'; import pagePassword from './pagePassword';
import CryptoWorker from '../lib/crypto/cryptoworker';
import LottieLoader from '../lib/lottieLoader'; import LottieLoader from '../lib/lottieLoader';
import apiManager from '../lib/mtproto/apiManager'; //import CryptoWorker from '../lib/crypto/cryptoworker';
//import apiManager from '../lib/mtproto/apiManager';
import apiManager from '../lib/mtproto/mtprotoworker';
import Page from './page'; import Page from './page';
import { App } from '../lib/mtproto/mtproto_config';
let authCode: { let authCode: {
_: string, // 'auth.sentCode' _: string, // 'auth.sentCode'
@ -49,8 +51,8 @@ let onFirstMount = (): Promise<any> => {
changePhonePromise = apiManager.invokeApi('auth.sendCode', { changePhonePromise = apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */ /* flags: 0, */
phone_number: phone_number, phone_number: phone_number,
api_id: Config.App.id, api_id: App.id,
api_hash: Config.App.hash, api_hash: App.hash,
settings: { settings: {
_: 'codeSettings', // that's how we sending Type _: 'codeSettings', // that's how we sending Type
flags: 0 flags: 0
@ -122,7 +124,7 @@ let onFirstMount = (): Promise<any> => {
console.log('invoking auth.signIn with params:', params); console.log('invoking auth.signIn with params:', params);
apiManager.invokeApi('auth.signIn', params) apiManager.invokeApi('auth.signIn', params, {ignoreErrors: true})
.then((response: any) => { .then((response: any) => {
console.log('auth.signIn response:', response); console.log('auth.signIn response:', response);
@ -220,7 +222,7 @@ let onFirstMount = (): Promise<any> => {
fetch('assets/img/TwoFactorSetupMonkeyTracking.tgs') fetch('assets/img/TwoFactorSetupMonkeyTracking.tgs')
.then(res => res.arrayBuffer()) .then(res => res.arrayBuffer())
.then(data => CryptoWorker.gzipUncompress<string>(data, true)) .then(data => apiManager.gzipUncompress<string>(data, true))
.then(str => LottieLoader.loadAnimation({ .then(str => LottieLoader.loadAnimation({
container: page.pageEl.querySelector('.auth-image'), container: page.pageEl.querySelector('.auth-image'),
renderer: 'svg', renderer: 'svg',

45
src/pages/pagePassword.ts

@ -1,10 +1,11 @@
import pageIm from './pageIm'; import pageIm from './pageIm';
import CryptoWorker from '../lib/crypto/cryptoworker'; //import CryptoWorker from '../lib/crypto/cryptoworker';
//import apiManager from '../lib/mtproto/apiManager';
import { putPreloader } from '../components/misc'; import { putPreloader } from '../components/misc';
import LottieLoader from '../lib/lottieLoader'; import LottieLoader from '../lib/lottieLoader';
import passwordManager from '../lib/mtproto/passwordManager'; //import passwordManager from '../lib/mtproto/passwordManager';
import apiManager from '../lib/mtproto/apiManager'; import apiManager from '../lib/mtproto/mtprotoworker';
import Page from './page'; import Page from './page';
let onFirstMount = (): Promise<any> => { let onFirstMount = (): Promise<any> => {
@ -58,27 +59,23 @@ let onFirstMount = (): Promise<any> => {
this.textContent = 'PLEASE WAIT...'; this.textContent = 'PLEASE WAIT...';
putPreloader(this); putPreloader(this);
passwordManager.getState() apiManager.checkPassword(value).then((response: any) => {
.then(state => { console.log('passwordManager response:', response);
console.log(state);
passwordManager.check(state, value).then((response: any) => {
console.log('passwordManager response:', response);
switch(response._) { switch(response._) {
case 'auth.authorization': case 'auth.authorization':
apiManager.setUserAuth({ apiManager.setUserAuth({
id: response.user.id id: response.user.id
}); });
pageIm.mount(); pageIm.mount();
if(animation) animation.destroy(); if(animation) animation.destroy();
break; break;
default: default:
btnNext.removeAttribute('disabled'); btnNext.removeAttribute('disabled');
btnNext.innerText = response._; btnNext.innerText = response._;
break; break;
} }
}).catch(handleError);
}).catch(handleError); }).catch(handleError);
}); });
@ -98,7 +95,7 @@ let onFirstMount = (): Promise<any> => {
fetch('assets/img/TwoFactorSetupMonkeyClose.tgs') fetch('assets/img/TwoFactorSetupMonkeyClose.tgs')
.then(res => res.arrayBuffer()) .then(res => res.arrayBuffer())
.then(data => CryptoWorker.gzipUncompress<string>(data, true)) .then(data => apiManager.gzipUncompress<string>(data, true))
.then(str => LottieLoader.loadAnimation({ .then(str => LottieLoader.loadAnimation({
container: page.pageEl.querySelector('.auth-image'), container: page.pageEl.querySelector('.auth-image'),
renderer: 'svg', renderer: 'svg',

26
src/pages/pageSignIn.ts

@ -1,12 +1,14 @@
import { putPreloader, formatPhoneNumber } from "../components/misc"; import { putPreloader, formatPhoneNumber } from "../components/misc";
import Scrollable from '../components/scrollable'; import Scrollable from '../components/scrollable';
import {RichTextProcessor} from '../lib/richtextprocessor'; import {RichTextProcessor} from '../lib/richtextprocessor';
import * as Config from '../lib/config'; import Config from '../lib/config';
import { findUpTag } from "../lib/utils"; import { findUpTag } from "../lib/utils";
import pageAuthCode from "./pageAuthCode"; import pageAuthCode from "./pageAuthCode";
import apiManager from "../lib/mtproto/apiManager"; //import apiManager from "../lib/mtproto/apiManager";
import apiManager from "../lib/mtproto/mtprotoworker";
import Page from "./page"; import Page from "./page";
import { App, Modes } from "../lib/mtproto/mtproto_config";
type Country = { type Country = {
name: string, name: string,
@ -21,6 +23,18 @@ type Country = {
let btnNext: HTMLButtonElement = null; let btnNext: HTMLButtonElement = null;
let onFirstMount = () => { let onFirstMount = () => {
if(Modes.test) {
Config.Countries.push({
name: 'Test Country',
phoneCode: '999 66',
code: 'TC',
emoji: '🤔',
pattern: '999 66 XXX XX'
});
console.log('Added test country to list!');
}
//const countries: Country[] = _countries.default.filter(c => c.emoji); //const countries: Country[] = _countries.default.filter(c => c.emoji);
const countries: Country[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name)); const countries: Country[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name));
@ -189,15 +203,15 @@ let onFirstMount = () => {
let phone_number = telEl.value; let phone_number = telEl.value;
apiManager.invokeApi('auth.sendCode', { apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */ //flags: 0,
phone_number: phone_number, phone_number: phone_number,
api_id: Config.App.id, api_id: App.id,
api_hash: Config.App.hash, api_hash: App.hash,
settings: { settings: {
_: 'codeSettings', // that's how we sending Type _: 'codeSettings', // that's how we sending Type
flags: 0 flags: 0
} }
/* lang_code: navigator.language || 'en' */ //lang_code: navigator.language || 'en'
}).then((code: any) => { }).then((code: any) => {
console.log('got code', code); console.log('got code', code);

3
src/pages/pageSignUp.ts

@ -1,7 +1,8 @@
import {putPreloader} from '../components/misc'; import {putPreloader} from '../components/misc';
import resizeableImage from '../lib/cropper'; import resizeableImage from '../lib/cropper';
import pageIm from './pageIm'; import pageIm from './pageIm';
import apiManager from '../lib/mtproto/apiManager'; //import apiManager from '../lib/mtproto/apiManager';
import apiManager from '../lib/mtproto/mtprotoworker';
import apiFileManager from '../lib/mtproto/apiFileManager'; import apiFileManager from '../lib/mtproto/apiFileManager';
import Page from './page'; import Page from './page';

26517
stats.json

File diff suppressed because one or more lines are too long

2
tsconfig.json

@ -66,7 +66,7 @@
"public", "public",
"coverage", "coverage",
"./src/lib/ckin.js", "./src/lib/ckin.js",
"./src/lib/config.js", "src/lib/config.ts",
"./src/lib/StackBlur.js", "./src/lib/StackBlur.js",
"./src/lib/*.js", "./src/lib/*.js",
"./src/*.js", "./src/*.js",

12
webpack.common.js

@ -3,6 +3,13 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
let allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192']; let allowedIPs = ['195.66.140.39', '192.168.31.144', '127.0.0.1', '192.168.31.1', '192.168.31.192'];
const opts = {
MTPROTO_WORKER: true,
version: 3,
"ifdef-verbose": true, // add this for verbose output
"ifdef-triple-slash": true // add this to use double slash comment instead of default triple slash
};
module.exports = { module.exports = {
module: { module: {
rules: [ rules: [
@ -31,7 +38,10 @@ module.exports = {
}, },
{ {
test: /\.ts?$/, test: /\.ts?$/,
use: 'ts-loader', use: [
'ts-loader',
{ loader: "ifdef-loader", options: opts }
],
exclude: /node_modules/, exclude: /node_modules/,
}, },
{ {

Loading…
Cancel
Save