no comments
This commit is contained in:
parent
04442dcffa
commit
e0999ad4d0
44
package.json
44
package.json
@ -19,64 +19,64 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsbn": "^1.1.0",
|
"jsbn": "^1.1.0",
|
||||||
"webpack-dev-server": "^3.11.0"
|
"webpack-dev-server": "^3.11.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.12.1",
|
"@babel/cli": "^7.12.13",
|
||||||
"@babel/core": "^7.12.3",
|
"@babel/core": "^7.12.13",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
||||||
"@babel/plugin-transform-typescript": "^7.12.1",
|
"@babel/plugin-transform-typescript": "^7.12.13",
|
||||||
"@babel/polyfill": "^7.12.1",
|
"@babel/polyfill": "^7.12.1",
|
||||||
"@babel/preset-env": "^7.12.1",
|
"@babel/preset-env": "^7.12.13",
|
||||||
"@babel/preset-es2015": "^7.0.0-beta.53",
|
"@babel/preset-es2015": "^7.0.0-beta.53",
|
||||||
"@babel/preset-typescript": "^7.12.1",
|
"@babel/preset-typescript": "^7.12.13",
|
||||||
"@cryptography/aes": "^0.1.1",
|
"@cryptography/aes": "^0.1.1",
|
||||||
"@cryptography/sha1": "^0.1.0",
|
"@cryptography/sha1": "^0.1.0",
|
||||||
"@cryptography/sha256": "^0.2.0",
|
"@cryptography/sha256": "^0.2.0",
|
||||||
"@peculiar/webcrypto": "^1.1.3",
|
"@peculiar/webcrypto": "^1.1.6",
|
||||||
"@types/aes-js": "^3.1.1",
|
"@types/aes-js": "^3.1.1",
|
||||||
"@types/chrome": "0.0.91",
|
"@types/chrome": "0.0.91",
|
||||||
"@types/jest": "^24.9.1",
|
"@types/jest": "^24.9.1",
|
||||||
"@types/serviceworker-webpack-plugin": "^1.0.1",
|
"@types/serviceworker-webpack-plugin": "^1.0.1",
|
||||||
"aes-js": "^3.1.2",
|
"aes-js": "^3.1.2",
|
||||||
"autoprefixer": "^9.8.0",
|
"autoprefixer": "^9.8.6",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^24.9.0",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"compression-webpack-plugin": "^3.1.0",
|
"compression-webpack-plugin": "^3.1.0",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.8.3",
|
||||||
"css-loader": "^3.5.3",
|
"css-loader": "^3.6.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"fast-png": "^5.0.2",
|
"fast-png": "^5.0.3",
|
||||||
"handlebars": "^4.7.6",
|
"handlebars": "^4.7.6",
|
||||||
"handlebars-loader": "^1.7.1",
|
"handlebars-loader": "^1.7.1",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"ifdef-loader": "^2.1.5",
|
"ifdef-loader": "^2.1.5",
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"jest": "^24.9.0",
|
"jest": "^24.9.0",
|
||||||
"media-query-plugin": "^1.3.1",
|
"media-query-plugin": "^1.4.0",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
"npm": "^6.14.10",
|
"npm": "^6.14.11",
|
||||||
"on-build-webpack": "^0.1.0",
|
"on-build-webpack": "^0.1.0",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||||
"pako": "^1.0.11",
|
"pako": "^1.0.11",
|
||||||
"postcss": "^7.0.32",
|
"postcss": "^7.0.35",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"postcss-preset-env": "^6.7.0",
|
"postcss-preset-env": "^6.7.0",
|
||||||
"qr-code-styling": "^1.0.1",
|
"qr-code-styling": "^1.3.4",
|
||||||
"resolve-url-loader": "^3.1.2",
|
"resolve-url-loader": "^3.1.2",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"serviceworker-webpack-plugin": "^1.0.1",
|
"serviceworker-webpack-plugin": "^1.0.1",
|
||||||
"style-loader": "^1.2.1",
|
"style-loader": "^1.3.0",
|
||||||
"terser-webpack-plugin": "^3.0.2",
|
"terser-webpack-plugin": "^3.1.0",
|
||||||
"ts-jest": "^24.3.0",
|
"ts-jest": "^24.3.0",
|
||||||
"ts-loader": "^6.2.2",
|
"ts-loader": "^6.2.2",
|
||||||
"typescript": "^3.9.7",
|
"typescript": "^3.9.7",
|
||||||
"url-loader": "^2.3.0",
|
"url-loader": "^2.3.0",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-merge": "^4.2.2",
|
"webpack-merge": "^4.2.2",
|
||||||
"worker-loader": "^2.0.0"
|
"worker-loader": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
import rootScope from "../../lib/rootScope";
|
import rootScope from "../../lib/rootScope";
|
||||||
import { generatePathData } from "../../helpers/dom";
|
//import { generatePathData } from "../../helpers/dom";
|
||||||
import { MyMessage } from "../../lib/appManagers/appMessagesManager";
|
import { MyMessage } from "../../lib/appManagers/appMessagesManager";
|
||||||
import Chat from "./chat";
|
import Chat from "./chat";
|
||||||
|
|
||||||
type Group = {bubble: HTMLDivElement, mid: number, timestamp: number}[];
|
type Group = {bubble: HTMLElement, mid: number, timestamp: number}[];
|
||||||
type BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};
|
type BubbleGroup = {timestamp: number, fromId: number, mid: number, group: Group};
|
||||||
export default class BubbleGroups {
|
export default class BubbleGroups {
|
||||||
private bubbles: Array<BubbleGroup> = []; // map to group
|
private bubbles: Array<BubbleGroup> = []; // map to group
|
||||||
|
private detailsMap: Map<HTMLElement, BubbleGroup> = new Map();
|
||||||
private groups: Array<Group> = [];
|
private groups: Array<Group> = [];
|
||||||
//updateRAFs: Map<HTMLDivElement[], number> = new Map();
|
//updateRAFs: Map<HTMLElement[], number> = new Map();
|
||||||
private newGroupDiff = 121; // * 121 in scheduled messages
|
private newGroupDiff = 121; // * 121 in scheduled messages
|
||||||
|
|
||||||
constructor(private chat: Chat) {
|
constructor(private chat: Chat) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeBubble(bubble: HTMLDivElement, mid: number) {
|
removeBubble(bubble: HTMLElement) {
|
||||||
const details = this.bubbles.findAndSplice(g => g.mid === mid);
|
const details = this.detailsMap.get(bubble);
|
||||||
if(details && details.group.length) {
|
if(details && details.group.length) {
|
||||||
details.group.findAndSplice(d => d.bubble === bubble);
|
details.group.findAndSplice(d => d.bubble === bubble);
|
||||||
if(!details.group.length) {
|
if(!details.group.length) {
|
||||||
@ -27,7 +28,7 @@ export default class BubbleGroups {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addBubble(bubble: HTMLDivElement, message: MyMessage, reverse: boolean) {
|
addBubble(bubble: HTMLElement, message: MyMessage, reverse: boolean) {
|
||||||
//return;
|
//return;
|
||||||
|
|
||||||
const timestamp = message.date;
|
const timestamp = message.date;
|
||||||
@ -41,7 +42,7 @@ export default class BubbleGroups {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to find added
|
// try to find added
|
||||||
//this.removeBubble(message.mid);
|
this.removeBubble(bubble);
|
||||||
|
|
||||||
const insertObject = {bubble, mid, timestamp};
|
const insertObject = {bubble, mid, timestamp};
|
||||||
if(this.bubbles.length) {
|
if(this.bubbles.length) {
|
||||||
@ -105,28 +106,24 @@ export default class BubbleGroups {
|
|||||||
|
|
||||||
//console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);
|
//console.log('[BUBBLE]: addBubble', bubble, message.mid, fromId, reverse, group);
|
||||||
|
|
||||||
if(mid > 0) {
|
const bubbleGroup = {timestamp, fromId, mid: message.mid, group};
|
||||||
let insertIndex = 0;
|
let insertIndex = 0;
|
||||||
for(; insertIndex < this.bubbles.length; ++insertIndex) {
|
for(; insertIndex < this.bubbles.length; ++insertIndex) {
|
||||||
if(this.bubbles[insertIndex].mid < mid) {
|
if(this.bubbles[insertIndex].mid < mid) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bubbles.splice(insertIndex, 0, {timestamp, fromId, mid: message.mid, group});
|
|
||||||
} else {
|
|
||||||
this.bubbles.unshift({timestamp, fromId, mid: message.mid, group});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.bubbles.push({timestamp, fromId, mid: message.mid, group});
|
this.bubbles.splice(insertIndex, 0, {timestamp, fromId, mid: message.mid, group});
|
||||||
this.updateGroup(group);
|
this.updateGroup(group);
|
||||||
|
|
||||||
|
this.detailsMap.set(bubble, bubbleGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
setClipIfNeeded(bubble: HTMLDivElement, remove = false) {
|
/* setClipIfNeeded(bubble: HTMLDivElement, remove = false) {
|
||||||
//console.log('setClipIfNeeded', bubble, remove);
|
//console.log('setClipIfNeeded', bubble, remove);
|
||||||
const className = bubble.className;
|
const className = bubble.className;
|
||||||
if(className.includes('is-message-empty')/* && !className.includes('is-reply') */
|
if(className.includes('is-message-empty') && (className.includes('photo') || className.includes('video'))) {
|
||||||
&& (className.includes('photo') || className.includes('video'))) {
|
|
||||||
let container = bubble.querySelector('.bubble__media-container') as SVGSVGElement;
|
let container = bubble.querySelector('.bubble__media-container') as SVGSVGElement;
|
||||||
//console.log('setClipIfNeeded', bubble, remove, container);
|
//console.log('setClipIfNeeded', bubble, remove, container);
|
||||||
if(!container) return;
|
if(!container) return;
|
||||||
@ -171,7 +168,7 @@ export default class BubbleGroups {
|
|||||||
});
|
});
|
||||||
} catch(err) {}
|
} catch(err) {}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
updateGroup(group: Group) {
|
updateGroup(group: Group) {
|
||||||
/* if(this.updateRAFs.has(group)) {
|
/* if(this.updateRAFs.has(group)) {
|
||||||
@ -192,25 +189,25 @@ export default class BubbleGroups {
|
|||||||
|
|
||||||
if(group.length === 1) {
|
if(group.length === 1) {
|
||||||
first.classList.add('is-group-first', 'is-group-last');
|
first.classList.add('is-group-first', 'is-group-last');
|
||||||
this.setClipIfNeeded(first);
|
//this.setClipIfNeeded(first);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
first.classList.remove('is-group-last');
|
first.classList.remove('is-group-last');
|
||||||
first.classList.add('is-group-first');
|
first.classList.add('is-group-first');
|
||||||
this.setClipIfNeeded(first, true);
|
//this.setClipIfNeeded(first, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const length = group.length - 1;
|
const length = group.length - 1;
|
||||||
for(let i = 1; i < length; ++i) {
|
for(let i = 1; i < length; ++i) {
|
||||||
const bubble = group[i].bubble;
|
const bubble = group[i].bubble;
|
||||||
bubble.classList.remove('is-group-last', 'is-group-first');
|
bubble.classList.remove('is-group-last', 'is-group-first');
|
||||||
this.setClipIfNeeded(bubble, true);
|
//this.setClipIfNeeded(bubble, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const last = group[group.length - 1].bubble;
|
const last = group[group.length - 1].bubble;
|
||||||
last.classList.remove('is-group-first');
|
last.classList.remove('is-group-first');
|
||||||
last.classList.add('is-group-last');
|
last.classList.add('is-group-last');
|
||||||
this.setClipIfNeeded(last);
|
//this.setClipIfNeeded(last);
|
||||||
//}));
|
//}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +221,7 @@ export default class BubbleGroups {
|
|||||||
cleanup() {
|
cleanup() {
|
||||||
this.bubbles = [];
|
this.bubbles = [];
|
||||||
this.groups = [];
|
this.groups = [];
|
||||||
|
this.detailsMap.clear();
|
||||||
/* for(let value of this.updateRAFs.values()) {
|
/* for(let value of this.updateRAFs.values()) {
|
||||||
window.cancelAnimationFrame(value);
|
window.cancelAnimationFrame(value);
|
||||||
}
|
}
|
||||||
|
@ -152,12 +152,9 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
const message = this.chat.getMessage(mid);
|
const message = this.chat.getMessage(mid);
|
||||||
//bubble.remove();
|
//bubble.remove();
|
||||||
this.bubbleGroups.removeBubble(bubble, message.mid);
|
|
||||||
this.setBubblePosition(bubble, message, false);
|
this.setBubblePosition(bubble, message, false);
|
||||||
//this.log('history_update', this.bubbles[mid], mid, message);
|
//this.log('history_update', this.bubbles[mid], mid, message);
|
||||||
|
|
||||||
this.bubbleGroups.addBubble(bubble, message, false);
|
|
||||||
|
|
||||||
if(this.scrollingToNewBubble) {
|
if(this.scrollingToNewBubble) {
|
||||||
this.scrollToNewLastBubble();
|
this.scrollToNewLastBubble();
|
||||||
}
|
}
|
||||||
@ -268,8 +265,6 @@ export default class ChatBubbles {
|
|||||||
//});
|
//});
|
||||||
|
|
||||||
bubble.dataset.mid = '' + mid;
|
bubble.dataset.mid = '' + mid;
|
||||||
|
|
||||||
this.bubbleGroups.removeBubble(bubble, tempId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.unreadOut.has(tempId)) {
|
if(this.unreadOut.has(tempId)) {
|
||||||
@ -423,7 +418,7 @@ export default class ChatBubbles {
|
|||||||
const msgIdsByPeer = e;
|
const msgIdsByPeer = e;
|
||||||
|
|
||||||
if(!(this.peerId in msgIdsByPeer)) return;
|
if(!(this.peerId in msgIdsByPeer)) return;
|
||||||
const msgIds = msgIdsByPeer[this.peerId];
|
const msgIds = (msgIdsByPeer[this.peerId] as number[]).slice().sort((a, b) => b - a);
|
||||||
this.renderNewMessagesByIds(msgIds);
|
this.renderNewMessagesByIds(msgIds);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1147,7 +1142,7 @@ export default class ChatBubbles {
|
|||||||
this.firstUnreadBubble = null;
|
this.firstUnreadBubble = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bubbleGroups.removeBubble(bubble, mid);
|
this.bubbleGroups.removeBubble(bubble);
|
||||||
if(this.unreadedObserver) {
|
if(this.unreadedObserver) {
|
||||||
this.unreadedObserver.unobserve(bubble);
|
this.unreadedObserver.unobserve(bubble);
|
||||||
}
|
}
|
||||||
@ -1691,6 +1686,8 @@ export default class ChatBubbles {
|
|||||||
dateMessage.container.append(bubble);
|
dateMessage.container.append(bubble);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.bubbleGroups.addBubble(bubble, message, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// * will change .cleaned in cleanup() and new instance will be created
|
// * will change .cleaned in cleanup() and new instance will be created
|
||||||
@ -1779,16 +1776,8 @@ export default class ChatBubbles {
|
|||||||
bubble.remove(); // * for positionElementByIndex
|
bubble.remove(); // * for positionElementByIndex
|
||||||
} */
|
} */
|
||||||
|
|
||||||
if(!sameMid || updatePosition) {
|
|
||||||
this.bubbleGroups.removeBubble(bubble, originalMid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!sameMid) {
|
if(!sameMid) {
|
||||||
delete this.bubbles[originalMid];
|
delete this.bubbles[originalMid];
|
||||||
|
|
||||||
if(!updatePosition) {
|
|
||||||
this.bubbleGroups.addBubble(bubble, message, reverse);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bubble.innerHTML = '';
|
//bubble.innerHTML = '';
|
||||||
@ -1815,9 +1804,7 @@ export default class ChatBubbles {
|
|||||||
if(updatePosition) {
|
if(updatePosition) {
|
||||||
this.renderMessagesQueue(message, bubble, reverse, loadPromises);
|
this.renderMessagesQueue(message, bubble, reverse, loadPromises);
|
||||||
|
|
||||||
if(!message.pFlags.is_single) { // * Ignore 'Discussion started'
|
if(message.pFlags.is_single) { // * Ignore 'Discussion started'
|
||||||
this.bubbleGroups.addBubble(bubble, message, reverse);
|
|
||||||
} else {
|
|
||||||
bubble.classList.add('is-group-last');
|
bubble.classList.add('is-group-last');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2452,13 +2439,7 @@ export default class ChatBubbles {
|
|||||||
|
|
||||||
bubble.classList.add(isOut ? 'is-out' : 'is-in');
|
bubble.classList.add(isOut ? 'is-out' : 'is-in');
|
||||||
if(updatePosition) {
|
if(updatePosition) {
|
||||||
if(!isThreadStarter) {
|
|
||||||
this.bubbleGroups.addBubble(bubble, message, reverse);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.renderMessagesQueue(message, bubble, reverse, loadPromises);
|
this.renderMessagesQueue(message, bubble, reverse, loadPromises);
|
||||||
} else {
|
|
||||||
this.bubbleGroups.updateGroupByMessageId(message.mid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(withReplies) {
|
if(withReplies) {
|
||||||
|
@ -215,7 +215,7 @@ export default class ChatContextMenu {
|
|||||||
icon: 'link',
|
icon: 'link',
|
||||||
text: 'Copy Link',
|
text: 'Copy Link',
|
||||||
onClick: this.onCopyLinkClick,
|
onClick: this.onCopyLinkClick,
|
||||||
verify: () => this.appPeersManager.isChannel(this.peerId)
|
verify: () => this.appPeersManager.isChannel(this.peerId) && !this.message.pFlags.is_outgoing
|
||||||
}, {
|
}, {
|
||||||
icon: 'pin',
|
icon: 'pin',
|
||||||
text: 'Pin',
|
text: 'Pin',
|
||||||
|
@ -3313,7 +3313,7 @@ export class AppMessagesManager {
|
|||||||
} as any,
|
} as any,
|
||||||
id: this.generateMessageId(message.id, true),
|
id: this.generateMessageId(message.id, true),
|
||||||
date: message.date,
|
date: message.date,
|
||||||
from_id: message.from_id,
|
from_id: {_: 'peerUser', user_id: 0}/* message.from_id */,
|
||||||
peer_id: message.peer_id,
|
peer_id: message.peer_id,
|
||||||
action: {
|
action: {
|
||||||
_: 'messageActionCustomAction',
|
_: 'messageActionCustomAction',
|
||||||
|
@ -156,7 +156,7 @@ export class AppStateManager extends EventListenerBase<{
|
|||||||
if(state) {
|
if(state) {
|
||||||
if(state.version !== STATE_VERSION) {
|
if(state.version !== STATE_VERSION) {
|
||||||
state = copy(STATE_INIT);
|
state = copy(STATE_INIT);
|
||||||
} else if((state.stateCreatedTime + REFRESH_EVERY) < time/* && false */) {
|
} else if((state.stateCreatedTime + REFRESH_EVERY) < time/* || true *//* && false */) {
|
||||||
if(DEBUG) {
|
if(DEBUG) {
|
||||||
this.log('will refresh state', state.stateCreatedTime, time);
|
this.log('will refresh state', state.stateCreatedTime, time);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,9 @@ export class AppUsersManager {
|
|||||||
this.pushContact(userId);
|
this.pushContact(userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.contactsFillPromise = Promise.resolve(this.contactsList);
|
if(this.contactsList.size) {
|
||||||
|
this.contactsFillPromise = Promise.resolve(this.contactsList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -605,7 +607,7 @@ export class AppUsersManager {
|
|||||||
return apiManager.invokeApi('contacts.getTopPeers', {
|
return apiManager.invokeApi('contacts.getTopPeers', {
|
||||||
correspondents: true,
|
correspondents: true,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
limit: 30,
|
limit: 15,
|
||||||
hash: 0,
|
hash: 0,
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
let peerIds: number[] = [];
|
let peerIds: number[] = [];
|
||||||
|
@ -16,7 +16,7 @@ import { addPadding, bytesFromBigInt } from '../mtproto/bin_utils';
|
|||||||
import { bytesToWordss, bytesFromWordss, bytesToHex, bytesFromHex } from '../../helpers/bytes';
|
import { bytesToWordss, bytesFromWordss, bytesToHex, bytesFromHex } from '../../helpers/bytes';
|
||||||
import { nextRandomInt } from '../../helpers/random';
|
import { nextRandomInt } from '../../helpers/random';
|
||||||
|
|
||||||
export function longToBytes(sLong: string) {
|
export function longToBytes(sLong: string): Array<number> {
|
||||||
/* let perf = performance.now();
|
/* let perf = performance.now();
|
||||||
for(let i = 0; i < 1000000; ++i) {
|
for(let i = 0; i < 1000000; ++i) {
|
||||||
bytesFromWords({words: longToInts(sLong), sigBytes: 8}).reverse();
|
bytesFromWords({words: longToInts(sLong), sigBytes: 8}).reverse();
|
||||||
|
@ -157,12 +157,12 @@ export class ApiManager {
|
|||||||
|
|
||||||
// mtpGetNetworker
|
// mtpGetNetworker
|
||||||
public getNetworker(dcId: number, options: InvokeApiOptions = {}): Promise<MTPNetworker> {
|
public getNetworker(dcId: number, options: InvokeApiOptions = {}): Promise<MTPNetworker> {
|
||||||
const connectionType: ConnectionType = options.fileDownload ? 'download' : (options.fileUpload ? 'upload' : 'client');
|
//const connectionType: ConnectionType = options.fileDownload ? 'download' : (options.fileUpload ? 'upload' : 'client');
|
||||||
//const connectionType: ConnectionType = 'client';
|
const connectionType: ConnectionType = 'client';
|
||||||
|
|
||||||
/// #if MTPROTO_HTTP_UPLOAD
|
/// #if MTPROTO_HTTP_UPLOAD
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const transportType: TransportType = connectionType === 'upload' && isSafari ? 'https' : 'websocket';
|
const transportType: TransportType = connectionType === 'upload' && isSafari && false ? 'https' : 'websocket';
|
||||||
//const transportType: TransportType = connectionType !== 'client' ? 'https' : 'websocket';
|
//const transportType: TransportType = connectionType !== 'client' ? 'https' : 'websocket';
|
||||||
/// #else
|
/// #else
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -183,7 +183,7 @@ export class ApiManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const networkers = cache[dcId];
|
const networkers = cache[dcId];
|
||||||
if(networkers.length >= /* 1 */(connectionType === 'client' || transportType === 'https' ? 1 : (connectionType === 'download' ? 3 : 3))) {
|
if(networkers.length >= /* 1 */(connectionType === 'client' || transportType === 'https' ? 1 : (connectionType === 'download' ? 3 : 1))) {
|
||||||
let i = networkers.length - 1, found = false;
|
let i = networkers.length - 1, found = false;
|
||||||
for(; i >= 0; --i) {
|
for(; i >= 0; --i) {
|
||||||
if(networkers[i].isOnline) {
|
if(networkers[i].isOnline) {
|
||||||
|
@ -34,3 +34,33 @@ export const Database = {
|
|||||||
|
|
||||||
export const DEBUG = process.env.NODE_ENV !== 'production' || Modes.debug;
|
export const DEBUG = process.env.NODE_ENV !== 'production' || Modes.debug;
|
||||||
export const MOUNT_CLASS_TO: any = DEBUG ? (typeof(window) !== 'undefined' ? window : self) : null;
|
export const MOUNT_CLASS_TO: any = DEBUG ? (typeof(window) !== 'undefined' ? window : self) : null;
|
||||||
|
|
||||||
|
export const superDebug = (object: any, key: string) => {
|
||||||
|
var d = object[key];
|
||||||
|
var beforeStr = '', afterStr = '';
|
||||||
|
for(var r of d) {
|
||||||
|
beforeStr += r.before.hex + '\n';
|
||||||
|
afterStr += r.after.hex + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeStr = beforeStr.trim();
|
||||||
|
afterStr = afterStr.trim();
|
||||||
|
//var beforeStr = d.map(r => r.before.hex).join('\n');
|
||||||
|
//var afterStr = d.map(r => r.after.hex).join('\n');
|
||||||
|
|
||||||
|
var dada = (name: string, str: string) => {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.target = '_blank';
|
||||||
|
a.download = name + '.txt';
|
||||||
|
a.href = URL.createObjectURL(new Blob([str], {
|
||||||
|
type: 'text/plain'
|
||||||
|
}));
|
||||||
|
document.body.append(a);
|
||||||
|
a.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
dada(key + '_' + 'before', beforeStr);
|
||||||
|
dada(key + '_' + 'after', afterStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.superDebug = superDebug);
|
||||||
|
@ -124,7 +124,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
|
|||||||
//const worker = window;
|
//const worker = window;
|
||||||
worker.addEventListener('message', (e) => {
|
worker.addEventListener('message', (e) => {
|
||||||
if(!this.worker) {
|
if(!this.worker) {
|
||||||
this.worker = worker;
|
this.worker = worker as any;
|
||||||
this.log('set webWorker');
|
this.log('set webWorker');
|
||||||
|
|
||||||
if(USE_WORKER_AS_WORKER) {
|
if(USE_WORKER_AS_WORKER) {
|
||||||
|
@ -100,8 +100,9 @@ export default class MTPNetworker {
|
|||||||
/// #endif
|
/// #endif
|
||||||
|
|
||||||
private seqNo: number = 0;
|
private seqNo: number = 0;
|
||||||
private prevSessionId: Array<number> = [];
|
private prevSessionId: Uint8Array;
|
||||||
private sessionId: Array<number> = [];
|
private sessionId: Uint8Array;
|
||||||
|
private serverSalt: Uint8Array;
|
||||||
|
|
||||||
private lastResendReq: {
|
private lastResendReq: {
|
||||||
req_msg_id: string,
|
req_msg_id: string,
|
||||||
@ -119,9 +120,12 @@ export default class MTPNetworker {
|
|||||||
private tt = 0;
|
private tt = 0;
|
||||||
//public onConnectionStatusChange: (online: boolean) => void;
|
//public onConnectionStatusChange: (online: boolean) => void;
|
||||||
|
|
||||||
|
private debugRequests: Array<{before: Uint8Array, after: Uint8Array}> = [];
|
||||||
|
|
||||||
constructor(public dcId: number, private authKey: number[], private authKeyId: Uint8Array,
|
constructor(public dcId: number, private authKey: number[], private authKeyId: Uint8Array,
|
||||||
private serverSalt: number[], private transport: MTTransport, options: InvokeApiOptions = {}) {
|
serverSalt: number[], private transport: MTTransport, options: InvokeApiOptions = {}) {
|
||||||
this.authKeyUint8 = convertToUint8Array(this.authKey);
|
this.authKeyUint8 = convertToUint8Array(this.authKey);
|
||||||
|
this.serverSalt = convertToUint8Array(serverSalt);
|
||||||
|
|
||||||
this.isFileUpload = !!options.fileUpload;
|
this.isFileUpload = !!options.fileUpload;
|
||||||
this.isFileDownload = !!options.fileDownload;
|
this.isFileDownload = !!options.fileDownload;
|
||||||
@ -179,7 +183,7 @@ export default class MTPNetworker {
|
|||||||
public updateSession() {
|
public updateSession() {
|
||||||
this.seqNo = 0;
|
this.seqNo = 0;
|
||||||
this.prevSessionId = this.sessionId;
|
this.prevSessionId = this.sessionId;
|
||||||
this.sessionId = [...new Uint8Array(8).randomize()];
|
this.sessionId = new Uint8Array(8).randomize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateSentMessage(sentMessageId: string) {
|
public updateSentMessage(sentMessageId: string) {
|
||||||
@ -231,7 +235,7 @@ export default class MTPNetworker {
|
|||||||
const message = {
|
const message = {
|
||||||
msg_id: messageId,
|
msg_id: messageId,
|
||||||
seq_no: seqNo,
|
seq_no: seqNo,
|
||||||
body: serializer.getBytes()
|
body: serializer.getBytes(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Modes.debug) {
|
if(Modes.debug) {
|
||||||
@ -250,7 +254,7 @@ export default class MTPNetworker {
|
|||||||
const message = {
|
const message = {
|
||||||
msg_id: messageId,
|
msg_id: messageId,
|
||||||
seq_no: seqNo,
|
seq_no: seqNo,
|
||||||
body: serializer.getBytes()
|
body: serializer.getBytes(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Modes.debug) {
|
if(Modes.debug) {
|
||||||
@ -335,7 +339,7 @@ export default class MTPNetworker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private sendPingDelayDisconnect = () => {
|
private sendPingDelayDisconnect = () => {
|
||||||
if(this.pingPromise) return;
|
if(this.pingPromise || true) return;
|
||||||
|
|
||||||
if(!this.isOnline) {
|
if(!this.isOnline) {
|
||||||
if((this.transport as Socket).connected) {
|
if((this.transport as Socket).connected) {
|
||||||
@ -667,28 +671,28 @@ export default class MTPNetworker {
|
|||||||
this.scheduleRequest(delay);
|
this.scheduleRequest(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * correct, fully checked
|
||||||
public async getMsgKey(dataWithPadding: ArrayBuffer, isOut: boolean) {
|
public async getMsgKey(dataWithPadding: ArrayBuffer, isOut: boolean) {
|
||||||
const authKey = this.authKeyUint8;
|
|
||||||
const x = isOut ? 0 : 8
|
const x = isOut ? 0 : 8
|
||||||
const msgKeyLargePlain = bufferConcat(authKey.subarray(88 + x, 88 + x + 32), dataWithPadding);
|
const msgKeyLargePlain = bufferConcat(this.authKeyUint8.subarray(88 + x, 88 + x + 32), dataWithPadding);
|
||||||
|
|
||||||
const msgKeyLarge = await CryptoWorker.sha256Hash(msgKeyLargePlain);
|
const msgKeyLarge = await CryptoWorker.sha256Hash(msgKeyLargePlain);
|
||||||
const msgKey = new Uint8Array(msgKeyLarge).subarray(8, 24);
|
const msgKey = new Uint8Array(msgKeyLarge).subarray(8, 24);
|
||||||
return msgKey;
|
return msgKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// * correct, fully checked
|
||||||
public getAesKeyIv(msgKey: Uint8Array | number[], isOut: boolean): Promise<[Uint8Array, Uint8Array]> {
|
public getAesKeyIv(msgKey: Uint8Array | number[], isOut: boolean): Promise<[Uint8Array, Uint8Array]> {
|
||||||
const authKey = this.authKeyUint8;
|
|
||||||
const x = isOut ? 0 : 8;
|
const x = isOut ? 0 : 8;
|
||||||
const sha2aText = new Uint8Array(52);
|
const sha2aText = new Uint8Array(52);
|
||||||
const sha2bText = new Uint8Array(52);
|
const sha2bText = new Uint8Array(52);
|
||||||
const promises: Array<Promise<number[]>> = [];
|
const promises: Array<Promise<number[]>> = [];
|
||||||
|
|
||||||
sha2aText.set(msgKey, 0);
|
sha2aText.set(msgKey, 0);
|
||||||
sha2aText.set(authKey.subarray(x, x + 36), 16);
|
sha2aText.set(this.authKeyUint8.subarray(x, x + 36), 16);
|
||||||
promises.push(CryptoWorker.sha256Hash(sha2aText));
|
promises.push(CryptoWorker.sha256Hash(sha2aText));
|
||||||
|
|
||||||
sha2bText.set(authKey.subarray(40 + x, 40 + x + 36), 0);
|
sha2bText.set(this.authKeyUint8.subarray(40 + x, 40 + x + 36), 0);
|
||||||
sha2bText.set(msgKey, 36);
|
sha2bText.set(msgKey, 36);
|
||||||
promises.push(CryptoWorker.sha256Hash(sha2bText));
|
promises.push(CryptoWorker.sha256Hash(sha2bText));
|
||||||
|
|
||||||
@ -900,7 +904,7 @@ export default class MTPNetworker {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
bytes: encryptedBytes,
|
bytes: encryptedBytes,
|
||||||
msgKey: msgKey
|
msgKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -934,6 +938,14 @@ export default class MTPNetworker {
|
|||||||
data.storeInt(message.body.length, 'message_data_length');
|
data.storeInt(message.body.length, 'message_data_length');
|
||||||
data.storeRawBytes(message.body, 'message_data');
|
data.storeRawBytes(message.body, 'message_data');
|
||||||
|
|
||||||
|
const des = new TLDeserialization(data.getBuffer().slice(16));
|
||||||
|
const desSalt = des.fetchLong();
|
||||||
|
const desSessionId = des.fetchLong();
|
||||||
|
|
||||||
|
if(!this.isOnline) {
|
||||||
|
this.log.error('trying to send message when offline', message, new Uint8Array(des.buffer), desSalt, desSessionId);
|
||||||
|
}
|
||||||
|
|
||||||
/* const messageDataLength = message.body.length;
|
/* const messageDataLength = message.body.length;
|
||||||
let canBeLength = 0; // bytes
|
let canBeLength = 0; // bytes
|
||||||
canBeLength += 8;
|
canBeLength += 8;
|
||||||
@ -950,13 +962,15 @@ export default class MTPNetworker {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
const paddingLength = (16 - (data.offset % 16)) + 16 * (1 + nextRandomInt(5));
|
const paddingLength = (16 - (data.offset % 16)) + 16 * (1 + nextRandomInt(5));
|
||||||
const padding = [...new Uint8Array(paddingLength).randomize()];
|
const padding = (message as any).padding || new Uint8Array(paddingLength).randomize().fill(0);
|
||||||
/* const padding = [167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157,
|
/* const padding = [167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157,
|
||||||
51, 241, 46, 85, 141, 212, 139, 234, 213, 164, 197, 116, 245, 70, 184, 40, 40, 201, 233, 211, 150,
|
51, 241, 46, 85, 141, 212, 139, 234, 213, 164, 197, 116, 245, 70, 184, 40, 40, 201, 233, 211, 150,
|
||||||
94, 57, 84, 1, 135, 108, 253, 34, 139, 222, 208, 71, 214, 90, 67, 36, 28, 167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157,
|
94, 57, 84, 1, 135, 108, 253, 34, 139, 222, 208, 71, 214, 90, 67, 36, 28, 167, 148, 207, 226, 86, 192, 193, 57, 124, 153, 174, 145, 159, 1, 5, 70, 127, 157,
|
||||||
51, 241, 46, 85, 141, 212, 139, 234, 213, 164, 197, 116, 245, 70, 184, 40, 40, 201, 233, 211, 150,
|
51, 241, 46, 85, 141, 212, 139, 234, 213, 164, 197, 116, 245, 70, 184, 40, 40, 201, 233, 211, 150,
|
||||||
94, 57, 84, 1, 135, 108, 253, 34, 139, 222, 208, 71, 214, 90, 67, 36, 28].slice(0, paddingLength); */
|
94, 57, 84, 1, 135, 108, 253, 34, 139, 222, 208, 71, 214, 90, 67, 36, 28].slice(0, paddingLength); */
|
||||||
|
|
||||||
|
(message as any).padding = padding;
|
||||||
|
|
||||||
const dataWithPadding = bufferConcat(dataBuffer, padding);
|
const dataWithPadding = bufferConcat(dataBuffer, padding);
|
||||||
// this.log('Adding padding', dataBuffer, padding, dataWithPadding)
|
// this.log('Adding padding', dataBuffer, padding, dataWithPadding)
|
||||||
// this.log('auth_key_id', bytesToHex(self.authKeyID))
|
// this.log('auth_key_id', bytesToHex(self.authKeyID))
|
||||||
@ -969,6 +983,7 @@ export default class MTPNetworker {
|
|||||||
this.log('Send encrypted: body length:', (message.body as ArrayBuffer).byteLength, paddingLength, dataWithPadding);
|
this.log('Send encrypted: body length:', (message.body as ArrayBuffer).byteLength, paddingLength, dataWithPadding);
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
// * full next block is correct
|
||||||
return this.getEncryptedMessage(dataWithPadding).then((encryptedResult) => {
|
return this.getEncryptedMessage(dataWithPadding).then((encryptedResult) => {
|
||||||
/* if(DEBUG) {
|
/* if(DEBUG) {
|
||||||
this.log('Got encrypted out message', encryptedResult);
|
this.log('Got encrypted out message', encryptedResult);
|
||||||
@ -983,10 +998,12 @@ export default class MTPNetworker {
|
|||||||
|
|
||||||
const requestData = request.getBytes(true);
|
const requestData = request.getBytes(true);
|
||||||
|
|
||||||
//if(message.fileUpload) {
|
if(this.isFileNetworker) {
|
||||||
//this.log('Send encrypted: requestData length:', requestData.length, requestData.length % 16, paddingLength % 16, paddingLength, data.offset, encryptedResult.msgKey.length % 16, encryptedResult.bytes.length % 16);
|
//this.log('Send encrypted: requestData length:', requestData.length, requestData.length % 16, paddingLength % 16, paddingLength, data.offset, encryptedResult.msgKey.length % 16, encryptedResult.bytes.length % 16);
|
||||||
//this.log('Send encrypted: messageId:', message.msg_id, requestData.length);
|
//this.log('Send encrypted: messageId:', message.msg_id, requestData.length);
|
||||||
//}
|
//this.log('Send encrypted:', message, new Uint8Array(bufferConcat(des.buffer, padding)), requestData, this.serverSalt.hex, this.sessionId.hex/* new Uint8Array(des.buffer) */);
|
||||||
|
this.debugRequests.push({before: new Uint8Array(bufferConcat(des.buffer, padding)), after: requestData});
|
||||||
|
}
|
||||||
|
|
||||||
return requestData;
|
return requestData;
|
||||||
});
|
});
|
||||||
@ -1137,7 +1154,7 @@ export default class MTPNetworker {
|
|||||||
return {
|
return {
|
||||||
response,
|
response,
|
||||||
messageId,
|
messageId,
|
||||||
sessionId: sessionId,
|
sessionId,
|
||||||
seqNo
|
seqNo
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1151,7 +1168,7 @@ export default class MTPNetworker {
|
|||||||
['dc' + this.dcId + '_server_salt']: bytesToHex(serverSalt)
|
['dc' + this.dcId + '_server_salt']: bytesToHex(serverSalt)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.serverSalt = serverSalt;
|
this.serverSalt = new Uint8Array(serverSalt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! таймаут очень сильно тормозит скорость работы сокета (даже нулевой)
|
// ! таймаут очень сильно тормозит скорость работы сокета (даже нулевой)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { bytesToHex } from '../../helpers/bytes';
|
import { bytesToHex } from '../../helpers/bytes';
|
||||||
import { bigint, bigStringInt, isObject } from './bin_utils';
|
import { bigint, bigStringInt, isObject } from './bin_utils';
|
||||||
|
import { MOUNT_CLASS_TO } from './mtproto_config';
|
||||||
/// #if MTPROTO_WORKER
|
/// #if MTPROTO_WORKER
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { gzipUncompress } from '../crypto/crypto_utils';
|
import { gzipUncompress } from '../crypto/crypto_utils';
|
||||||
@ -789,5 +790,6 @@ class TLDeserialization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.TLDeserialization = TLDeserialization);
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.TLSerialization = TLSerialization);
|
||||||
export { TLDeserialization, TLSerialization };
|
export { TLDeserialization, TLSerialization };
|
||||||
|
|
||||||
|
@ -4,13 +4,15 @@ export class IntermediatePacketCodec implements Codec {
|
|||||||
public tag = 0xee;
|
public tag = 0xee;
|
||||||
public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]);
|
public obfuscateTag = new Uint8Array([this.tag, this.tag, this.tag, this.tag]);
|
||||||
|
|
||||||
|
//private lol = 0;
|
||||||
|
|
||||||
public encodePacket(data: Uint8Array) {
|
public encodePacket(data: Uint8Array) {
|
||||||
if((data.length % 4) !== 0) {
|
if((data.length % 4) !== 0) {
|
||||||
console.error('Encode error!', data.length, data);
|
console.error('Encode error!', data.length, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const len = data.length;
|
const len = data.length;
|
||||||
const header = new Uint8Array(new Uint32Array([len]).buffer);
|
const header = new Uint8Array(new Int32Array([/* ++this.lol >= 25 ? 0x80000001 : */len]).buffer);
|
||||||
|
|
||||||
//console.log('got nobody cause im braindead', header, len, /* data, */data.buffer.byteLength === data.length);
|
//console.log('got nobody cause im braindead', header, len, /* data, */data.buffer.byteLength === data.length);
|
||||||
return header.concat(data);
|
return header.concat(data);
|
||||||
|
@ -95,8 +95,8 @@ export default class Obfuscation {
|
|||||||
/* this.enc = new aesjs.ModeOfOperation.ctr(encKey, new aesjs.Counter(encIv as any));
|
/* this.enc = new aesjs.ModeOfOperation.ctr(encKey, new aesjs.Counter(encIv as any));
|
||||||
this.dec = new aesjs.ModeOfOperation.ctr(decKey, new aesjs.Counter(decIv as any)); */
|
this.dec = new aesjs.ModeOfOperation.ctr(decKey, new aesjs.Counter(decIv as any)); */
|
||||||
|
|
||||||
/* console.log('encKey', encKey, encIv);
|
console.log('encKey', encKey.hex, encIv.hex);
|
||||||
console.log('decKey', decKey, decIv); */
|
console.log('decKey', decKey.hex, decIv.hex);
|
||||||
|
|
||||||
this.encNew = new CTR(encKey, encIv);
|
this.encNew = new CTR(encKey, encIv);
|
||||||
this.decNew = new CTR(decKey, decIv);
|
this.decNew = new CTR(decKey, decIv);
|
||||||
|
@ -34,6 +34,8 @@ export default class Socket extends MTTransport {
|
|||||||
//private lol: Uint8Array[] = [];
|
//private lol: Uint8Array[] = [];
|
||||||
//private dd: () => void;
|
//private dd: () => void;
|
||||||
|
|
||||||
|
//private debugPayloads: MTPNetworker['debugRequests'] = [];
|
||||||
|
|
||||||
constructor(dcId: number, url: string, logSuffix: string, public retryTimeout: number) {
|
constructor(dcId: number, url: string, logSuffix: string, public retryTimeout: number) {
|
||||||
super(dcId, url);
|
super(dcId, url);
|
||||||
|
|
||||||
@ -220,6 +222,8 @@ export default class Socket extends MTTransport {
|
|||||||
const enc = this.obfuscation.encode(toEncode);
|
const enc = this.obfuscation.encode(toEncode);
|
||||||
//this.log('send after obf:', enc.hex);
|
//this.log('send after obf:', enc.hex);
|
||||||
|
|
||||||
|
//this.debugPayloads.push({before: body.slice(), after: enc});
|
||||||
|
|
||||||
this.debug && this.log.debug('-> body length to send:', enc.length, this.ws.bufferedAmount);
|
this.debug && this.log.debug('-> body length to send:', enc.length, this.ws.bufferedAmount);
|
||||||
/* if(this.ws.bufferedAmount) {
|
/* if(this.ws.bufferedAmount) {
|
||||||
this.log.error('bufferedAmount:', this.ws.bufferedAmount);
|
this.log.error('bufferedAmount:', this.ws.bufferedAmount);
|
||||||
|
92
t.py
92
t.py
@ -1,8 +1,16 @@
|
|||||||
from telethon import TelegramClient, events, sync
|
from telethon import TelegramClient, events, sync
|
||||||
from telethon.network import ConnectionTcpAbridged
|
from telethon.network import ConnectionTcpAbridged
|
||||||
|
from telethon.network.mtprotostate import MTProtoState
|
||||||
|
from telethon.crypto.authkey import AuthKey
|
||||||
|
from telethon.network.connection.tcpobfuscated import ConnectionTcpObfuscated
|
||||||
|
from telethon.network.connection.tcpintermediate import IntermediatePacketCodec
|
||||||
|
|
||||||
import sys
|
import struct
|
||||||
print(sys.path)
|
import logging
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
# import sys
|
||||||
|
# print(sys.path)
|
||||||
|
|
||||||
# These example values won't work. You must get your own api_id and
|
# These example values won't work. You must get your own api_id and
|
||||||
# api_hash from https://my.telegram.org, under API Development.
|
# api_hash from https://my.telegram.org, under API Development.
|
||||||
@ -11,4 +19,82 @@ api_hash = '452b0359b988148995f22ff0f4229750'
|
|||||||
|
|
||||||
client = TelegramClient('session_name', api_id, api_hash, connection=ConnectionTcpAbridged)
|
client = TelegramClient('session_name', api_id, api_hash, connection=ConnectionTcpAbridged)
|
||||||
#client.start()
|
#client.start()
|
||||||
client.connect()
|
#client.connect()
|
||||||
|
|
||||||
|
authKey = AuthKey(bytes.fromhex("2c45ed62da34d41bc82b6ef660760d3b01cb80028b0c363633f1c40ec80d5f4ad9d4ddee646736b6a9465fd7258b8936dedde6a86c69b4a03277ed6c543ccfd31fa8fa9f9449d686b4822b54542c91255231ecfa6aed4a9896cdcc3d5491e7f1b7529cbff75597f262813ced7eb3b5ac1e7e6794ca7aa00c5ea4d1d714e7c276fb63e5f8a1742cf4707eace8a6ec2ed4dcceceabdc7fc92bd099c811931e0da337f1b0271d8ba33e7a4a22fa1e4a913d8220edb0dd3a810ed408f03fe5d7f2d5dd43db4272d314b20a22376c03b0a05423600f4d012e7196ce9b3c45b28a75dbfa053222f5c86d1c6a706a2fd68ca270fd9a6449df1fa15a21837d34f4cf4e95"))
|
||||||
|
state = MTProtoState(authKey, loggers=client._log)
|
||||||
|
|
||||||
|
state.salt = struct.unpack('q', bytes.fromhex("d1b37eebb4997ca9"))[0]
|
||||||
|
state.id = struct.unpack('q', bytes.fromhex("502368ee46d39313"))[0]
|
||||||
|
|
||||||
|
#print(state.id)
|
||||||
|
|
||||||
|
""" with open('file_part.txt', 'r') as file:
|
||||||
|
data = file.read()
|
||||||
|
messageData = bytes.fromhex(data)
|
||||||
|
#messageData = bytes.fromhex("146f8265b5342560290000000c000000ec77be7aaa40f90300000000")
|
||||||
|
#print(data)
|
||||||
|
|
||||||
|
encrypted = state.encrypt_message_data(messageData)
|
||||||
|
|
||||||
|
file.close()
|
||||||
|
with open('file_part_encrypted.txt', 'w') as file:
|
||||||
|
file.write(encrypted.hex())
|
||||||
|
file.close()
|
||||||
|
#print(encrypted) """
|
||||||
|
|
||||||
|
ConnectionTcpObfuscated.packet_codec = IntermediatePacketCodec
|
||||||
|
connection = ConnectionTcpObfuscated("", "", 2, loggers=client._log)
|
||||||
|
obfuscatedIo = connection.obfuscated_io(connection)
|
||||||
|
#print(encrypted)
|
||||||
|
#exit()
|
||||||
|
#encoded = connection.packet_codec.encode_packet(connection.packet_codec, bytes.fromhex("deadbeef"))
|
||||||
|
#print(encoded)
|
||||||
|
#exit()
|
||||||
|
|
||||||
|
name = "debugPayloads"
|
||||||
|
#name = "debugRequests"
|
||||||
|
|
||||||
|
with open(name + '_before.txt', 'r') as fileBefore:
|
||||||
|
data = fileBefore.read()
|
||||||
|
lines = data.splitlines()
|
||||||
|
|
||||||
|
with open(name + '_after.txt', 'r') as fileAfter:
|
||||||
|
data = fileAfter.read()
|
||||||
|
linesAfter = data.splitlines()
|
||||||
|
|
||||||
|
length = len(lines)
|
||||||
|
for i in range(length):
|
||||||
|
print("processing line %i, of %i", i, length)
|
||||||
|
|
||||||
|
lineBefore = lines[i]
|
||||||
|
lineAfter = linesAfter[i]
|
||||||
|
|
||||||
|
messageData = bytes.fromhex(lineBefore)
|
||||||
|
messageData = connection.packet_codec.encode_packet(connection.packet_codec, messageData)
|
||||||
|
encrypted = obfuscatedIo._encrypt.encrypt(messageData)
|
||||||
|
#encrypted = state.encrypt_message_data(messageData) # need to comment padding inside
|
||||||
|
|
||||||
|
#print(encrypted.hex())
|
||||||
|
|
||||||
|
#print(len(encrypted.hex()))
|
||||||
|
#print(len(lineAfter))
|
||||||
|
#print(encrypted.hex() == lineAfter)
|
||||||
|
|
||||||
|
#break
|
||||||
|
|
||||||
|
if encrypted.hex() != lineAfter:
|
||||||
|
print("lol")
|
||||||
|
|
||||||
|
with open('difference_before.txt', 'w') as file:
|
||||||
|
file.write(lineAfter)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
with open('difference_after.txt', 'w') as file:
|
||||||
|
file.write(encrypted.hex())
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
|
||||||
|
#print(encrypted.hex())
|
||||||
|
#print(lineAfter)
|
||||||
|
exit()
|
||||||
|
83
t2.py
Normal file
83
t2.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
from telethon import TelegramClient, events, sync
|
||||||
|
from telethon.network import ConnectionTcpAbridged
|
||||||
|
from telethon.network.mtprotostate import MTProtoState
|
||||||
|
from telethon.crypto.authkey import AuthKey
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
|
# import sys
|
||||||
|
# print(sys.path)
|
||||||
|
|
||||||
|
# These example values won't work. You must get your own api_id and
|
||||||
|
# api_hash from https://my.telegram.org, under API Development.
|
||||||
|
api_id = 1025907
|
||||||
|
api_hash = '452b0359b988148995f22ff0f4229750'
|
||||||
|
|
||||||
|
client = TelegramClient('session_name', api_id, api_hash, connection=ConnectionTcpAbridged)
|
||||||
|
#client.start()
|
||||||
|
#client.connect()
|
||||||
|
|
||||||
|
authKey = AuthKey(bytes.fromhex("2c45ed62da34d41bc82b6ef660760d3b01cb80028b0c363633f1c40ec80d5f4ad9d4ddee646736b6a9465fd7258b8936dedde6a86c69b4a03277ed6c543ccfd31fa8fa9f9449d686b4822b54542c91255231ecfa6aed4a9896cdcc3d5491e7f1b7529cbff75597f262813ced7eb3b5ac1e7e6794ca7aa00c5ea4d1d714e7c276fb63e5f8a1742cf4707eace8a6ec2ed4dcceceabdc7fc92bd099c811931e0da337f1b0271d8ba33e7a4a22fa1e4a913d8220edb0dd3a810ed408f03fe5d7f2d5dd43db4272d314b20a22376c03b0a05423600f4d012e7196ce9b3c45b28a75dbfa053222f5c86d1c6a706a2fd68ca270fd9a6449df1fa15a21837d34f4cf4e95"))
|
||||||
|
state = MTProtoState(authKey, loggers=client._log)
|
||||||
|
|
||||||
|
state.salt = struct.unpack('q', bytes.fromhex("d1b37eebb4997ca9"))[0]
|
||||||
|
state.id = struct.unpack('q', bytes.fromhex("502368ee46d39313"))[0]
|
||||||
|
|
||||||
|
print(state.id)
|
||||||
|
|
||||||
|
""" with open('file_part.txt', 'r') as file:
|
||||||
|
data = file.read()
|
||||||
|
messageData = bytes.fromhex(data)
|
||||||
|
#messageData = bytes.fromhex("146f8265b5342560290000000c000000ec77be7aaa40f90300000000")
|
||||||
|
#print(data)
|
||||||
|
|
||||||
|
encrypted = state.encrypt_message_data(messageData)
|
||||||
|
|
||||||
|
file.close()
|
||||||
|
with open('file_part_encrypted.txt', 'w') as file:
|
||||||
|
file.write(encrypted.hex())
|
||||||
|
file.close()
|
||||||
|
#print(encrypted) """
|
||||||
|
|
||||||
|
with open('debugRequests_before.txt', 'r') as fileBefore:
|
||||||
|
data = fileBefore.read()
|
||||||
|
lines = data.splitlines()
|
||||||
|
|
||||||
|
with open('debugRequests_after.txt', 'r') as fileAfter:
|
||||||
|
data = fileAfter.read()
|
||||||
|
linesAfter = data.splitlines()
|
||||||
|
|
||||||
|
length = len(lines)
|
||||||
|
for i in range(length):
|
||||||
|
print("processing line %i, of %i", i, length)
|
||||||
|
|
||||||
|
lineBefore = lines[i]
|
||||||
|
|
||||||
|
messageData = bytes.fromhex(lineBefore)
|
||||||
|
encrypted = state.encrypt_message_data(messageData) # need to comment padding inside
|
||||||
|
|
||||||
|
lineAfter = linesAfter[i]
|
||||||
|
|
||||||
|
#print(len(encrypted.hex()))
|
||||||
|
#print(len(lineAfter))
|
||||||
|
#print(encrypted.hex() == lineAfter)
|
||||||
|
|
||||||
|
#break
|
||||||
|
|
||||||
|
if encrypted.hex() != lineAfter:
|
||||||
|
print("lol")
|
||||||
|
|
||||||
|
with open('difference_before.txt', 'w') as file:
|
||||||
|
file.write(lineAfter)
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
with open('difference_after.txt', 'w') as file:
|
||||||
|
file.write(encrypted.hex())
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
|
||||||
|
#print(encrypted.hex())
|
||||||
|
#print(lineAfter)
|
||||||
|
exit()
|
@ -8,8 +8,8 @@ const fs = require('fs');
|
|||||||
|
|
||||||
const allowedIPs = ['194.58.97.147', '195.66.140.39', '127.0.0.1', '176.100.8.254'];
|
const allowedIPs = ['194.58.97.147', '195.66.140.39', '127.0.0.1', '176.100.8.254'];
|
||||||
const devMode = process.env.NODE_ENV !== 'production';
|
const devMode = process.env.NODE_ENV !== 'production';
|
||||||
const useLocal = false;
|
const useLocal = true;
|
||||||
const useLocalNotLocal = false;
|
const useLocalNotLocal = true;
|
||||||
|
|
||||||
if(devMode) {
|
if(devMode) {
|
||||||
console.log('DEVMODE IS ON!');
|
console.log('DEVMODE IS ON!');
|
||||||
@ -103,7 +103,7 @@ module.exports = {
|
|||||||
allowedHosts: useLocal ? undefined : [
|
allowedHosts: useLocal ? undefined : [
|
||||||
'tweb.enko.club'
|
'tweb.enko.club'
|
||||||
],
|
],
|
||||||
host: useLocalNotLocal ? '192.168.93.183' : (useLocal ? undefined : '0.0.0.0'),
|
host: useLocalNotLocal ? '192.168.93.209' : (useLocal ? undefined : '0.0.0.0'),
|
||||||
public: useLocal ? undefined : 'tweb.enko.club',
|
public: useLocal ? undefined : 'tweb.enko.club',
|
||||||
//host: '192.168.0.105', // '0.0.0.0'
|
//host: '192.168.0.105', // '0.0.0.0'
|
||||||
//host: 'tweb.enko.club', // '0.0.0.0'
|
//host: 'tweb.enko.club', // '0.0.0.0'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user