1
0
Эх сурвалжийг харах

Gram JS: Remove deps; Fix Factorizator and remove leemon lib

painor 5 жил өмнө
parent
commit
229da42c68

+ 7 - 0
package.json

@@ -52,6 +52,7 @@
     "typescript": "^3.6.4"
     "typescript": "^3.6.4"
   },
   },
   "dependencies": {
   "dependencies": {
+<<<<<<< HEAD
     "aes-js": "^3.1.2",
     "aes-js": "^3.1.2",
     "crc": "^3.8.0",
     "crc": "^3.8.0",
     "crypto": "^1.0.1",
     "crypto": "^1.0.1",
@@ -62,6 +63,12 @@
     "python-struct": "^1.1.2",
     "python-struct": "^1.1.2",
     "string-format": "^2.0.0",
     "string-format": "^2.0.0",
     "td": "^0.3.2",
     "td": "^0.3.2",
+=======
+    "big-integer": "latest",
+    "croppie": "^2.6.4",
+    "emoji-regex": "^8.0.0",
+    "events": "^3.0.0",
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib
     "tdweb": "^1.5.0",
     "tdweb": "^1.5.0",
     "websocket": "^1.0.30",
     "websocket": "^1.0.30",
     "big-integer": "latest"
     "big-integer": "latest"

+ 31 - 0
src/lib/gramjs/Helpers.js

@@ -249,12 +249,43 @@ function isArrayLike(obj) {
     return true
     return true
 }
 }
 
 
+// Taken from https://stackoverflow.com/questions/18638900/javascript-crc32/18639999#18639999
+function makeCRCTable() {
+    let c
+    const crcTable = []
+    for (let n = 0; n < 256; n++) {
+        c = n
+        for (let k = 0; k < 8; k++) {
+            c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1))
+        }
+        crcTable[n] = c
+    }
+    return crcTable
+}
 
 
+let crcTable = null
+
+function crc32(buf) {
+    if (!crcTable) {
+        crcTable = makeCRCTable()
+    }
+    if (!Buffer.isBuffer(buf)) {
+        buf = Buffer.from(buf)
+    }
+    let crc = -1
+
+    for (let index = 0; index < buf.length; index++) {
+        const byte = buf[index]
+        crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8)
+    }
+    return (crc ^ (-1)) >>> 0
+}
 module.exports = {
 module.exports = {
     readBigIntFromBuffer,
     readBigIntFromBuffer,
     readBufferFromBigInt,
     readBufferFromBigInt,
     generateRandomLong,
     generateRandomLong,
     mod,
     mod,
+    crc32,
     generateRandomBytes,
     generateRandomBytes,
     calcKey,
     calcKey,
     calcMsgKey,
     calcMsgKey,

+ 1 - 1
src/lib/gramjs/Utils.js

@@ -12,7 +12,7 @@ const VALID_USERNAME_RE = new RegExp('^([a-z]((?!__)[\\w\\d]){3,30}[a-z\\d]|gif|
     'pic|bing|wiki|imdb|bold|vote|like|coub)$')
     'pic|bing|wiki|imdb|bold|vote|like|coub)$')
 
 
 function _raiseCastFail(entity, target) {
 function _raiseCastFail(entity, target) {
-    throw new Error(`Cannot cast ${entity.constructor.name} to any kind of ${target}`)
+    throw new Error(`Cannot cast ${entity.className} to any kind of ${target}`)
 }
 }
 
 
 /**
 /**

+ 82 - 0
src/lib/gramjs/crypto/AES.js

@@ -0,0 +1,82 @@
+const crypto = require('crypto')
+const { generateRandomBytes } = require('../Helpers')
+
+class AES {
+    /**
+     * Decrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector
+     * @param cipherText {Buffer}
+     * @param key {Buffer}
+     * @param iv {Buffer}
+     * @returns {Buffer}
+     */
+    static decryptIge(cipherText, key, iv) {
+
+        let iv1 = iv.slice(0, Math.floor(iv.length / 2))
+        let iv2 = iv.slice(Math.floor(iv.length / 2))
+        let plainText = []
+        const aes = crypto.createDecipheriv('AES-256-ECB', key, Buffer.alloc(0))
+        aes.setAutoPadding(true)
+        const blocksCount = Math.floor(cipherText.length / 16)
+        const cipherTextBlock = Buffer.alloc(16).fill(0)
+
+        for (let blockIndex = 0; blockIndex < blocksCount; blockIndex++) {
+            for (let i = 0; i < 16; i++) {
+                cipherTextBlock[i] = cipherText[blockIndex * 16 + i] ^ iv2[i]
+            }
+            //This might be a bug in the crypto module
+            aes.update(cipherTextBlock)
+            const plainTextBlock = aes.update(cipherTextBlock)
+
+            for (let i = 0; i < 16; i++) {
+                plainTextBlock[i] ^= iv1[i]
+            }
+
+            iv1 = cipherText.slice(blockIndex * 16, blockIndex * 16 + 16)
+            iv2 = plainTextBlock.slice(0, 16)
+
+            Array.prototype.push.apply(plainText, iv2)
+        }
+        return Buffer.from(plainText)
+    }
+
+    /**
+     * Encrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector
+     * @param plainText {Buffer}
+     * @param key {Buffer}
+     * @param iv {Buffer}
+     * @returns {Buffer}
+     */
+    static encryptIge(plainText, key, iv) {
+        const padding = plainText.length % 16
+        if (padding) {
+            plainText = Buffer.concat([plainText, generateRandomBytes(16 - padding)])
+        }
+
+        let iv1 = iv.slice(0, Math.floor(iv.length / 2))
+        let iv2 = iv.slice(Math.floor(iv.length / 2))
+        const aes = crypto.createCipheriv('AES-256-ECB', key, Buffer.alloc(0))
+        aes.setAutoPadding(true)
+        let cipherText = Buffer.alloc(0)
+        const blockCount = Math.floor(plainText.length / 16)
+
+        for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
+            const plainTextBlock = Buffer.from(plainText.slice(blockIndex * 16, blockIndex * 16 + 16))
+
+            for (let i = 0; i < 16; i++) {
+                plainTextBlock[i] ^= iv1[i]
+            }
+            const cipherTextBlock = aes.update(plainTextBlock)
+
+            for (let i = 0; i < 16; i++) {
+                cipherTextBlock[i] ^= iv2[i]
+            }
+
+            iv1 = cipherTextBlock
+            iv2 = plainText.slice(blockIndex * 16, blockIndex * 16 + 16)
+            cipherText = Buffer.concat([cipherText, cipherTextBlock])
+        }
+        return cipherText
+    }
+}
+
+module.exports = AES

+ 3 - 7
src/lib/gramjs/crypto/AESCTR.js

