Browse Source

Moved MTProto to worker

master
morethanwords 5 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. 23
      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. 26
      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. 47
      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 @@ @@ -5633,6 +5633,15 @@
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
"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": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",

1
package.json

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

3
src/components/chatInput.ts

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
import Scrollable from "./scrollable";
import LazyLoadQueue from "./lazyLoadQueue";
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 appImManager from "../lib/appManagers/appImManager";
import { calcImageInBox, getRichValue } from "../lib/utils";

8
src/components/emoticonsDropdown.ts

@ -6,13 +6,15 @@ import Scrollable from "./scrollable"; @@ -6,13 +6,15 @@ import Scrollable from "./scrollable";
import { findUpTag, whichChild, calcImageInBox } from "../lib/utils";
import { RichTextProcessor } from "../lib/richtextprocessor";
import appStickersManager, { MTStickerSet } from "../lib/appManagers/appStickersManager";
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 CryptoWorker from '../lib/crypto/cryptoworker';
import LazyLoadQueue from "./lazyLoadQueue";
import { MTDocument, wrapSticker } from "./wrappers";
import appWebpManager from "../lib/appManagers/appWebpManager";
import appDocsManager from "../lib/appManagers/appDocsManager";
import ProgressivePreloader from "./preloader";
import Config from "../lib/config";
export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown';
@ -369,7 +371,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement, @@ -369,7 +371,7 @@ const initEmoticonsDropdown = (pageEl: HTMLDivElement,
reader.addEventListener('loadend', async(e) => {
// @ts-ignore
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({
container: li,

1
src/components/misc.ts

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import { whichChild, findUpTag } from "../lib/utils";
import Config from "../lib/config";
let rippleClickID = 0;
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 @@ @@ -1,5 +1,6 @@
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 appStickersManager from "../lib/appManagers/appStickersManager";
import appDocsManager from "../lib/appManagers/appDocsManager";
@ -709,7 +710,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: ( @@ -709,7 +710,7 @@ export function wrapSticker(doc: MTDocument, div: HTMLDivElement, middleware?: (
console.time('render sticker' + doc.id);
// @ts-ignore
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);

7
src/lib/appManagers/apiUpdatesManager.ts

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

3
src/lib/appManagers/appImManager.ts

@ -1,4 +1,5 @@ @@ -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 appUsersManager from "./appUsersManager";
import appMessagesManager from "./appMessagesManager";

1
src/lib/appManagers/appMediaViewer.ts

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

7
src/lib/appManagers/appMessagesManager.ts

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

23
src/lib/appManagers/appPhotosManager.ts

@ -4,7 +4,8 @@ import fileManager from '../filemanager'; @@ -4,7 +4,8 @@ import fileManager from '../filemanager';
import { bytesFromHex } from "../bin_utils";
import { MTPhotoSize } from "../../components/wrappers";
import apiFileManager from "../mtproto/apiFileManager";
import apiManager from "../mtproto/apiManager";
//import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
export type MTPhoto = {
_: 'photo' | 'photoEmpty' | string,
@ -89,7 +90,8 @@ export class AppPhotosManager { @@ -89,7 +90,8 @@ export class AppPhotosManager {
}
public choosePhotoSize(photo: any, width = 0, height = 0) {
if(Config.Navigator.retina) {
//if(Config.Navigator.retina) {
if(window.devicePixelRatio > 1) {
width *= 2;
height *= 2;
}
@ -106,6 +108,19 @@ export class AppPhotosManager { @@ -106,6 +108,19 @@ export class AppPhotosManager {
d crop 1280x1280 */
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;
//console.log('choosePhotoSize', photo);
@ -123,9 +138,9 @@ export class AppPhotosManager { @@ -123,9 +138,9 @@ export class AppPhotosManager {
}
//console.log('diff', diff, photoSize, bestPhotoSize);
});
}); */
//console.log('choosing', photo, width, height, bestPhotoSize);
console.log('choosing', photo, width, height, bestPhotoSize);
return bestPhotoSize;
}

5
src/lib/appManagers/appSharedMediaManager.ts

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

3
src/lib/appManagers/appSidebarLeft.ts

@ -2,7 +2,8 @@ @@ -2,7 +2,8 @@
import appDialogsManager from "./appDialogsManager";
import { $rootScope } from "../utils";
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";
class AppSidebarLeft {

3
src/lib/appManagers/appStickersManager.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import AppStorage from '../storage';
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 appDocsManager from './appDocsManager';

3
src/lib/appManagers/appUsersManager.ts

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
import { SearchIndexManager, safeReplaceObject, isObject, tsNow, copy, $rootScope } from "../utils";
import { RichTextProcessor } from "../richtextprocessor";
import appChatsManager from "./appChatsManager";
import apiManager from "../mtproto/apiManager";
//import apiManager from '../mtproto/apiManager';
import apiManager from '../mtproto/mtprotoworker';
import serverTimeManager from "../mtproto/serverTimeManager";
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 @@ @@ -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 @@ @@ -1,7 +1,5 @@
import {convertToArrayBuffer, convertToByteArray, dT} from '../bin_utils';
// @ts-ignore
//import Worker from './crypto.worker.js';
import {dT} from '../bin_utils';
import CryptoWorkerMethods from './crypto_methods';
type Task = {
taskID: number,
@ -9,7 +7,7 @@ type Task = { @@ -9,7 +7,7 @@ type Task = {
args: any[]
};
class CryptoWorker {
class CryptoWorker extends CryptoWorkerMethods {
private webWorker: Worker | boolean = false;
private taskID = 0;
private awaiting: {
@ -22,13 +20,35 @@ class CryptoWorker { @@ -22,13 +20,35 @@ class CryptoWorker {
private pending: Array<Task> = [];
private debug = false;
private utils: {[name: string]: (...args: any[]) => any} = {};
constructor() {
super();
console.log(dT(), 'CW constructor');
if(window.Worker/* && 1 == 2 */) {
import('./crypto.worker.js').then((CryptoWebWorker: any) => {
//console.log(CryptoWebWorker);
var tmpWorker = new CryptoWebWorker.default();
/// #if MTPROTO_WORKER
Promise.all([
import('./crypto_utils').then(utils => {
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();
tmpWorker.onmessage = (e: any) => {
if(!this.webWorker) {
@ -41,11 +61,12 @@ class CryptoWorker { @@ -41,11 +61,12 @@ class CryptoWorker {
};
tmpWorker.onerror = (error: any) => {
console.error('CW error', error/* , error.stack */);
console.error('CW error', error);
this.webWorker = false;
};
});
}
/// #endif
}
private finalizeTask(taskID: number, result: any) {
@ -60,6 +81,9 @@ class CryptoWorker { @@ -60,6 +81,9 @@ class CryptoWorker {
public performTaskWorker<T>(task: string, ...args: any[]) {
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) => {
this.awaiting[this.taskID] = {resolve, reject, taskName: task};
@ -75,6 +99,7 @@ class CryptoWorker { @@ -75,6 +99,7 @@ class CryptoWorker {
this.taskID++;
});
/// #endif
}
private releasePending() {
@ -86,49 +111,8 @@ class CryptoWorker { @@ -86,49 +111,8 @@ class CryptoWorker {
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();
(window as any).CryptoWorker = cryptoWorker;
//(window as any).CryptoWorker = cryptoWorker;
export default cryptoWorker;

11
src/lib/filemanager.ts

@ -1,11 +1,11 @@ @@ -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
import streamSaver from 'streamsaver';
if(window.location.href.indexOf('localhost') === -1) {
streamSaver.mitm = 'mitm.html';
}
} */
class FileManager {
public blobSupported = true;
@ -104,13 +104,14 @@ class FileManager { @@ -104,13 +104,14 @@ class FileManager {
}
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,
writableStrategy: undefined,
readableStrategy: undefined
});
let writer = fileStream.getWriter();
return writer;
return writer; */
}
public getFakeFileWriter(mimeType: string, saveFileCallback: any) {

41
src/lib/idb.ts

@ -6,28 +6,11 @@ class IdbFileStorage { @@ -6,28 +6,11 @@ class IdbFileStorage {
public dbStoreName = 'files';
public dbVersion = 2;
public openDbPromise: Promise<IDBDatabase>;
public storageIsAvailable: boolean;
public storeBlobsAvailable: boolean;
public storageIsAvailable = true;
public storeBlobsAvailable = true;
public name = 'IndexedDB';
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();
}
@ -103,8 +86,7 @@ class IdbFileStorage { @@ -103,8 +86,7 @@ class IdbFileStorage {
public deleteFile(fileName: string): Promise<void> {
return this.openDatabase().then((db) => {
try {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
var objectStore = db.transaction([this.dbStoreName], 'readwrite')
.objectStore(this.dbStoreName);
console.log('Delete file: `' + fileName + '`');
@ -137,8 +119,7 @@ class IdbFileStorage { @@ -137,8 +119,7 @@ class IdbFileStorage {
}
try {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
var objectStore = db.transaction([this.dbStoreName], 'readwrite')
.objectStore(this.dbStoreName);
var request = objectStore.put(blob, fileName);
} catch(error) {
@ -206,8 +187,7 @@ class IdbFileStorage { @@ -206,8 +187,7 @@ class IdbFileStorage {
public storagePutB64String(db: IDBDatabase, fileName: string, b64string: string) {
try {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ_WRITE || 'readwrite')
var objectStore = db.transaction([this.dbStoreName], 'readwrite')
.objectStore(this.dbStoreName);
var request = objectStore.put(b64string, fileName);
} catch(error) {
@ -230,8 +210,7 @@ class IdbFileStorage { @@ -230,8 +210,7 @@ class IdbFileStorage {
public getFile(fileName: string, size?: any): Promise<Blob> {
return this.openDatabase().then((db) => {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
var objectStore = db.transaction([this.dbStoreName], 'readonly')
.objectStore(this.dbStoreName);
var request = objectStore.get(fileName);
@ -257,8 +236,7 @@ class IdbFileStorage { @@ -257,8 +236,7 @@ class IdbFileStorage {
public getAllKeys(): Promise<Array<string>> {
console.time('getAllEntries');
return this.openDatabase().then((db) => {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
var objectStore = db.transaction([this.dbStoreName], 'readonly')
.objectStore(this.dbStoreName);
var request = objectStore.getAllKeys();
@ -278,8 +256,7 @@ class IdbFileStorage { @@ -278,8 +256,7 @@ class IdbFileStorage {
public isFileExists(fileName: string): Promise<boolean> {
console.time('isFileExists');
return this.openDatabase().then((db) => {
// @ts-ignore
var objectStore = db.transaction([this.dbStoreName], IDBTransaction.READ || 'readonly')
var objectStore = db.transaction([this.dbStoreName], 'readonly')
.objectStore(this.dbStoreName);
var request = objectStore.openCursor(fileName);
@ -307,6 +284,6 @@ class IdbFileStorage { @@ -307,6 +284,6 @@ class IdbFileStorage {
const idbFileStorage = new IdbFileStorage();
(window as any).IdbFileStorage = idbFileStorage;
//(window as any).IdbFileStorage = idbFileStorage;
export default idbFileStorage;

3
src/lib/mtproto/apiFileManager.ts

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

19
src/lib/mtproto/apiManager.ts

@ -6,10 +6,13 @@ import networkerFactory from './networkerFactory'; @@ -6,10 +6,13 @@ import networkerFactory from './networkerFactory';
import { telegramMeWebService } from './mtproto';
import authorizer from './authorizer';
import { isObject, tsNow, $rootScope } from '../utils';
import * as Config from '../config';
import {App, Modes} from './mtproto_config';
import dcConfigurator from './dcConfigurator';
import HTTP from './transports/http';
import { logger } from '../polyfill';
import passwordManager from './passwordManager';
console.error('apiManager included!');
export class ApiManager {
public cachedNetworkers: {[x: number]: MTPNetworker} = {};
@ -55,7 +58,7 @@ export class ApiManager { @@ -55,7 +58,7 @@ export class ApiManager {
public async logOut() {
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++) {
storageKeys.push(prefix + dcID + '_auth_key');
@ -124,7 +127,7 @@ export class ApiManager { @@ -124,7 +127,7 @@ export class ApiManager {
// mtpGetNetworker
public async getNetworker(dcID: number, options: any = {}): Promise<MTPNetworker> {
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;
if(!dcID) {
@ -315,7 +318,7 @@ export class ApiManager { @@ -315,7 +318,7 @@ export class ApiManager {
this.getNetworker(dcID, options).then(performRequest, rejectPromise);
} else {
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 { @@ -328,6 +331,14 @@ export class ApiManager {
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();

7
src/lib/mtproto/authorizer.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { TLSerialization, TLDeserialization } from "../tl_utils";
import { TLSerialization, TLDeserialization } from "./tl_utils";
import dcConfigurator from "./dcConfigurator";
import { dT, bytesToHex, bytesCmp, bytesFromHex, bytesXor } from "../bin_utils";
import rsaKeysManager from "./rsaKeysManager";
@ -9,11 +9,6 @@ import timeManager from "./timeManager"; @@ -9,11 +9,6 @@ import timeManager from "./timeManager";
import { BigInteger } from "jsbn";
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 fNonce: any = bytesFromHex('b597720d11faa5914ef485c529cde414').reverse();

11
src/lib/mtproto/dcConfigurator.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import Socket from './transports/websocket';
import MTTransport from './transports/transport';
import HTTP from './transports/http';
import { Modes } from './mtproto_config';
type Servers = {
[transport: string]: {
@ -20,7 +21,7 @@ type Servers = { @@ -20,7 +21,7 @@ type Servers = {
export class DcConfigurator {
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: 2, host: '149.154.167.40', port: 80},
@ -47,7 +48,7 @@ export class DcConfigurator { @@ -47,7 +48,7 @@ export class DcConfigurator {
};
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.chosenServers[transport];
@ -56,14 +57,14 @@ export class DcConfigurator { @@ -56,14 +57,14 @@ export class DcConfigurator {
if(transport == 'websocket') {
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;
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 path = Config.Modes.test ? 'apiw_test1' : 'apiw1';
let path = Modes.test ? 'apiw_test1' : 'apiw1';
chosenServer = 'https://' + subdomain + '.web.telegram.org/' + path;
return servers[dcID] = new HTTP(dcID, chosenServer);
}

15
src/lib/mtproto/mtproto.ts

@ -1,9 +1,8 @@ @@ -1,9 +1,8 @@
import * as Config from '../config';
import AppStorage from '../storage';
import {tsNow} from '../utils';
import { Modes, App } from './mtproto_config';
import PasswordManager from './passwordManager';
/* import PasswordManager from './passwordManager';
import DcConfigurator from './dcConfigurator';
import RSAKeysManager from './rsaKeysManager';
import TimeManager from './timeManager';
@ -11,11 +10,11 @@ import ServerTimeManager from './serverTimeManager'; @@ -11,11 +10,11 @@ import ServerTimeManager from './serverTimeManager';
import Authorizer from './authorizer';
import NetworkerFactory from './networkerFactory';
import ApiManager from './apiManager';
import ApiFileManager from './apiFileManager';
import ApiFileManager from './apiFileManager'; */
export class TelegramMeWebService {
public disabled = Config.Modes.test ||
Config.App.domains.indexOf(location.hostname) == -1 ||
public disabled = Modes.test ||
App.domains.indexOf(location.hostname) == -1 ||
location.protocol != 'http:' && location.protocol != 'https:' ||
location.protocol == 'https:' && location.hostname != 'web.telegram.org';
@ -54,7 +53,7 @@ export class TelegramMeWebService { @@ -54,7 +53,7 @@ export class TelegramMeWebService {
export const telegramMeWebService = new TelegramMeWebService();
export namespace MTProto {
/* export namespace MTProto {
//$($window).on('click keydown', rng_seed_time); // WARNING!
export const passwordManager = PasswordManager;
@ -68,4 +67,4 @@ export namespace MTProto { @@ -68,4 +67,4 @@ export namespace MTProto {
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 @@ @@ -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 @@ @@ -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 @@ @@ -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'; @@ -2,10 +2,10 @@ import {tsNow, isObject} from '../utils';
import {convertToUint8Array,
bufferConcat, nextRandomInt, bytesToHex, longToBytes,
bytesCmp, uintToInt, bigStringInt} from '../bin_utils';
import {TLDeserialization, TLSerialization} from '../tl_utils';
import {TLDeserialization, TLSerialization} from './tl_utils';
import CryptoWorker from '../crypto/cryptoworker';
import AppStorage from '../storage';
import * as Config from '../config';
import Schema from './schema';
import timeManager from './timeManager';
import NetworkerFactory from './networkerFactory';
@ -13,10 +13,9 @@ import dcConfigurator from './dcConfigurator'; @@ -13,10 +13,9 @@ import dcConfigurator from './dcConfigurator';
import Socket from './transports/websocket';
import HTTP from './transports/http';
import { logger } from '../polyfill';
import { Modes, App } from './mtproto_config';
/* const chromeMatches = navigator.userAgent.match(/Chrome\/(\d+(\.\d+)?)/);
const chromeVersion = chromeMatches && parseFloat(chromeMatches[1]) || false;
const xhrSendBuffer = !('ArrayBufferView' in window) && (chromeVersion > 0 && chromeVersion < 30);*/
console.error('networker included!', new Error().stack);
type Message = {
msg_id: string,
@ -103,15 +102,11 @@ class MTPNetworker { @@ -103,15 +102,11 @@ class MTPNetworker {
this.updateSession();
if(!NetworkerFactory.offlineInited) {
NetworkerFactory.offlineInited = true;
/* $rootScope.offline = true
$rootScope.offlineConnecting = true */
}
if(Config.Navigator.mobile) {
this.setupMobileSleep();
}
// if(!NetworkerFactory.offlineInited) {
// NetworkerFactory.offlineInited = true;
// /* $rootScope.offline = true
// $rootScope.offlineConnecting = true */
// }
this.transport = dcConfigurator.chooseServer(this.dcID, this.upload);
@ -131,25 +126,6 @@ class MTPNetworker { @@ -131,25 +126,6 @@ class MTPNetworker {
//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) {
var sentMessage = this.sentMessages[sentMessageID];
if(!sentMessage) {
@ -202,7 +178,7 @@ class MTPNetworker { @@ -202,7 +178,7 @@ class MTPNetworker {
body: serializer.getBytes()
};
if(Config.Modes.debug) {
if(Modes.debug) {
this.log('MT call', method, params, messageID, seqNo);
}
@ -221,7 +197,7 @@ class MTPNetworker { @@ -221,7 +197,7 @@ class MTPNetworker {
body: serializer.getBytes()
};
if(Config.Modes.debug) {
if(Modes.debug) {
this.log('MT message', object, messageID, seqNo);
}
@ -251,32 +227,32 @@ class MTPNetworker { @@ -251,32 +227,32 @@ class MTPNetworker {
if(!this.connectionInited) { // this will call once for each new session
///////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!');
serializer.storeInt(+invokeWithLayer.id >>> 0, 'invokeWithLayer');
// @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!');
serializer.storeInt(+initConnection.id >>> 0, 'initConnection');
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.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('', 'lang_pack');
serializer.storeString(navigator.language || 'en', 'lang_code');
//serializer.storeInt(0x0, 'proxy');
/* serializer.storeMethod('initConnection', {
'flags': 0,
'api_id': Config.App.id,
'api_id': App.id,
'device_model': navigator.userAgent || 'Unknown UserAgent',
'system_version': navigator.platform || 'Unknown Platform',
'app_version': Config.App.version,
'app_version': App.version,
'system_lang_code': navigator.language || 'en',
'lang_pack': '',
'lang_code': navigator.language || 'en'
@ -284,7 +260,7 @@ class MTPNetworker { @@ -284,7 +260,7 @@ class MTPNetworker {
}
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!');
this.log('Api call options.afterMessageID!');
@ -307,7 +283,7 @@ class MTPNetworker { @@ -307,7 +283,7 @@ class MTPNetworker {
isAPI: true
};
if(Config.Modes.debug/* || true */) {
if(Modes.debug/* || true */) {
this.log('Api call', method, message, params, options);
} else {
//////this.log('Api call', method);
@ -677,7 +653,7 @@ class MTPNetworker { @@ -677,7 +653,7 @@ class MTPNetworker {
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);
}
} else {
@ -698,7 +674,7 @@ class MTPNetworker { @@ -698,7 +674,7 @@ class MTPNetworker {
self.toggleOffline(false);
// this.log('parse for', message)
self.parseResponse(result).then((response) => {
if(Config.Modes.debug) {
if(Modes.debug) {
this.log('Server response', self.dcID, response);
}
@ -1194,7 +1170,7 @@ class MTPNetworker { @@ -1194,7 +1170,7 @@ class MTPNetworker {
}
} else {
if(deferred) {
if(Config.Modes.debug) {
if(Modes.debug) {
this.debug && this.log('Rpc response', message.result);
} else {
var dRes = message.result._;

14
src/lib/mtproto/networkerFactory.ts

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

16
src/lib/mtproto/passwordManager.ts

@ -1,9 +1,6 @@ @@ -1,9 +1,6 @@
import apiManager from "./apiManager";
import { bufferConcats, bytesToHex, bytesFromHex, bufferConcat, bytesXor } from "../bin_utils";
import CryptoWorker from "../crypto/cryptoworker";
import {str2bigInt, greater, isZero,
// @ts-ignore
bigInt2str, powMod, int2bigInt, mult, mod, sub, bitSize, negative, mult, add} from 'leemon';
@ -80,19 +77,6 @@ export class PasswordManager { @@ -80,19 +77,6 @@ export class PasswordManager {
}, 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) {
var passwordUTF8 = unescape(encodeURIComponent(password));

4
src/lib/mtproto/rsaKeysManager.ts

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

5
src/lib/mtproto/schema.ts

File diff suppressed because one or more lines are too long

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

@ -5,14 +5,14 @@ @@ -5,14 +5,14 @@
* https://github.com/zhukov/webogram/blob/master/LICENSE
*/
import {bigint, intToUint, bigStringInt, bytesToHex, gzipUncompress, uintToInt} from './bin_utils';
import {isObject} from './utils';
import * as Config from './config';
import {bigint, intToUint, bigStringInt, bytesToHex, gzipUncompress, uintToInt} from '../bin_utils';
import {isObject} from '../utils';
import Schema from './schema';
const boolFalse = +Config.Schema.API.constructors.find((c: any) => c.predicate == 'boolFalse').id >>> 0;
const boolTrue = +Config.Schema.API.constructors.find((c: any) => c.predicate == 'boolTrue').id >>> 0;
const vector = +Config.Schema.API.constructors.find((c: any) => c.predicate == 'vector').id >>> 0;
const gzipPacked = +Config.Schema.MTProto.constructors.find((c: any) => c.predicate == 'gzip_packed').id >>> 0;
const boolFalse = +Schema.API.constructors.find((c: any) => c.predicate == 'boolFalse').id >>> 0;
const boolTrue = +Schema.API.constructors.find((c: any) => c.predicate == 'boolTrue').id >>> 0;
const vector = +Schema.API.constructors.find((c: any) => c.predicate == 'vector').id >>> 0;
const gzipPacked = +Schema.MTProto.constructors.find((c: any) => c.predicate == 'gzip_packed').id >>> 0;
//console.log('boolFalse', boolFalse == 0xbc799737);
@ -20,7 +20,7 @@ class TLSerialization { @@ -20,7 +20,7 @@ class TLSerialization {
public maxLength = 2048; // 2Kb
public offset = 0; // in bytes
public mtproto = false;
private debug = false;//Config.Modes.debug;
private debug = false;//Modes.debug;
public buffer: ArrayBuffer;
public intView: Int32Array;
@ -229,7 +229,7 @@ class TLSerialization { @@ -229,7 +229,7 @@ class TLSerialization {
}
public storeMethod(methodName: string, params: any) {
var schema = this.mtproto ? Config.Schema.MTProto : Config.Schema.API;
var schema = this.mtproto ? Schema.MTProto : Schema.API;
var methodData: any = false,
i;
@ -316,7 +316,7 @@ class TLSerialization { @@ -316,7 +316,7 @@ class TLSerialization {
throw new Error('Invalid object for type ' + type);
}
var schema = this.mtproto ? Config.Schema.MTProto : Config.Schema.API;
var schema = this.mtproto ? Schema.MTProto : Schema.API;
var predicate = obj['_'];
var isBare = false;
var constructorData: any = false;
@ -402,7 +402,7 @@ class TLDeserialization { @@ -402,7 +402,7 @@ class TLDeserialization {
this.override = 'override' in options ? options.override : {};
this.mtproto = 'mtproto' in options ? options.mtproto : false;
this.debug = options.debug !== undefined ? options.debug : /* Config.Modes.debug */false;
this.debug = options.debug !== undefined ? options.debug : /* Modes.debug */false;
}
public readInt(field: string) {
@ -621,7 +621,7 @@ class TLDeserialization { @@ -621,7 +621,7 @@ class TLDeserialization {
return result;
}
var schema = (this.mtproto ? Config.Schema.MTProto : Config.Schema.API) as any;
var schema = (this.mtproto ? Schema.MTProto : Schema.API) as any;
var predicate = false;
var constructorData: any = false;
@ -675,7 +675,7 @@ class TLDeserialization { @@ -675,7 +675,7 @@ class TLDeserialization {
var fallback = false;
if(!constructorData && this.mtproto) {
var schemaFallback = Config.Schema.API;
var schemaFallback = Schema.API;
for(i = 0; i < schemaFallback.constructors.length; i++) {
if(+schemaFallback.constructors[i].id == constructorCmp) {
constructorData = schemaFallback.constructors[i];

1
src/lib/richtextprocessor.js

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

209
src/lib/storage.ts

@ -1,26 +1,205 @@ @@ -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 {
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) {
ConfigStorage.prefix(newPrefix);
configStorage.keyPrefix = newPrefix;
}
public noPrefix() {
ConfigStorage.noPrefix();
configStorage.noPrefix = true;
}
private proxy<T>(methodName: string, ..._args: any[]) {
let args = Array.prototype.slice.call(_args);
public finishTask(taskID: number, result: any) {
this.tasks[taskID](result);
delete this.tasks[taskID];
}
let promise = new Promise<T>((resolve, reject) => {
args.push((result: T) => {
resolve(result);
});
private proxy<T>(methodName: string, ..._args: any[]) {
return new Promise<T>((resolve, reject) => {
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[]) {
@ -39,12 +218,6 @@ class AppStorage { @@ -39,12 +218,6 @@ class AppStorage {
public clear<T>(...args: any[]) {
return this.proxy<T>('clear', ...args);
}
constructor() {
if(Modes.test) {
this.setPrefix('t_');
}
}
}
export default new AppStorage();

6
src/lib/utils.js

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

14
src/pages/pageAuthCode.ts

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

47
src/pages/pagePassword.ts

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

26
src/pages/pageSignIn.ts

@ -1,12 +1,14 @@ @@ -1,12 +1,14 @@
import { putPreloader, formatPhoneNumber } from "../components/misc";
import Scrollable from '../components/scrollable';
import {RichTextProcessor} from '../lib/richtextprocessor';
import * as Config from '../lib/config';
import Config from '../lib/config';
import { findUpTag } from "../lib/utils";
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 { App, Modes } from "../lib/mtproto/mtproto_config";
type Country = {
name: string,
@ -21,6 +23,18 @@ type Country = { @@ -21,6 +23,18 @@ type Country = {
let btnNext: HTMLButtonElement = null;
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[] = Config.Countries.filter(c => c.emoji).sort((a, b) => a.name.localeCompare(b.name));
@ -189,15 +203,15 @@ let onFirstMount = () => { @@ -189,15 +203,15 @@ let onFirstMount = () => {
let phone_number = telEl.value;
apiManager.invokeApi('auth.sendCode', {
/* flags: 0, */
//flags: 0,
phone_number: phone_number,
api_id: Config.App.id,
api_hash: Config.App.hash,
api_id: App.id,
api_hash: App.hash,
settings: {
_: 'codeSettings', // that's how we sending Type
flags: 0
}
/* lang_code: navigator.language || 'en' */
//lang_code: navigator.language || 'en'
}).then((code: any) => {
console.log('got code', code);

3
src/pages/pageSignUp.ts

@ -1,7 +1,8 @@ @@ -1,7 +1,8 @@
import {putPreloader} from '../components/misc';
import resizeableImage from '../lib/cropper';
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 Page from './page';

26517
stats.json

File diff suppressed because one or more lines are too long

2
tsconfig.json

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

12
webpack.common.js

@ -3,6 +3,13 @@ const HtmlWebpackPlugin = require('html-webpack-plugin'); @@ -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'];
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: {
rules: [
@ -31,7 +38,10 @@ module.exports = { @@ -31,7 +38,10 @@ module.exports = {
},
{
test: /\.ts?$/,
use: 'ts-loader',
use: [
'ts-loader',
{ loader: "ifdef-loader", options: opts }
],
exclude: /node_modules/,
},
{

Loading…
Cancel
Save