@@ -1,21 +1,17 @@
-const aesjs = require('aes-js')
+const crypto = require('crypto')
 
 
 class AESModeCTR {
 class AESModeCTR {
     constructor(key, iv) {
     constructor(key, iv) {
         if (!(key instanceof Buffer) || !(iv instanceof Buffer) || iv.length !== 16) {
         if (!(key instanceof Buffer) || !(iv instanceof Buffer) || iv.length !== 16) {
             throw new Error('Key and iv need to be a buffer')
             throw new Error('Key and iv need to be a buffer')
         }
         }
-        this.cipher = new aesjs.ModeOfOperation.ctr(Buffer.from(key), Buffer.from(iv))
+        this.cipher = crypto.createCipheriv('AES-256-CTR', key, iv)
     }
     }
 
 
     encrypt(data) {
     encrypt(data) {
-        const res = this.cipher.encrypt(data)
-        return Buffer.from(res)
+        return this.cipher.update(data)
     }
     }
 
 
-    decrypt(data) {
-        return Buffer.from(this.cipher.decrypt(data))
-    }
 
 
 }
 }
 
 

+ 6 - 4
src/lib/gramjs/crypto/AuthKey.js

@@ -1,6 +1,5 @@
 const { sha1, readBufferFromBigInt, readBigIntFromBuffer } = require('../Helpers')
 const { sha1, readBufferFromBigInt, readBigIntFromBuffer } = require('../Helpers')
 const BinaryReader = require('../extensions/BinaryReader')
 const BinaryReader = require('../extensions/BinaryReader')
-const struct = require('python-struct')
 const { sleep } = require("../Helpers")
 const { sleep } = require("../Helpers")
 
 
 class AuthKey {
 class AuthKey {
@@ -26,8 +25,8 @@ class AuthKey {
         this.keyId = reader.readLong(false)
         this.keyId = reader.readLong(false)
     }
     }
 
 
-    async waitForKey(){
-        while (!this.key){
+    async waitForKey() {
+        while (!this.key) {
             await sleep(20)
             await sleep(20)
         }
         }
     }
     }
@@ -46,7 +45,10 @@ class AuthKey {
      */
      */
     calcNewNonceHash(newNonce, number) {
     calcNewNonceHash(newNonce, number) {
         newNonce = readBufferFromBigInt(newNonce, 32, true, true)
         newNonce = readBufferFromBigInt(newNonce, 32, true, true)
-        const data = Buffer.concat([newNonce, struct.pack('<BQ', number.toString(), this.auxHash.toString())])
+        const n = Buffer.alloc(1)
+        n.writeUInt8(number, 0)
+        const data = Buffer.concat([newNonce,
+            Buffer.concat([n, readBufferFromBigInt(this.auxHash, 8, true)])])
 
 
         // Calculates the message key from the given data
         // Calculates the message key from the given data
         const shaData = sha1(data).slice(4, 20)
         const shaData = sha1(data).slice(4, 20)

+ 51 - 60
src/lib/gramjs/crypto/Factorizator.js

@@ -1,9 +1,7 @@
 const BigInt = require('big-integer')
 const BigInt = require('big-integer')
-const { getByteArray, readBigIntFromBuffer, modExp } = require('../Helpers')
-const FactorizatorLeemon = require('./FactorizatorLeemon');
+const { modExp } = require('../Helpers')
 
 
 class Factorizator {
 class Factorizator {
-
     /**
     /**
      * Calculates the greatest common divisor
      * Calculates the greatest common divisor
      * @param a {BigInteger}
      * @param a {BigInteger}
@@ -25,64 +23,57 @@ class Factorizator {
      * @returns {{p: *, q: *}}
      * @returns {{p: *, q: *}}
      */
      */
     static factorize(pq) {
     static factorize(pq) {
-        const pqBuffer = getByteArray(pq);
-        const { p: pBytes, q: qBytes } = FactorizatorLeemon.factorize(pqBuffer);
-        return {
-            p: Buffer.from(pBytes),
-            q: Buffer.from(qBytes),
-        };
-    }
+        if (pq.remainder(2).equals(BigInt.zero)) {
+            return { p: BigInt(2), q: pq.divide(BigInt(2)) }
+        }
+        let y = BigInt.randBetween(BigInt(1),pq.minus(1))
+        const c = BigInt.randBetween(BigInt(1),pq.minus(1))
+        const m = BigInt.randBetween(BigInt(1),pq.minus(1))
+
+        let g = BigInt.one
+        let r = BigInt.one
+        let q = BigInt.one
+        let x = BigInt.zero
+        let ys = BigInt.zero
+        let k
+
+        while (g.eq(BigInt.one)) {
+            x = y
+            for (let i = 0; BigInt(i).lesser(r); i++) {
+                y = (modExp(y, BigInt(2), pq)).add(c).remainder(pq)
+            }
+            k = BigInt.zero
+
+            while (k.lesser(r) && g.eq(BigInt.one)) {
+
+                ys = y
+                let condition = BigInt.min(m, r.minus(k))
+                for (let i = 0; BigInt(i).lesser(condition); i++) {
+                    y = (modExp(y, BigInt(2), pq)).add(c).remainder(pq)
+                    q = q.multiply(x.minus(y).abs()).remainder(pq)
+                }
+                g = Factorizator.gcd(q, pq)
+                k = k.add(m)
+            }
 
 
-    // // TODO Broken. Sometimes this gets stuck for some reason.
-    // static factorize(pq) {
-    //     console.log("I am going to f", pq)
-    //     if (pq.remainder(2).equals(BigInt.zero)) {
-    //         return { p: BigInt(2), q: pq.divide(BigInt(2)) }
-    //     }
-    //     let y = BigInt.randBetween(1, pq.minus(1))
-    //     const c = BigInt.randBetween(1, pq.minus(1))
-    //     const m = BigInt.randBetween(1, pq.minus(1))
-    //     let g = BigInt.one
-    //     let r = BigInt.one
-    //     let q = BigInt.one
-    //     let x = BigInt.zero
-    //     let ys = BigInt.zero
-    //
-    //     let k
-    //     while (g.eq(BigInt.one)) {
-    //         x = y
-    //         for (let i = 0; BigInt(i).lesser(r); i++) {
-    //             y = (modExp(y, BigInt(2), pq)).add(c).remainder(pq)
-    //         }
-    //         k = BigInt.zero
-    //         while (k.lesser(r) && g.eq(BigInt.one)) {
-    //             ys = y
-    //             let condition = BigInt.min(m, r.minus(k))
-    //             for (let i = 0; BigInt(i).lesser(condition); i++) {
-    //                 y = (modExp(y, BigInt(2), pq)).add(c).remainder(pq)
-    //                 q = q.multiply(x.minus(y).abs()).remainder(pq)
-    //             }
-    //
-    //             g = Factorizator.gcd(q, pq)
-    //             k = k.add(m)
-    //         }
-    //         r = r.multiply(2)
-    //     }
-    //
-    //     if (g.eq(pq)) {
-    //         while (true) {
-    //             ys = (modExp(y, BigInt(2), pq)).add(c).remainder(pq)
-    //             g = Factorizator.gcd(x.minus(ys).abs(), pq)
-    //             if (g.greater(1)) {
-    //                 break
-    //             }
-    //         }
-    //     }
-    //     const p = g
-    //     q = pq.divide(g)
-    //
-    //     return p < q ? { p: p, q: q } : { p: q, q: p }
-    // }
+            r = r.multiply(2)
+        }
+
+
+        if (g.eq(pq)) {
+            while (true) {
+                ys = (modExp(ys, BigInt(2), pq)).add(c).remainder(pq)
+                g = Factorizator.gcd(x.minus(ys).abs(), pq)
+
+                if (g.greater(1)) {
+                    break
+                }
+            }
+        }
+        const p = g
+        q = pq.divide(g)
+        return p < q ? { p: p, q: q } : { p: q, q: p }
+    }
 }
 }
 
 
 module.exports = Factorizator
 module.exports = Factorizator

+ 44 - 49
src/lib/gramjs/crypto/RSA.js

@@ -1,79 +1,74 @@
-const NodeRSA = require('node-rsa')
 const { serializeBytes } = require('../tl')
 const { serializeBytes } = require('../tl')
 const { readBigIntFromBuffer, readBufferFromBigInt, getByteArray, sha1, generateRandomBytes, modExp } = require('../Helpers')
 const { readBigIntFromBuffer, readBufferFromBigInt, getByteArray, sha1, generateRandomBytes, modExp } = require('../Helpers')
 const _serverKeys = {}
 const _serverKeys = {}
 const BigInt = require('big-integer')
 const BigInt = require('big-integer')
 
 
 
 
+/**
+ * Given a RSA key, computes its fingerprint like Telegram does.
+ * @param key the RSA key.
+ * @returns {bigInt.BigInteger|*} its 8-bytes-long fingerprint
+ * @private
+ */
 function _computeFingerprint(key) {
 function _computeFingerprint(key) {
-    const buf = readBigIntFromBuffer(key.keyPair.n.toBuffer(), false)
-    const nArray = getByteArray(buf)
 
 
-    const n = serializeBytes(nArray)
-    const e = serializeBytes(getByteArray(key.keyPair.e))
+    const n = serializeBytes(getByteArray(key.n))
+    const e = serializeBytes(getByteArray(key.e))
     // Telegram uses the last 8 bytes as the fingerprint
     // Telegram uses the last 8 bytes as the fingerprint
-    const sh = sha1(Buffer.concat([ n, e ]))
+    const sh = sha1(Buffer.concat([n, e]))
     return readBigIntFromBuffer(sh.slice(-8), true, true)
     return readBigIntFromBuffer(sh.slice(-8), true, true)
 }
 }
 
 
+/**
+ * Adds a new public key to be used when encrypting new data is needed
+ * @param pub {{n:BigInt,e:BigInt}}
+ */
 function addKey(pub) {
 function addKey(pub) {
-    const key = new NodeRSA(pub)
-    _serverKeys[_computeFingerprint(key)] = key
+    _serverKeys[_computeFingerprint(pub)] = pub
 }
 }
 
 
+/**
+ * Encrypts the given data known the fingerprint to be used
+ * in the way Telegram requires us to do so (sha1(data) + data + padding)
+
+ * @param fingerprint the fingerprint of the RSA key.
+ * @param data the data to be encrypted.
+ * @returns {Buffer|*|undefined} the cipher text, or None if no key matching this fingerprint is found.
+ */
 function encrypt(fingerprint, data) {
 function encrypt(fingerprint, data) {
     const key = _serverKeys[fingerprint]
     const key = _serverKeys[fingerprint]
     if (!key) {
     if (!key) {
         return undefined
         return undefined
     }
     }
-    const buf = readBigIntFromBuffer(key.keyPair.n.toBuffer(), false)
+
+    // len(sha1.digest) is always 20, so we're left with 255 - 20 - x padding
     const rand = generateRandomBytes(235 - data.length)
     const rand = generateRandomBytes(235 - data.length)
     const toEncrypt = Buffer.concat([sha1(data), data, rand])
     const toEncrypt = Buffer.concat([sha1(data), data, rand])
+
+    // rsa module rsa.encrypt adds 11 bits for padding which we don't want
+    // rsa module uses rsa.transform.bytes2int(to_encrypt), easier way:
     const payload = readBigIntFromBuffer(toEncrypt, false)
     const payload = readBigIntFromBuffer(toEncrypt, false)
-    const encrypted = modExp(payload, BigInt(key.keyPair.e), buf)
-    const block = readBufferFromBigInt(encrypted, 256, false)
-    return block
+    const encrypted = modExp(payload, BigInt(key.e), key.n)
+    // rsa module uses transform.int2bytes(encrypted, keylength), easier:
+    return readBufferFromBigInt(encrypted, 256, false)
 }
 }
 
 
-const publicKeys = [
-    `-----BEGIN RSA PUBLIC KEY-----
-MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
-lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
-an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
-Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
-8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
-Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
------END RSA PUBLIC KEY-----`,
-
-    `-----BEGIN RSA PUBLIC KEY-----
-MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt
-ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru
-vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L
-xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi
-XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp
-NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB
------END RSA PUBLIC KEY-----`,
-
-    `-----BEGIN RSA PUBLIC KEY-----
-MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+
-DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB
-1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s
-g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z
-hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f
-x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB
------END RSA PUBLIC KEY-----`,
-
-    `-----BEGIN RSA PUBLIC KEY-----
-MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa
-xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i
-qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc
-/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks
-WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t
-UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB
------END RSA PUBLIC KEY-----`,
-]
+const publicKeys = [{
+    'n': BigInt('24403446649145068056824081744112065346446136066297307473868293895086332508101251964919587745984311372853053253457835208829824428441874946556659953519213382748319518214765985662663680818277989736779506318868003755216402538945900388706898101286548187286716959100102939636333452457308619454821845196109544157601096359148241435922125602449263164512290854366930013825808102403072317738266383237191313714482187326643144603633877219028262697593882410403273959074350849923041765639673335775605842311578109726403165298875058941765362622936097839775380070572921007586266115476975819175319995527916042178582540628652481530373407'),
+    'e': 65537
+}, {
+    'n': BigInt('25081407810410225030931722734886059247598515157516470397242545867550116598436968553551465554653745201634977779380884774534457386795922003815072071558370597290368737862981871277312823942822144802509055492512145589734772907225259038113414940384446493111736999668652848440655603157665903721517224934142301456312994547591626081517162758808439979745328030376796953660042629868902013177751703385501412640560275067171555763725421377065095231095517201241069856888933358280729674273422117201596511978645878544308102076746465468955910659145532699238576978901011112475698963666091510778777356966351191806495199073754705289253783'),
+    'e': 65537
+}, {
+    'n': BigInt('22347337644621997830323797217583448833849627595286505527328214795712874535417149457567295215523199212899872122674023936713124024124676488204889357563104452250187725437815819680799441376434162907889288526863223004380906766451781702435861040049293189979755757428366240570457372226323943522935844086838355728767565415115131238950994049041950699006558441163206523696546297006014416576123345545601004508537089192869558480948139679182328810531942418921113328804749485349441503927570568778905918696883174575510385552845625481490900659718413892216221539684717773483326240872061786759868040623935592404144262688161923519030977'),
+    'e': 65537
+}, {
+    'n': BigInt('24573455207957565047870011785254215390918912369814947541785386299516827003508659346069416840622922416779652050319196701077275060353178142796963682024347858398319926119639265555410256455471016400261630917813337515247954638555325280392998950756512879748873422896798579889820248358636937659872379948616822902110696986481638776226860777480684653756042166610633513404129518040549077551227082262066602286208338952016035637334787564972991208252928951876463555456715923743181359826124083963758009484867346318483872552977652588089928761806897223231500970500186019991032176060579816348322451864584743414550721639495547636008351'),
+    'e': 65537
+}]
 for (const pub of publicKeys) {
 for (const pub of publicKeys) {
     addKey(pub)
     addKey(pub)
 }
 }
 
 
 module.exports = { encrypt, addKey }
 module.exports = { encrypt, addKey }
+

+ 0 - 1
src/lib/gramjs/errors/Common.js

@@ -2,7 +2,6 @@
  * Errors not related to the Telegram API itself
  * Errors not related to the Telegram API itself
  */
  */
 
 
-const struct = require('python-struct')
 
 
 /**
 /**
  * Occurs when a read operation was cancelled.
  * Occurs when a read operation was cancelled.

+ 17 - 17
src/lib/gramjs/errors/RPCErrorList.js

@@ -1,12 +1,11 @@
 const { RPCError, InvalidDCError, FloodError } = require('./RPCBaseErrors')
 const { RPCError, InvalidDCError, FloodError } = require('./RPCBaseErrors')
-const format = require('string-format')
 
 
 
 
 class UserMigrateError extends InvalidDCError {
 class UserMigrateError extends InvalidDCError {
     constructor(args) {
     constructor(args) {
         const newDc = Number(args.capture || 0)
         const newDc = Number(args.capture || 0)
-        super(format('The user whose identity is being used to execute queries is associated with DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request))
-        this.message = format('The user whose identity is being used to execute queries is associated with DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request)
+        super(`The user whose identity is being used to execute queries is associated with DC ${newDc}` + RPCError._fmtRequest(args.request))
+        this.message = `The user whose identity is being used to execute queries is associated with DC ${newDc}` + RPCError._fmtRequest(args.request)
         this.newDc = newDc
         this.newDc = newDc
     }
     }
 }
 }
@@ -15,8 +14,8 @@ class UserMigrateError extends InvalidDCError {
 class PhoneMigrateError extends InvalidDCError {
 class PhoneMigrateError extends InvalidDCError {
     constructor(args) {
     constructor(args) {
         const newDc = Number(args.capture || 0)
         const newDc = Number(args.capture || 0)
-        super(format('The phone number a user is trying to use for authorization is associated with DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request))
-        this.message = format('The phone number a user is trying to use for authorization is associated with DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request)
+        super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}` + RPCError._fmtRequest(args.request))
+        this.message = `The phone number a user is trying to use for authorization is associated with DC ${newDc}` + RPCError._fmtRequest(args.request)
         this.newDc = newDc
         this.newDc = newDc
     }
     }
 }
 }
@@ -24,8 +23,8 @@ class PhoneMigrateError extends InvalidDCError {
 class SlowModeWaitError extends FloodError {
 class SlowModeWaitError extends FloodError {
     constructor(args) {
     constructor(args) {
         const seconds = Number(args.capture || 0)
         const seconds = Number(args.capture || 0)
-        super(format('A wait of {seconds} seconds is required before sending another message in this chat', { seconds }) + RPCError._fmtRequest(args.request))
-        this.message = format('A wait of {seconds} seconds is required before sending another message in this chat', { seconds }) + RPCError._fmtRequest(args.request)
+        super(`A wait of ${seconds} seconds is required before sending another message in this chat` + RPCError._fmtRequest(args.request))
+        this.message = `A wait of ${seconds} seconds is required before sending another message in this chat` + RPCError._fmtRequest(args.request)
         this.seconds = seconds
         this.seconds = seconds
     }
     }
 }
 }
@@ -33,8 +32,8 @@ class SlowModeWaitError extends FloodError {
 class FloodWaitError extends FloodError {
 class FloodWaitError extends FloodError {
     constructor(args) {
     constructor(args) {
         const seconds = Number(args.capture || 0)
         const seconds = Number(args.capture || 0)
-        super(format('A wait of {seconds} seconds is required', { seconds }) + RPCError._fmtRequest(args.request))
-        this.message = format('A wait of {seconds} seconds is required', { seconds }) + RPCError._fmtRequest(args.request)
+        super(`A wait of ${seconds} seconds is required` + RPCError._fmtRequest(args.request))
+        this.message = `A wait of ${seconds} seconds is required` + RPCError._fmtRequest(args.request)
         this.seconds = seconds
         this.seconds = seconds
     }
     }
 }
 }
@@ -42,8 +41,8 @@ class FloodWaitError extends FloodError {
 class FloodTestPhoneWaitError extends FloodError {
 class FloodTestPhoneWaitError extends FloodError {
     constructor(args) {
     constructor(args) {
         const seconds = Number(args.capture || 0)
         const seconds = Number(args.capture || 0)
-        super(format('A wait of {seconds} seconds is required in the test servers', { seconds }) + RPCError._fmtRequest(args.request))
-        this.message = format('A wait of {seconds} seconds is required in the test servers', { seconds }) + RPCError._fmtRequest(args.request)
+        super(`A wait of ${seconds} seconds is required in the test servers` + RPCError._fmtRequest(args.request))
+        this.message = `A wait of ${seconds} seconds is required in the test servers` + RPCError._fmtRequest(args.request)
         this.seconds = seconds
         this.seconds = seconds
     }
     }
 }
 }
@@ -51,17 +50,18 @@ class FloodTestPhoneWaitError extends FloodError {
 class FileMigrateError extends InvalidDCError {
 class FileMigrateError extends InvalidDCError {
     constructor(args) {
     constructor(args) {
         const newDc = Number(args.capture || 0)
         const newDc = Number(args.capture || 0)
-        super(format('The file to be accessed is currently stored in DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request))
-        this.message = format('The file to be accessed is currently stored in DC {new_dc}', { newDc }) + RPCError._fmtRequest(args.request)
+        super(`The file to be accessed is currently stored in DC ${newDc}` + RPCError._fmtRequest(args.request))
+        this.message = `The file to be accessed is currently stored in DC ${newDc}` + RPCError._fmtRequest(args.request)
         this.newDc = newDc
         this.newDc = newDc
     }
     }
 }
 }
+
 class NetworkMigrateError extends InvalidDCError {
 class NetworkMigrateError extends InvalidDCError {
     constructor(args) {
     constructor(args) {
-        const newDc = Number(args.capture || 0);
-        super(format('The source IP address is associated with DC {new_dc}', {newDc}) + RPCError._fmtRequest(args.request));
-        this.message = format('The source IP address is associated with DC {new_dc}', {newDc}) + RPCError._fmtRequest(args.request);
-        this.newDc = newDc;
+        const newDc = Number(args.capture || 0)
+        super(`The source IP address is associated with DC ${newDc}` + RPCError._fmtRequest(args.request))
+        this.message = `The source IP address is associated with DC ${newDc}` + RPCError._fmtRequest(args.request)
+        this.newDc = newDc
     }
     }
 }
 }
 
 

+ 3 - 4
src/lib/gramjs/extensions/BinaryReader.js

@@ -1,9 +1,7 @@
-const { unpack } = require('python-struct')
 const { TypeNotFoundError } = require('../errors/Common')
 const { TypeNotFoundError } = require('../errors/Common')
 const { coreObjects } = require('../tl/core')
 const { coreObjects } = require('../tl/core')
 const { tlobjects } = require('../tl/AllTLObjects')
 const { tlobjects } = require('../tl/AllTLObjects')
 const { readBigIntFromBuffer } = require('../Helpers')
 const { readBigIntFromBuffer } = require('../Helpers')
-const BigInt = require('big-integer')
 
 
 class BinaryReader {
 class BinaryReader {
     /**
     /**
@@ -56,7 +54,7 @@ class BinaryReader {
      * @returns {number}
      * @returns {number}
      */
      */
     readFloat() {
     readFloat() {
-        return unpack('<f', this.read(4))[0]
+        return this.read(4).readFloatLE(0)
     }
     }
 
 
     /**
     /**
@@ -64,7 +62,8 @@ class BinaryReader {
      * @returns {BigInteger}
      * @returns {BigInteger}
      */
      */
     readDouble() {
     readDouble() {
-        return unpack('<f', this.read(8))[0]
+        // was this a bug ? it should have been <d
+        return this.read(8).readDoubleLE(0)
     }
     }
 
 
     /**
     /**

+ 4 - 4
src/lib/gramjs/extensions/MessagePacker.js

@@ -1,7 +1,6 @@
 const MessageContainer = require('../tl/core/MessageContainer')
 const MessageContainer = require('../tl/core/MessageContainer')
 const TLMessage = require('../tl/core/TLMessage')
 const TLMessage = require('../tl/core/TLMessage')
 const BinaryWriter = require('../extensions/BinaryWriter')
 const BinaryWriter = require('../extensions/BinaryWriter')
-const struct = require('python-struct')
 
 
 class MessagePacker {
 class MessagePacker {
     constructor(state, logger) {
     constructor(state, logger) {
@@ -71,9 +70,10 @@ class MessagePacker {
             return null
             return null
         }
         }
         if (batch.length > 1) {
         if (batch.length > 1) {
-            data = Buffer.concat([struct.pack(
-                '<Ii', MessageContainer.CONSTRUCTOR_ID, batch.length,
-            ), buffer.getValue()])
+            const b = Buffer.alloc(8)
+            b.writeUInt32LE(MessageContainer.CONSTRUCTOR_ID,0)
+            b.writeInt32LE(batch.length,4)
+            data = Buffer.concat([b, buffer.getValue()])
             buffer = new BinaryWriter(Buffer.alloc(0))
             buffer = new BinaryWriter(Buffer.alloc(0))
             const containerId = await this._state.writeDataAsMessage(
             const containerId = await this._state.writeDataAsMessage(
                 buffer, data, false,
                 buffer, data, false,

+ 2 - 2
src/lib/gramjs/network/Authenticator.js

@@ -36,8 +36,8 @@ async function doAuthentication(sender, log) {
     let { p, q } = Factorizator.factorize(pq)
     let { p, q } = Factorizator.factorize(pq)
 
 
     // TODO Bring back after `Factorizator` fix.
     // TODO Bring back after `Factorizator` fix.
-    // p = Helpers.getByteArray(p)
-    // q = Helpers.getByteArray(q)
+     p = Helpers.getByteArray(p)
+     q = Helpers.getByteArray(q)
 
 
     bytes = Helpers.generateRandomBytes(32)
     bytes = Helpers.generateRandomBytes(32)
     const newNonce = Helpers.readBigIntFromBuffer(bytes, true, true)
     const newNonce = Helpers.readBigIntFromBuffer(bytes, true, true)

+ 6 - 2
src/lib/gramjs/network/MTProtoPlainSender.js

@@ -4,10 +4,10 @@
  */
  */
 const Helpers = require('../Helpers')
 const Helpers = require('../Helpers')
 const MTProtoState = require('./MTProtoState')
 const MTProtoState = require('./MTProtoState')
-const struct = require('python-struct')
 const BinaryReader = require('../extensions/BinaryReader')
 const BinaryReader = require('../extensions/BinaryReader')
 const { InvalidBufferError } = require('../errors/Common')
 const { InvalidBufferError } = require('../errors/Common')
 const BigInt = require('big-integer')
 const BigInt = require('big-integer')
+const { readBufferFromBigInt } = require("../Helpers")
 
 
 /**
 /**
  * MTProto Mobile Protocol plain sender (https://core.telegram.org/mtproto/description#unencrypted-messages)
  * MTProto Mobile Protocol plain sender (https://core.telegram.org/mtproto/description#unencrypted-messages)
@@ -32,7 +32,11 @@ class MTProtoPlainSender {
 
 
         let body = request.getBytes()
         let body = request.getBytes()
         let msgId = this._state._getNewMsgId()
         let msgId = this._state._getNewMsgId()
-        const res = Buffer.concat([ struct.pack('<qqi', [ 0, msgId.toString(), body.length ]), body ])
+        const m = readBufferFromBigInt(msgId, 8, true, true)
+        const b = Buffer.alloc(4)
+        b.writeInt32LE(body.length, 0)
+
+        const res = Buffer.concat([Buffer.concat([Buffer.alloc(8), m, b]), body])
 
 
         await this._connection.send(res)
         await this._connection.send(res)
         body = await this._connection.recv()
         body = await this._connection.recv()

+ 0 - 2
src/lib/gramjs/network/MTProtoSender.js

@@ -7,7 +7,6 @@ const RPCResult = require('../tl/core/RPCResult')
 const MessageContainer = require('../tl/core/MessageContainer')
 const MessageContainer = require('../tl/core/MessageContainer')
 const GZIPPacked = require('../tl/core/GZIPPacked')
 const GZIPPacked = require('../tl/core/GZIPPacked')
 const RequestState = require('./RequestState')
 const RequestState = require('./RequestState')
-const format = require('string-format')
 const { MsgsAck, File, MsgsStateInfo, Pong } = require('../tl').constructors
 const { MsgsAck, File, MsgsStateInfo, Pong } = require('../tl').constructors
 const MessagePacker = require('../extensions/MessagePacker')
 const MessagePacker = require('../extensions/MessagePacker')
 const BinaryReader = require('../extensions/BinaryReader')
 const BinaryReader = require('../extensions/BinaryReader')
@@ -29,7 +28,6 @@ const { LogOutRequest } = require('../tl').requests.auth
 const { RPCMessageToError } = require('../errors')
 const { RPCMessageToError } = require('../errors')
 const { TypeNotFoundError } = require('../errors/Common')
 const { TypeNotFoundError } = require('../errors/Common')
 
 
-format.extend(String.prototype, {})
 
 
 /**
 /**
  * MTProto Mobile Protocol sender
  * MTProto Mobile Protocol sender

+ 11 - 3
src/lib/gramjs/network/MTProtoState.js

@@ -1,4 +1,3 @@
-const struct = require('python-struct')
 const Helpers = require('../Helpers')
 const Helpers = require('../Helpers')
 const AES = require('../crypto/AES')
 const AES = require('../crypto/AES')
 const BinaryReader = require('../extensions/BinaryReader')
 const BinaryReader = require('../extensions/BinaryReader')
@@ -7,6 +6,8 @@ const { TLMessage } = require('../tl/core')
 const { SecurityError, InvalidBufferError } = require('../errors/Common')
 const { SecurityError, InvalidBufferError } = require('../errors/Common')
 const { InvokeAfterMsgRequest } = require('../tl').requests
 const { InvokeAfterMsgRequest } = require('../tl').requests
 const BigInt = require('big-integer')
 const BigInt = require('big-integer')
+const { readBufferFromBigInt } = require("../Helpers")
+const { readBigIntFromBuffer } = require("../Helpers")
 
 
 class MTProtoState {
 class MTProtoState {
     /**
     /**
@@ -97,7 +98,12 @@ class MTProtoState {
         } else {
         } else {
             body = await GZIPPacked.gzipIfSmaller(contentRelated, new InvokeAfterMsgRequest(afterId, data).getBytes())
             body = await GZIPPacked.gzipIfSmaller(contentRelated, new InvokeAfterMsgRequest(afterId, data).getBytes())
         }
         }
-        buffer.write(struct.pack('<qii', msgId.toString(), seqNo, body.length))
+        const s = Buffer.alloc(4)
+        s.writeInt32LE(seqNo, 0)
+        const b = Buffer.alloc(4)
+        b.writeInt32LE(body.length, 0)
+        const m = readBufferFromBigInt(msgId, 8, true, true)
+        buffer.write(Buffer.concat([m, s, b]))
         buffer.write(body)
         buffer.write(body)
         return msgId
         return msgId
     }
     }
@@ -109,7 +115,9 @@ class MTProtoState {
      */
      */
     async encryptMessageData(data) {
     async encryptMessageData(data) {
         await this.authKey.waitForKey()
         await this.authKey.waitForKey()
-        data = Buffer.concat([struct.pack('<qq', this.salt.toString(), this.id.toString()), data])
+        const s = readBufferFromBigInt(this.salt,8,true,true)
+        const i = readBufferFromBigInt(this.id,8,true,true)
+        data = Buffer.concat([Buffer.concat([s,i]), data])
         const padding = Helpers.generateRandomBytes(Helpers.mod(-(data.length + 12), 16) + 12)
         const padding = Helpers.generateRandomBytes(Helpers.mod(-(data.length + 12), 16) + 12)
         // Being substr(what, offset, length); x = 0 for client
         // Being substr(what, offset, length); x = 0 for client
         // "msg_key_large = SHA256(substr(auth_key, 88+x, 32) + pt + padding)"
         // "msg_key_large = SHA256(substr(auth_key, 88+x, 32) + pt + padding)"

+ 5 - 5
src/lib/gramjs/network/connection/TCPAbridged.js

@@ -1,4 +1,3 @@
-const struct = require('python-struct')
 const { readBufferFromBigInt } = require('../../Helpers')
 const { readBufferFromBigInt } = require('../../Helpers')
 const { Connection, PacketCodec } = require('./Connection')
 const { Connection, PacketCodec } = require('./Connection')
 const BigInt = require('big-integer')
 const BigInt = require('big-integer')
@@ -16,7 +15,9 @@ class AbridgedPacketCodec extends PacketCodec {
     encodePacket(data) {
     encodePacket(data) {
         let length = data.length >> 2
         let length = data.length >> 2
         if (length < 127) {
         if (length < 127) {
-            length = struct.pack('B', length)
+            const b = Buffer.alloc(1)
+            b.writeUInt8(length, 0)
+            length = b
         } else {
         } else {
             length = Buffer.concat([Buffer.from('7f', 'hex'), readBufferFromBigInt(BigInt(length), 3)])
             length = Buffer.concat([Buffer.from('7f', 'hex'), readBufferFromBigInt(BigInt(length), 3)])
         }
         }
@@ -25,10 +26,9 @@ class AbridgedPacketCodec extends PacketCodec {
 
 
     async readPacket(reader) {
     async readPacket(reader) {
         const readData = await reader.read(1)
         const readData = await reader.read(1)
-        let length = struct.unpack('<B', readData)[0]
+        let length = readData[0]
         if (length >= 127) {
         if (length >= 127) {
-            length = struct.unpack(
-                '<i', Buffer.concat([await reader.read(3), Buffer.alloc(1)]))[0]
+            length = Buffer.concat([await reader.read(3), Buffer.alloc(1)]).readInt32LE(0)
         }
         }
 
 
         return await reader.read(length << 2)
         return await reader.read(length << 2)

+ 56 - 0
src/lib/gramjs/network/connection/TCPFull.js

@@ -0,0 +1,56 @@
+const { Connection, PacketCodec } = require('./Connection')
+const { crc32 } = require('../../Helpers')
+const { InvalidChecksumError } = require('../../errors/Common')
+
+class FullPacketCodec extends PacketCodec {
+    constructor(connection) {
+        super(connection)
+        this._sendCounter = 0 // Telegram will ignore us otherwise
+    }
+
+    encodePacket(data) {
+        // https://core.telegram.org/mtproto#tcp-transport
+        // total length, sequence number, packet and checksum (CRC32)
+        const length = data.length + 12
+        const e = Buffer.alloc(8)
+        e.writeInt32LE(length,0)
+        e.writeInt32LE(this._sendCounter,4)
+        data = Buffer.concat([e, data])
+        const crc =  Buffer.alloc(4)
+        crc.writeUInt32LE(crc32(data),0)
+        this._sendCounter += 1
+        return Buffer.concat([data, crc])
+    }
+
+    /**
+     *
+     * @param reader {PromisedWebSockets}
+     * @returns {Promise<*>}
+     */
+    async readPacket(reader) {
+        const packetLenSeq = await reader.read(8) // 4 and 4
+        // process.exit(0);
+        if (packetLenSeq === undefined) {
+            return false
+        }
+        const packetLen = packetLenSeq.readInt32LE(0)
+        let body = await reader.read(packetLen - 8)
+        const [checksum] = body.slice(-4).readUInt32LE(0)
+        body = body.slice(0, -4)
+
+        const validChecksum = crc32(Buffer.concat([packetLenSeq, body]))
+        if (!(validChecksum === checksum)) {
+            throw new InvalidChecksumError(checksum, validChecksum)
+        }
+        return body
+    }
+}
+
+class ConnectionTCPFull extends Connection {
+    PacketCodecClass = FullPacketCodec;
+}
+
+module.exports = {
+    FullPacketCodec,
+    ConnectionTCPFull,
+}

+ 32 - 8
src/lib/gramjs/tl/core/GZIPPacked.js

@@ -1,10 +1,8 @@
-const struct = require('python-struct')
 const { serializeBytes } = require("../index")
 const { serializeBytes } = require("../index")
-const { ungzip } = require('node-gzip')
-const { gzip } = require('node-gzip')
+const zlib = require('zlib')
 
 
 class GZIPPacked {
 class GZIPPacked {
-    static CONSTRUCTOR_ID = 0x3072cfa1;
+    static CONSTRUCTOR_ID = 0x3072cfa1
     static classType = "constructor"
     static classType = "constructor"
 
 
     constructor(data) {
     constructor(data) {
@@ -23,10 +21,36 @@ class GZIPPacked {
         return data
         return data
     }
     }
 
 
+    static gzip(input, options) {
+        return new Promise(function (resolve, reject) {
+            zlib.gzip(input, options, function (error, result) {
+                if (!error) {
+                    resolve(result)
+                } else {
+                    reject(Error(error))
+                }
+            })
+        })
+    }
+
+    static ungzip(input, options) {
+        return new Promise(function (resolve, reject) {
+            zlib.gunzip(input, options, function (error, result) {
+                if (!error) {
+                    resolve(result)
+                } else {
+                    reject(Error(error))
+                }
+            })
+        })
+    }
+
     async toBytes() {
     async toBytes() {
+        const g = Buffer.alloc(0)
+        g.writeUInt32LE(GZIPPacked.CONSTRUCTOR_ID, 0)
         return Buffer.concat([
         return Buffer.concat([
-            struct.pack('<I', GZIPPacked.CONSTRUCTOR_ID),
-            serializeBytes(await gzip(this.data)),
+            g,
+            serializeBytes(await GZIPPacked.gzip(this.data)),
         ])
         ])
     }
     }
 
 
@@ -35,11 +59,11 @@ class GZIPPacked {
         if (constructor !== GZIPPacked.CONSTRUCTOR_ID) {
         if (constructor !== GZIPPacked.CONSTRUCTOR_ID) {
             throw new Error('not equal')
             throw new Error('not equal')
         }
         }
-        return await gzip(reader.tgReadBytes())
+        return await GZIPPacked.gzip(reader.tgReadBytes())
     }
     }
 
 
     static async fromReader(reader) {
     static async fromReader(reader) {
-        return new GZIPPacked(await ungzip(reader.tgReadBytes()))
+        return new GZIPPacked(await GZIPPacked.ungzip(reader.tgReadBytes()))
     }
     }
 }
 }
 
 

+ 39 - 0
src/lib/gramjs/tl/generationHelpers.js

@@ -1,4 +1,8 @@
+<<<<<<< HEAD
 const {crc32} = require('crc');
 const {crc32} = require('crc');
+=======
+const { crc32 } = require('../Helpers')
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib
 const snakeToCamelCase = (name) => {
 const snakeToCamelCase = (name) => {
   const result = name.replace(/(?:^|_)([a-z])/g, (_, g) => g.toUpperCase())
   const result = name.replace(/(?:^|_)([a-z])/g, (_, g) => g.toUpperCase())
   return result.replace(/_/g, '')
   return result.replace(/_/g, '')
@@ -62,7 +66,26 @@ const fromLine = (line, isFunction, methodInfo, layer) => {
     } else {
     } else {
       args = ''
       args = ''
     }
     }
+<<<<<<< HEAD
 
 
+=======
+    if (!currentConfig.constructorId) {
+
+        let hexId = ''
+        let args
+
+        if (Object.values(currentConfig.argsConfig).length) {
+            args = ` ${Object.keys(currentConfig.argsConfig).map((arg) => arg.toString()).join(' ')}`
+        } else {
+            args = ''
+        }
+
+        const representation = `${currentConfig.name}${hexId}${args} = ${currentConfig.result}`
+            .replace(/(:|\?)bytes /g, '$1string ')
+            .replace(/</g, ' ')
+            .replace(/>|{|}/g, '')
+            .replace(/ \w+:flags\.\d+\?true/g, '')
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib
 
 
     const representation = `${currentConfig.name}${hexId}${args} = ${currentConfig.result}`
     const representation = `${currentConfig.name}${hexId}${args} = ${currentConfig.result}`
       .replace(/(:|\?)bytes /g, '$1string ')
       .replace(/(:|\?)bytes /g, '$1string ')
@@ -311,6 +334,7 @@ function serializeBytes(data) {
 }
 }
 
 
 function serializeDate(dt) {
 function serializeDate(dt) {
+<<<<<<< HEAD
   if (!dt) {
   if (!dt) {
     return Buffer.alloc(4)
     return Buffer.alloc(4)
         .fill(0)
         .fill(0)
@@ -322,6 +346,21 @@ function serializeDate(dt) {
     return struct.pack('<i', dt)
     return struct.pack('<i', dt)
   }
   }
   throw Error(`Cannot interpret "${dt}" as a date`)
   throw Error(`Cannot interpret "${dt}" as a date`)
+=======
+    if (!dt) {
+        return Buffer.alloc(4)
+            .fill(0)
+    }
+    if (dt instanceof Date) {
+        dt = Math.floor((Date.now() - dt.getTime()) / 1000)
+    }
+    if (typeof dt == 'number') {
+        const t = Buffer.alloc(4)
+        t.writeInt32LE(dt, 0)
+        return t
+    }
+    throw Error(`Cannot interpret "${dt}" as a date`)
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib
 }
 }
 module.exports = {
 module.exports = {
   findAll,
   findAll,

+ 35 - 12
src/lib/gramjs/tl/gramJsApi.js

@@ -1,7 +1,11 @@
+<<<<<<< HEAD:src/lib/gramjs/tl/gramJsApi.js
 //const { readFileSync } = require('fs')
 //const { readFileSync } = require('fs')
 import { readFileSync } from 'fs'
 import { readFileSync } from 'fs'
 
 
 
 
+=======
+const { readFileSync } = require('fs')
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib:src/lib/gramjs/tl/api.js
 const {
 const {
     parseTl,
     parseTl,
     serializeBytes,
     serializeBytes,
@@ -58,19 +62,21 @@ function extractParams(fileContent) {
 function argToBytes(x, type) {
 function argToBytes(x, type) {
     switch (type) {
     switch (type) {
         case 'int':
         case 'int':
-            return (struct.pack('<i', x))
+            const i = Buffer.alloc(4)
+            return i.writeInt32LE(x, 0)
         case 'long':
         case 'long':
-            return (readBufferFromBigInt(x, 8, true, true))
+            return readBufferFromBigInt(x, 8, true, true)
         case 'int128':
         case 'int128':
-            return (readBufferFromBigInt(x, 16, true, true))
+            return readBufferFromBigInt(x, 16, true, true)
         case 'int256':
         case 'int256':
-            return (readBufferFromBigInt(x, 32, true, true))
+            return readBufferFromBigInt(x, 32, true, true)
         case 'double':
         case 'double':
-            return (struct.pack('<d', x.toString()))
+            const d = Buffer.alloc(8)
+            return d.writeDoubleLE(x, 0)
         case 'string':
         case 'string':
             return serializeBytes(x)
             return serializeBytes(x)
         case 'Bool':
         case 'Bool':
-            return (x ? Buffer.from('b5757299', 'hex') : Buffer.from('379779bc', 'hex'))
+            return x ? Buffer.from('b5757299', 'hex') : Buffer.from('379779bc', 'hex')
         case 'true':
         case 'true':
             return Buffer.alloc(0)
             return Buffer.alloc(0)
         case 'bytes':
         case 'bytes':
@@ -217,7 +223,9 @@ function createClasses(classesType, params) {
             getBytes() {
             getBytes() {
                 // The next is pseudo-code:
                 // The next is pseudo-code:
                 const idForBytes = this.CONSTRUCTOR_ID
                 const idForBytes = this.CONSTRUCTOR_ID
-                const buffers = [struct.pack('<I', idForBytes)]
+                const c = Buffer.alloc(4)
+                c.writeUInt32LE(idForBytes, 0)
+                const buffers = [c]
                 for (const arg in argsConfig) {
                 for (const arg in argsConfig) {
                     if (argsConfig.hasOwnProperty(arg)) {
                     if (argsConfig.hasOwnProperty(arg)) {
                         if (argsConfig[arg].isFlag) {
                         if (argsConfig[arg].isFlag) {
@@ -228,14 +236,18 @@ function createClasses(classesType, params) {
                                 if (argsConfig[arg].useVectorId) {
                                 if (argsConfig[arg].useVectorId) {
                                     tempBuffers.push(Buffer.from('15c4b51c', 'hex'))
                                     tempBuffers.push(Buffer.from('15c4b51c', 'hex'))
                                 }
                                 }
+                                const l = Buffer.alloc(4)
+                                l.writeInt32LE(this[arg].length, 0)
                                 buffers.push((!this[arg] ? Buffer.alloc(0) : Buffer.concat([...tempBuffers,
                                 buffers.push((!this[arg] ? Buffer.alloc(0) : Buffer.concat([...tempBuffers,
-                                    struct.pack('<i', this[arg].length), Buffer.concat(this[arg].map(x => argToBytes(x, argsConfig[arg].type)))])))
+                                    l, Buffer.concat(this[arg].map(x => argToBytes(x, argsConfig[arg].type)))])))
                             }
                             }
                         } else if (argsConfig[arg].isVector && !argsConfig[arg].isFlag) {
                         } else if (argsConfig[arg].isVector && !argsConfig[arg].isFlag) {
                             if (argsConfig[arg].isVector) {
                             if (argsConfig[arg].isVector) {
                                 buffers.push(Buffer.from('15c4b51c', 'hex'))
                                 buffers.push(Buffer.from('15c4b51c', 'hex'))
                             }
                             }
-                            buffers.push(struct.pack('<i', this[arg].length), Buffer.concat(this[arg].map(x => argToBytes(x, argsConfig[arg].type))))
+                            const l = Buffer.alloc(4)
+                            l.writeInt32LE(this[arg].length, 0)
+                            buffers.push(l, Buffer.concat(this[arg].map(x => argToBytes(x, argsConfig[arg].type))))
                         } else if (argsConfig[arg].flagIndicator) {
                         } else if (argsConfig[arg].flagIndicator) {
                             // @ts-ignore
                             // @ts-ignore
                             if (!Object.values(argsConfig)
                             if (!Object.values(argsConfig)
@@ -252,13 +264,17 @@ function createClasses(classesType, params) {
                                         }
                                         }
                                     }
                                     }
                                 }
                                 }
-                                buffers.push(struct.pack('<I', flagCalculate))
+                                const f = Buffer.alloc(4)
+                                f.writeUInt32LE(flagCalculate, 0)
+                                buffers.push(f)
                             }
                             }
                         } else {
                         } else {
 
 
                             switch (argsConfig[arg].type) {
                             switch (argsConfig[arg].type) {
                                 case 'int':
                                 case 'int':
-                                    buffers.push(struct.pack('<i', this[arg]))
+                                    const i = Buffer.alloc(4)
+                                    i.writeInt32LE(this[arg], 0)
+                                    buffers.push(i)
                                     break
                                     break
                                 case 'long':
                                 case 'long':
                                     buffers.push(readBufferFromBigInt(this[arg], 8, true, true))
                                     buffers.push(readBufferFromBigInt(this[arg], 8, true, true))
@@ -270,7 +286,9 @@ function createClasses(classesType, params) {
                                     buffers.push(readBufferFromBigInt(this[arg], 32, true, true))
                                     buffers.push(readBufferFromBigInt(this[arg], 32, true, true))
                                     break
                                     break
                                 case 'double':
                                 case 'double':
-                                    buffers.push(struct.pack('<d', this[arg].toString()))
+                                    const d = Buffer.alloc(8)
+                                    d.writeDoubleLE(this[arg].toString(), 0)
+                                    buffers.push(d)
                                     break
                                     break
                                 case 'string':
                                 case 'string':
                                     buffers.push(serializeBytes(this[arg]))
                                     buffers.push(serializeBytes(this[arg]))
@@ -373,5 +391,10 @@ function createClasses(classesType, params) {
     return classes
     return classes
 }
 }
 
 
+<<<<<<< HEAD:src/lib/gramjs/tl/gramJsApi.js
 const gramJsApi = buildApiFromTlSchema()
 const gramJsApi = buildApiFromTlSchema()
 module.exports = gramJsApi
 module.exports = gramJsApi
+=======
+module.exports = buildApiFromTlSchema()
+console.log(module.exports)
+>>>>>>> 1ab480fe... Gram JS: Remove deps; Fix Factorizator and remove leemon lib:src/lib/gramjs/tl/api.js