Prechádzať zdrojové kódy

Various fixes
Support node again

painor 4 rokov pred
rodič
commit
fe4cacde72

+ 1 - 3
.gitignore

@@ -6,8 +6,6 @@
 /gramjs/tl/functions/
 /gramjs/tl/types/
 /gramjs/tl/patched/
-/gramjs/tl/AllTLObjects.js
-/gramjs/errors/RPCErrorList.js
 /dist/
 /coverage/
 
@@ -23,4 +21,4 @@ example.js
 
 settings
 
-/browser/
+/browser/

+ 5 - 3
gramjs/Helpers.js

@@ -1,5 +1,7 @@
-const crypto = require('./crypto/crypto')
+
 const BigInt = require('big-integer')
+const IS_NODE = !(this.window === this)
+const crypto = require(IS_NODE ? 'crypto' : './crypto/crypto')
 
 /**
  * converts a buffer to big int
@@ -343,6 +345,6 @@ module.exports = {
     getByteArray,
     //isArrayLike,
     toSignedLittleBuffer,
-    convertToLittle
-
+    convertToLittle,
+    IS_NODE
 }

+ 19 - 15
gramjs/Utils.js

@@ -1,4 +1,6 @@
+const {IS_NODE} = require("./Helpers");
 const { constructors } = require('./tl')
+const { requests } = require('./tl')
 
 const USERNAME_RE = new RegExp('@|(?:https?:\\/\\/)?(?:www\\.)?' +
     '(?:telegram\\.(?:me|dog)|t\\.me)\\/(@|joinchat\\/)?')
@@ -612,12 +614,13 @@ function isListLike(item) {
     )
 }
 */
-function getDC(dcId, cdn = false) {
+async function getDC(dcId,client, cdn = false) {
+    if (!IS_NODE){
     switch (dcId) {
         case 1:
             return {
                 id: 1,
-                ipAddress: 'pluto.web.telegram.org',
+                ipAddress: IS_NODE?'':'pluto.web.telegram.org',
                 port: 443
             }
         case 2:
@@ -647,22 +650,23 @@ function getDC(dcId, cdn = false) {
         default:
             throw new Error(`Cannot find the DC with the ID of ${dcId}`)
     }
-    // TODO chose based on current connection method
-    /*
-    if (!this._config) {
-        this._config = await this.invoke(new requests.help.GetConfig())
     }
-    if (cdn && !this._cdnConfig) {
-        this._cdnConfig = await this.invoke(new requests.help.GetCdnConfig())
-        for (const pk of this._cdnConfig.publicKeys) {
-            addKey(pk.publicKey)
-        }
+    if (!client._config) {
+        client._config = await client.invoke(new requests.help.GetConfig())
+    }
+    if (cdn) {
+        throw new Error(`CDNs are Not supported`)
     }
-    for (const DC of this._config.dcOptions) {
-        if (DC.id === dcId && Boolean(DC.ipv6) === this._useIPV6 && Boolean(DC.cdn) === cdn) {
-            return DC
+
+    for (const DC of client._config.dcOptions) {
+        if (DC.id === dcId && Boolean(DC.ipv6) === client._useIPV6 && Boolean(DC.cdn) === cdn) {
+            return {
+                id:DC.id,
+                ipAddress:DC.ipAddress,
+                port:443
+            }
         }
-    }*/
+    }
 }
 
 module.exports = {

+ 8 - 11
gramjs/client/TelegramClient.js

@@ -1,5 +1,5 @@
 const Logger = require('../extensions/Logger')
-const { sleep } = require('../Helpers')
+const { sleep,IS_NODE } = require('../Helpers')
 const errors = require('../errors')
 const MemorySession = require('../sessions/Memory')
 const Helpers = require('../Helpers')
@@ -12,12 +12,13 @@ const { constructors, requests } = require('../tl')
 const MTProtoSender = require('../network/MTProtoSender')
 const { UpdateConnectionState } = require("../network")
 const { ConnectionTCPObfuscated } = require('../network/connection/TCPObfuscated')
+const { ConnectionTCPFull } = require('../network/connection/TCPFull')
 const { authFlow, checkAuthorization } = require('./auth')
 const { downloadFile } = require('./downloadFile')
 const { uploadFile } = require('./uploadFile')
 
-const DEFAULT_DC_ID = 2
-const DEFAULT_IPV4_IP = 'venus.web.telegram.org'
+const DEFAULT_DC_ID = 1
+const DEFAULT_IPV4_IP = IS_NODE?'149.154.167.51':'pluto.web.telegram.org'
 const DEFAULT_IPV6_IP = '[2001:67c:4e8:f002::a]'
 
 // All types
@@ -26,7 +27,7 @@ const sizeTypes = ['w', 'y', 'd', 'x', 'c', 'm', 'b', 'a', 's']
 
 class TelegramClient {
     static DEFAULT_OPTIONS = {
-        connection: ConnectionTCPObfuscated,
+        connection:IS_NODE? ConnectionTCPFull: ConnectionTCPObfuscated,
         useIPV6: false,
         proxy: null,
         timeout: 10,
@@ -68,11 +69,7 @@ class TelegramClient {
         }
         // Determine what session we will use
         if (typeof session === 'string' || !session) {
-            try {
-                throw new Error('not implemented')
-            } catch (e) {
-                session = new MemorySession()
-            }
+            throw new Error('not implemented')
         } else if (!(session instanceof Session)) {
             throw new Error('The given session must be str or a session instance')
         }
@@ -231,7 +228,7 @@ class TelegramClient {
 
     async _switchDC(newDc) {
         this._log.info(`Reconnecting to new data center ${newDc}`)
-        const DC = utils.getDC(newDc)
+        const DC = await utils.getDC(newDc,this)
         this.session.setDC(newDc, DC.ipAddress, DC.port)
         // authKey's are associated with a server, which has now changed
         // so it's not valid anymore. Set to None to force recreating it.
@@ -268,7 +265,7 @@ class TelegramClient {
     }
 
     async _createExportedSender(dcId, retries) {
-        const dc = utils.getDC(dcId)
+        const dc = await utils.getDC(dcId,this)
         const sender = new MTProtoSender(this.session.getAuthKey(dcId),
             {
                 logger: this._log,

+ 2 - 3
gramjs/client/auth.ts

@@ -1,6 +1,6 @@
-import { default as Api } from '../tl/api';
+import  * as Api  from '../tl/api';
 import TelegramClient from './TelegramClient';
-import utils from '../Utils';
+import * as utils from '../Utils';
 import { sleep } from '../Helpers';
 import { computeCheck as computePasswordSrpCheck } from '../Password';
 
@@ -308,6 +308,5 @@ async function signInBot(client: TelegramClient, apiCredentials: ApiCredentials,
         apiHash,
         botAuthToken,
     })) as Api.auth.Authorization;
-
     return user;
 }

+ 0 - 1
gramjs/crypto/crypto.js

@@ -1,7 +1,6 @@
 const AES = require('@cryptography/aes').default;
 const { i2ab, ab2i } = require('./converters');
 const { getWords } = require('./words');
-
 class Counter {
     constructor(initialValue) {
         this.setBytes(initialValue)

+ 87 - 0
gramjs/errors/RPCErrorList.js

@@ -0,0 +1,87 @@
+const { RPCError, InvalidDCError, FloodError } = require('./RPCBaseErrors')
+
+
+class UserMigrateError extends InvalidDCError {
+    constructor(args) {
+        const newDc = Number(args.capture || 0)
+        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
+    }
+}
+
+
+class PhoneMigrateError extends InvalidDCError {
+    constructor(args) {
+        const newDc = Number(args.capture || 0)
+        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
+    }
+}
+
+class SlowModeWaitError extends FloodError {
+    constructor(args) {
+        const seconds = Number(args.capture || 0)
+        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
+    }
+}
+
+class FloodWaitError extends FloodError {
+    constructor(args) {
+        const seconds = Number(args.capture || 0)
+        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
+    }
+}
+
+class FloodTestPhoneWaitError extends FloodError {
+    constructor(args) {
+        const seconds = Number(args.capture || 0)
+        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
+    }
+}
+
+class FileMigrateError extends InvalidDCError {
+    constructor(args) {
+        const newDc = Number(args.capture || 0)
+        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
+    }
+}
+
+class NetworkMigrateError extends InvalidDCError {
+    constructor(args) {
+        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
+    }
+}
+
+const rpcErrorRe = [
+    [/FILE_MIGRATE_(\d+)/, FileMigrateError],
+    [/FLOOD_TEST_PHONE_WAIT_(\d+)/, FloodTestPhoneWaitError],
+    [/FLOOD_WAIT_(\d+)/, FloodWaitError],
+    [/PHONE_MIGRATE_(\d+)/, PhoneMigrateError],
+    [/SLOWMODE_WAIT_(\d+)/, SlowModeWaitError],
+    [/USER_MIGRATE_(\d+)/, UserMigrateError],
+    [/NETWORK_MIGRATE_(\d+)/, NetworkMigrateError],
+
+]
+module.exports = {
+    rpcErrorRe,
+    FileMigrateError,
+    FloodTestPhoneWaitError,
+    FloodWaitError,
+    PhoneMigrateError,
+    SlowModeWaitError,
+    UserMigrateError,
+    NetworkMigrateError
+}

+ 117 - 0
gramjs/extensions/PromisedNetSockets.js

@@ -0,0 +1,117 @@
+const Socket = require('net').Socket
+const Mutex = require('async-mutex').Mutex
+const mutex = new Mutex()
+
+const closeError = new Error('NetSocket was closed')
+
+class PromisedNetSockets {
+    constructor() {
+        this.client = null
+        this.closed = true
+    }
+
+    async readExactly(number) {
+        let readData = Buffer.alloc(0)
+        while (true) {
+            const thisTime = await this.read(number)
+            readData = Buffer.concat([readData, thisTime])
+            number = number - thisTime.length
+            if (!number) {
+                return readData
+            }
+        }
+    }
+
+    async read(number) {
+        if (this.closed) {
+            throw closeError
+        }
+        await this.canRead
+        if (this.closed) {
+            throw closeError
+        }
+        const toReturn = this.stream.slice(0, number)
+        this.stream = this.stream.slice(number)
+        if (this.stream.length === 0) {
+            this.canRead = new Promise((resolve) => {
+                this.resolveRead = resolve
+            })
+        }
+
+        return toReturn
+    }
+
+    async readAll() {
+        if (this.closed || !await this.canRead) {
+            throw closeError
+        }
+        const toReturn = this.stream
+        this.stream = Buffer.alloc(0)
+        this.canRead = new Promise((resolve) => {
+            this.resolveRead = resolve
+        })
+        return toReturn
+    }
+
+    /**
+     * Creates a new connection
+     * @param port
+     * @param ip
+     * @returns {Promise<void>}
+     */
+    async connect(port, ip) {
+        this.stream = Buffer.alloc(0)
+
+        this.client = new Socket()
+        this.canRead = new Promise((resolve) => {
+            this.resolveRead = resolve
+        })
+        this.closed = false
+        return new Promise((resolve, reject) => {
+            this.client.connect(port, ip, () => {
+                this.receive()
+                resolve(this)
+            })
+            this.client.on('error', reject)
+            this.client.on('close', () => {
+                if (this.client.closed) {
+                    this.resolveRead(false)
+                    this.closed = true
+                }
+            })
+        })
+    }
+
+    write(data) {
+        if (this.closed) {
+            throw closeError
+        }
+        this.client.write(data)
+    }
+
+
+
+    async close() {
+        await this.client.destroy()
+        this.client.unref()
+        this.closed = true
+    }
+
+    async receive() {
+        this.client.on('data', async (message) => {
+
+            const release = await mutex.acquire()
+            try {
+                let data
+                //CONTEST BROWSER
+                this.stream = Buffer.concat([this.stream, message])
+                this.resolveRead(true)
+            } finally {
+                release()
+            }
+        })
+    }
+}
+
+module.exports = PromisedNetSockets
+

+ 0 - 2
gramjs/network/Authenticator.js

@@ -19,7 +19,6 @@ async function doAuthentication(sender, log) {
     let bytes = Helpers.generateRandomBytes(16)
 
     const nonce = Helpers.readBigIntFromBuffer(bytes, false, true)
-
     const resPQ = await sender.send(new requests.ReqPqMulti({ nonce: nonce }))
     log.debug('Starting authKey generation step 1')
 
@@ -41,7 +40,6 @@ async function doAuthentication(sender, log) {
 
     bytes = Helpers.generateRandomBytes(32)
     const newNonce = Helpers.readBigIntFromBuffer(bytes, true, true)
-
     const pqInnerData = new constructors.PQInnerData({
         pq: Helpers.getByteArray(pq), // unsigned
         p: p,

+ 2 - 0
gramjs/network/MTProtoPlainSender.js

@@ -31,6 +31,7 @@ class MTProtoPlainSender {
     async send(request) {
 
         let body = request.getBytes()
+
         let msgId = this._state._getNewMsgId()
         const m = toSignedLittleBuffer(msgId, 8)
         const b = Buffer.alloc(4)
@@ -40,6 +41,7 @@ class MTProtoPlainSender {
 
         await this._connection.send(res)
         body = await this._connection.recv()
+
         if (body.length < 8) {
             throw new InvalidBufferError(body)
         }

+ 4 - 0
gramjs/network/MTProtoSender.js

@@ -170,7 +170,10 @@ class MTProtoSender {
                 if (attempt===0 && eventDispatch!==null){
                     eventDispatch({ update: new UpdateConnectionState(-1) })
                 }
+                console.log(e);
+
                 this._log.error("WebSocket connection failed attempt : "+(attempt+1))
+                process.exit(0)
                 await Helpers.sleep(this._delay)
             }
         }
@@ -803,6 +806,7 @@ class MTProtoSender {
                 break
             } catch (e) {
                 this._log.error("WebSocket connection failed attempt : "+(attempt+1))
+                console.log(e)
                 await Helpers.sleep(this._delay)
             }
         }

+ 5 - 3
gramjs/network/connection/Connection.js

@@ -1,4 +1,5 @@
 const PromisedWebSockets = require('../../extensions/PromisedWebSockets')
+const PromisedNetSockets = require('../../extensions/PromisedNetSockets')
 const AsyncQueue = require('../../extensions/AsyncQueue')
 
 /**
@@ -27,9 +28,9 @@ class Connection {
         this._obfuscation = null // TcpObfuscated and MTProxy
         this._sendArray = new AsyncQueue()
         this._recvArray = new AsyncQueue()
-        //this.socket = new PromiseSocket(new Socket())
+        this.socket = new PromisedNetSockets()
 
-        this.socket = new PromisedWebSockets()
+        //this.socket = new PromisedWebSockets()
     }
 
     async _connect() {
@@ -67,6 +68,7 @@ class Connection {
     async recv() {
         while (this._connected) {
             const result = await this._recvArray.pop()
+
             // null = sentinel value = keep trying
             if (result) {
                 return result
@@ -102,7 +104,7 @@ class Connection {
             } catch (e) {
                 this._log.info('connection closed')
                 //await this._recvArray.push()
-
+                console.log(e)
                 this.disconnect()
                 return
             }

+ 56 - 57
gramjs/network/connection/TCPFull.js

@@ -1,57 +1,56 @@
-//CONTEST
-// 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,
-// }
+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,
+}

+ 1 - 1
gramjs/sessions/CacheApiSession.js

@@ -20,7 +20,7 @@ class CacheApi extends MemorySession {
         try {
             const json = await fetchFromCache(this._storageKey)
             const { mainDcId, keys, hashes } = JSON.parse(json)
-            const { ipAddress, port } = utils.getDC(mainDcId)
+            const { ipAddress, port } = await utils.getDC(mainDcId)
 
             this.setDC(mainDcId, ipAddress, port, true)
 

+ 19 - 0
gramjs/tl/AllTLObjects.js

@@ -0,0 +1,19 @@
+const api = require('./api')
+const LAYER = 112
+const tlobjects = {}
+
+
+for (const tl of Object.values(api)) {
+    if (tl.CONSTRUCTOR_ID) {
+        tlobjects[tl.CONSTRUCTOR_ID] = tl
+    } else {
+        for (const sub of Object.values(tl)) {
+            tlobjects[sub.CONSTRUCTOR_ID] = sub
+        }
+    }
+}
+
+module.exports = {
+    LAYER,
+    tlobjects
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 0 - 10113
gramjs/tl/api.d.ts


+ 10 - 3
gramjs/tl/api.js

@@ -3,10 +3,17 @@ const {
     serializeBytes,
     serializeDate
 } = require('./generationHelpers')
-const { readBufferFromBigInt,toSignedLittleBuffer } = require('../Helpers')
+const { IS_NODE,toSignedLittleBuffer } = require('../Helpers')
+let tlContent,schemeContent;
+if (IS_NODE){
+    const fs = require("fs");
+    tlContent = fs.readFileSync('./static/api.tl',"utf-8");
+    schemeContent = fs.readFileSync('./static/schema.tl',"utf-8");
+}else{
+     tlContent = require('./static/api.reduced.tl').default;
+     schemeContent = require('./static/schema.reduced.tl').default;
 
-const tlContent = require('./static/api.reduced.tl').default;
-const schemeContent = require('./static/schema.reduced.tl').default;
+}
 
 /*CONTEST
 const NAMED_AUTO_CASTS = new Set([

+ 0 - 186
index.js

@@ -1,186 +0,0 @@
-const fs = require('fs')
-const path = require('path')
-const glob = require('glob')
-
-class TempWorkDir {
-    /**
-     * Switches the working directory to be the one on which this file lives.
-     */
-    constructor(dir) {
-        this.original = null
-        this.dir = dir || path.join(__filename, '..')
-    }
-
-    open() {
-        this.original = __dirname
-        fs.mkdirSync(this.dir, { recursive: true })
-        process.chdir(this.dir)
-        return this
-    }
-
-    close() {
-        process.chdir(this.original)
-    }
-}
-
-const GENERATOR_DIR = './gramjs_generator'
-const LIBRARY_DIR = './gramjs'
-
-const ERRORS_IN = `${GENERATOR_DIR}/data/errors.csv`
-const ERRORS_OUT = `${LIBRARY_DIR}/errors/RPCErrorList.js`
-
-const METHODS_IN = `${GENERATOR_DIR}/data/methods.csv`
-
-// Which raw API methods are covered by *friendly* methods in the client?
-const FRIENDLY_IN = `${GENERATOR_DIR}/data/friendly.csv`
-
-const TLOBJECT_IN_TLS = glob.sync(`${GENERATOR_DIR}/data/*.tl`)
-const TLOBJECT_OUT = `${LIBRARY_DIR}/tl`
-const IMPORT_DEPTH = 2
-
-const DOCS_IN_RES = `../${GENERATOR_DIR}/data/html`
-const DOCS_OUT = `./docs`
-
-const generate = (which, action = 'gen') => {
-    const {
-        parseErrors,
-        parseMethods,
-        parseTl,
-        findLayer,
-    } = require('./gramjs_generator/parsers')
-
-    const {
-        generateErrors,
-        generateTLObjects,
-        generateDocs,
-        cleanTLObjects,
-    } = require('./gramjs_generator/generators')
-
-    const [layer] = TLOBJECT_IN_TLS.map(findLayer).filter(Boolean)
-    const errors = [...parseErrors(ERRORS_IN)]
-    const methods = [
-        ...parseMethods(
-            METHODS_IN,
-            FRIENDLY_IN,
-            errors.reduce((errors, error) => {
-                errors[error.stringCode] = error
-                return errors
-            }, {})
-        ),
-    ]
-
-    const tlobjects = TLOBJECT_IN_TLS.reduce(
-        (files, file) => [...files, ...parseTl(file, layer, methods)],
-        []
-    )
-
-    if (!which || which.length === 0) {
-        which.push('tl', 'errors')
-    }
-
-    const clean = action === 'clean'
-    action = clean ? 'Cleaning' : 'Generating'
-
-    if (which.includes('all')) {
-        which.splice(which.indexOf('all'), 1)
-
-        for (const x of ['tl', 'errors', 'docs']) {
-            if (!which.includes(x)) {
-                which.push(x)
-            }
-        }
-    }
-
-    if (which.includes('tl')) {
-        which.splice(which.indexOf('tl'), 1)
-        console.log(action, 'TLObjects...')
-
-        if (clean) {
-            cleanTLObjects(TLOBJECT_OUT)
-        } else {
-            generateTLObjects(tlobjects, layer, IMPORT_DEPTH, TLOBJECT_OUT)
-        }
-    }
-
-    if (which.includes('errors')) {
-        which.splice(which.indexOf('errors'), 1)
-        console.log(action, 'RPCErrors...')
-
-        if (clean) {
-            if (fs.statSync(ERRORS_OUT).isFile()) {
-                fs.unlinkSync(ERRORS_OUT)
-            }
-        } else {
-            const file = fs.createWriteStream(ERRORS_OUT)
-            generateErrors(errors, file)
-        }
-    }
-
-    if (which.includes('docs')) {
-        which.splice(which.indexOf('docs'), 1)
-        console.log(action, 'documentation...')
-
-        if (clean) {
-            if (fs.statSync(DOCS_OUT)) {
-                fs.rmdirSync(DOCS_OUT)
-            }
-        } else {
-            const tmp = new TempWorkDir(DOCS_OUT).open()
-            generateDocs(tlobjects, methods, layer, DOCS_IN_RES)
-            tmp.close()
-        }
-    }
-
-    if (which.includes('json')) {
-        which.splice(which.indexOf('json'), 1)
-        console.log(action, 'JSON schema...')
-
-        const jsonFiles = TLOBJECT_IN_TLS.map(
-            (x) => x.slice(0, x.lastIndexOf('.')) + '.json'
-        )
-
-        if (clean) {
-            for (const file of jsonFiles) {
-                if (fs.statSync(file).isFile()) {
-                    fs.unlinkSync(file)
-                }
-            }
-        } else {
-            const genJson = (fin, fout) => {
-                const meths = []
-                const constructors = []
-
-                for (const tl of parseTl(fin, layer)) {
-                    if (tl.isFunction) {
-                        meths.push(tl.toJson())
-                    } else {
-                        constructors.push(tl.toJson())
-                    }
-                }
-
-                const what = { constructors, methods }
-                fs.writeFileSync(fout, JSON.stringify(what, null, 2))
-            }
-
-            for (let i = 0; i < TLOBJECT_IN_TLS.length; i++) {
-                const fin = TLOBJECT_IN_TLS[i]
-                const fout = jsonFiles[i]
-                genJson(fin, fout)
-            }
-        }
-    }
-
-    if (which.length) {
-        console.log('The following items were not understood:', which)
-        console.log('  Consider using only "tl", "errors" and/or "docs".')
-        console.log(
-            '  Using only "clean" will clean them. "all" to act on all.'
-        )
-        console.log('  For instance "gen tl errors".')
-    }
-}
-
-const { argv } = process
-if (argv.length > 2 && argv[2] === 'gen') {
-    generate(argv.slice(3))
-}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 484 - 317
package-lock.json


+ 33 - 33
package.json

@@ -5,8 +5,7 @@
   "main": "index.js",
   "scripts": {
     "test": "jest",
-    "lint": "eslint .",
-    "postinstall": "node index.js gen tl errors"
+    "lint": "eslint ."
   },
   "repository": {
     "type": "git",
@@ -20,38 +19,39 @@
     "url": "https://github.com/gram-js/gramjs/issues"
   },
   "homepage": "https://github.com/gram-js/gramjs#readme",
-  "dependencies": {
-    "@babel/core": "^7.7.7",
-    "@babel/plugin-proposal-class-properties": "^7.7.0",
-    "@babel/preset-env": "^7.7.7",
-    "aes-js": "^3.1.2",
-    "babel-loader": "^8.0.6",
-    "babel-register": "^6.26.0",
-    "better-sqlite3": "^5.4.3",
-    "chalk": "^2.4.2",
-    "crc": "^3.8.0",
-    "csv-parse": "^4.4.6",
-    "fast-csv": "^3.4.0",
-    "glob": "^7.1.4",
-    "mime-types": "^2.1.25",
-    "net": "^1.0.2",
-    "node-gzip": "^1.1.2",
-    "node-rsa": "^1.0.6",
-    "python-struct": "^1.1.1",
-    "regenerator-runtime": "^0.13.3",
-    "sqlite3": "^4.1.1",
-    "stack-trace": "0.0.10",
-    "string-format": "^2.0.0",
-    "websocket": "^1.0.30"
-  },
   "devDependencies": {
-    "@babel/plugin-transform-async-to-generator": "^7.7.0",
+    "@babel/core": "^7.10.2",
+    "@babel/plugin-proposal-class-properties": "^7.7.0",
+    "@babel/preset-env": "^7.10.2",
+    "@babel/preset-react": "^7.10.1",
+    "@babel/preset-typescript": "^7.10.1",
+    "@types/croppie": "^2.5.4",
+    "@types/css-font-loading-module": "0.0.2",
+    "@types/dom-mediacapture-record": "^1.0.3",
+    "@types/resize-observer-browser": "^0.1.3",
+    "@typescript-eslint/eslint-plugin": "^2.6.1",
+    "@typescript-eslint/parser": "^2.6.1",
+    "autoprefixer": "^9.8.0",
     "babel-eslint": "^10.0.3",
-    "babel-jest": "^24.9.0",
-    "eslint": "^6.5.1",
-    "jest": "^24.9.0",
-    "webpack": "^4.41.2",
-    "webpack-cli": "^3.3.10",
-    "websocket-as-promised": "^0.10.1"
+    "babel-loader": "^8.1.0",
+    "eslint": "^7.2.0",
+    "eslint-config-airbnb-typescript": "^6.0.0",
+    "eslint-config-react-app": "^5.0.2",
+    "eslint-import-resolver-webpack": "^0.12.1",
+    "eslint-plugin-flowtype": "^3.13.0",
+    "eslint-plugin-import": "^2.20.2",
+    "eslint-plugin-jsx-a11y": "^6.2.3",
+    "eslint-plugin-no-async-without-await": "^1.2.0",
+    "lint-staged": "^9.4.2",
+    "ts-node": "^8.9.1",
+    "typescript": "^3.9.5",
+    "url-loader": "^4.1.0"
+  },
+  "dependencies": {
+    "@cryptography/aes": "^0.1.1",
+    "async-mutex": "^0.1.4",
+    "big-integer": "painor/BigInteger.js",
+    "pako": "^1.0.10",
+    "websocket": "^1.0.30"
   }
 }

+ 82 - 62
static/api.tl

@@ -71,12 +71,9 @@ inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int =
 inputMediaGame#d33f43f3 id:InputGame = InputMedia;
 inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
 inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
-<<<<<<< HEAD
-inputMediaPoll#6b3765b poll:Poll = InputMedia;
+inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
+inputMediaDice#e66fbf7b emoticon:string = InputMedia;
 
-=======
-inputMediaPoll#abe9ca25 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> = InputMedia;
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
 inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
 inputChatUploadedPhoto#927c55b4 file:InputFile = InputChatPhoto;
 inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
@@ -132,7 +129,7 @@ channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
 channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
 
 chatFull#1b7c9db3 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
-channelFull#2d895c74 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true can_set_location:flags.16?true has_scheduled:flags.19?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int pts:int = ChatFull;
+channelFull#f0e6672a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true can_set_location:flags.16?true has_scheduled:flags.19?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int = ChatFull;
 
 chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
 chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@@ -160,6 +157,7 @@ messageMediaGame#fdb19008 game:Game = MessageMedia;
 messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
 messageMediaGeoLive#7c3c2609 geo:GeoPoint period:int = MessageMedia;
 messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
+messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;
 
 messageActionEmpty#b6aef7b0 = MessageAction;
 messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
@@ -218,11 +216,8 @@ peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bo
 peerSettings#818426cd flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true = PeerSettings;
 
 wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
-<<<<<<< HEAD
-
-=======
 wallPaperNoFile#8af40b25 flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
+
 inputReportReasonSpam#58dbcab8 = ReportReason;
 inputReportReasonViolence#1e22c78d = ReportReason;
 inputReportReasonPornography#2e59d922 = ReportReason;
@@ -356,13 +351,13 @@ updatePeerLocated#b4afcfb0 peers:Vector<PeerLocated> = Update;
 updateNewScheduledMessage#39a51dfb message:Message = Update;
 updateDeleteScheduledMessages#90866cee peer:Peer messages:Vector<int> = Update;
 updateTheme#8216fba3 theme:Theme = Update;
-<<<<<<< HEAD
-
-=======
 updateGeoLiveViewed#871fb939 peer:Peer msg_id:int = Update;
 updateLoginToken#564fe691 = Update;
 updateMessagePollVote#42f88f2c poll_id:long user_id:int options:Vector<bytes> = Update;
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
+updateDialogFilter#26ffde7d flags:# id:int filter:flags.0?DialogFilter = Update;
+updateDialogFilterOrder#a5d72105 order:Vector<int> = Update;
+updateDialogFilters#3504914f = Update;
+
 updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
 
 updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
@@ -512,7 +507,7 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
 webPageEmpty#eb1477e8 id:long = WebPage;
 webPagePending#c586da1c id:long date:int = WebPage;
 webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
-webPageNotModified#85849473 = WebPage;
+webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;
 
 authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
 
@@ -538,6 +533,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
 inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
 inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
 inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
+inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
 
 stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
 
@@ -557,11 +553,8 @@ keyboardButtonGame#50f41ccf text:string = KeyboardButton;
 keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
 keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
 inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
-<<<<<<< HEAD
-
-=======
 keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = KeyboardButton;
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
+
 keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
 
 replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup;
@@ -587,6 +580,7 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
 messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
 messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
 messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
+messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
 
 inputChannelEmpty#ee8c1e86 = InputChannel;
 inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
@@ -698,8 +692,8 @@ contacts.topPeersDisabled#b52c939d = contacts.TopPeers;
 draftMessageEmpty#1b0c841a flags:# date:flags.0?int = DraftMessage;
 draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage;
 
-messages.featuredStickersNotModified#4ede3cf = messages.FeaturedStickers;
-messages.featuredStickers#f89d88e5 hash:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
+messages.featuredStickersNotModified#c6dc0c66 count:int = messages.FeaturedStickers;
+messages.featuredStickers#b6abc341 hash:int count:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;
 
 messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
 messages.recentStickers#22f3afb3 hash:int packs:Vector<StickerPack> stickers:Vector<Document> dates:Vector<int> = messages.RecentStickers;
@@ -835,7 +829,7 @@ phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?
 
 phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
 
-phoneCallProtocol#a2bb35cb flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int = PhoneCallProtocol;
+phoneCallProtocol#fc878fc8 flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int library_versions:Vector<string> = PhoneCallProtocol;
 
 phone.phoneCall#ec82e140 phone_call:PhoneCall users:Vector<User> = phone.PhoneCall;
 
@@ -1021,7 +1015,7 @@ pageListOrderedItemBlocks#98dd8936 num:string blocks:Vector<PageBlock> = PageLis
 
 pageRelatedArticle#b390dc08 flags:# url:string webpage_id:long title:flags.0?string description:flags.1?string photo_id:flags.2?long author:flags.3?string published_date:flags.4?int = PageRelatedArticle;
 
-page#ae891bec flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
+page#98657f0d flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> views:flags.3?int = Page;
 
 help.supportName#8c05f1c9 name:string = help.SupportName;
 
@@ -1029,19 +1023,13 @@ help.userInfoEmpty#f3ae2eed = help.UserInfo;
 help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:string date:int = help.UserInfo;
 
 pollAnswer#6ca9c2e9 text:string option:bytes = PollAnswer;
-<<<<<<< HEAD
 
-poll#d5529d06 id:long flags:# closed:flags.0?true question:string answers:Vector<PollAnswer> = Poll;
+poll#86e18161 id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true question:string answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int = Poll;
 
-pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true option:bytes voters:int = PollAnswerVoters;
+pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true correct:flags.1?true option:bytes voters:int = PollAnswerVoters;
 
-pollResults#5755785a flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int = PollResults;
+pollResults#badcc1a3 flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<int> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> = PollResults;
 
-=======
-poll#d5529d06 id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true question:string answers:Vector<PollAnswer> = Poll;
-pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true correct:flags.1?true option:bytes voters:int = PollAnswerVoters;
-pollResults#c87024a2 flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<int> = PollResults;
->>>>>>> 87ebffa3... GramJS: Replace incorrect constructors
 chatOnlines#f041e250 onlines:int = ChatOnlines;
 
 statsURL#47a971e0 url:string = StatsURL;
@@ -1052,21 +1040,17 @@ chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags
 
 inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper;
 inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
+inputWallPaperNoFile#8427bbac = InputWallPaper;
 
 account.wallPapersNotModified#1c199183 = account.WallPapers;
 account.wallPapers#702b65a9 hash:int wallpapers:Vector<WallPaper> = account.WallPapers;
 
 codeSettings#debebe83 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true = CodeSettings;
-<<<<<<< HEAD
-
-wallPaperSettings#a12f40b8 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int intensity:flags.3?int = WallPaperSettings;
 
-autoDownloadSettings#d246fd47 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:int file_size_max:int = AutoDownloadSettings;
-
-=======
 wallPaperSettings#5086cf8 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;
+
 autoDownloadSettings#e04232f3 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:int file_size_max:int video_upload_maxbitrate:int = AutoDownloadSettings;
->>>>>>> 87ebffa3... GramJS: Replace incorrect constructors
+
 account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
 
 emojiKeyword#d5b3b9f9 keyword:string emoticons:Vector<string> = EmojiKeyword;
@@ -1096,47 +1080,71 @@ channelLocationEmpty#bfb5ad8b = ChannelLocation;
 channelLocation#209b82db geo_point:GeoPoint address:string = ChannelLocation;
 
 peerLocated#ca461b5d peer:Peer expires:int distance:int = PeerLocated;
+peerSelfLocated#f8ec284b expires:int = PeerLocated;
 
 restrictionReason#d072acb4 platform:string reason:string text:string = RestrictionReason;
 
 inputTheme#3c5693e9 id:long access_hash:long = InputTheme;
 inputThemeSlug#f5890df1 slug:string = InputTheme;
-<<<<<<< HEAD
 
-themeDocumentNotModified#483d270c = Theme;
-theme#f7d90ce0 flags:# creator:flags.0?true default:flags.1?true id:long access_hash:long slug:string title:string document:flags.2?Document installs_count:int = Theme;
-
-=======
 theme#28f1114 flags:# creator:flags.0?true default:flags.1?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?ThemeSettings installs_count:int = Theme;
->>>>>>> 87ebffa3... GramJS: Replace incorrect constructors
+
 account.themesNotModified#f41eb622 = account.Themes;
 account.themes#7f676421 hash:int themes:Vector<Theme> = account.Themes;
-<<<<<<< HEAD
-=======
+
 auth.loginToken#629f1980 expires:int token:bytes = auth.LoginToken;
 auth.loginTokenMigrateTo#68e9916 dc_id:int token:bytes = auth.LoginToken;
 auth.loginTokenSuccess#390d5c5e authorization:auth.Authorization = auth.LoginToken;
+
 account.contentSettings#57e28221 flags:# sensitive_enabled:flags.0?true sensitive_can_change:flags.1?true = account.ContentSettings;
+
 messages.inactiveChats#a927fec5 dates:Vector<int> chats:Vector<Chat> users:Vector<User> = messages.InactiveChats;
+
 baseThemeClassic#c3a12462 = BaseTheme;
 baseThemeDay#fbd81688 = BaseTheme;
 baseThemeNight#b7b31ea8 = BaseTheme;
 baseThemeTinted#6d5f77ee = BaseTheme;
 baseThemeArctic#5b11125a = BaseTheme;
+
 inputThemeSettings#bd507cd1 flags:# base_theme:BaseTheme accent_color:int message_top_color:flags.0?int message_bottom_color:flags.0?int wallpaper:flags.1?InputWallPaper wallpaper_settings:flags.1?WallPaperSettings = InputThemeSettings;
+
 themeSettings#9c14984a flags:# base_theme:BaseTheme accent_color:int message_top_color:flags.0?int message_bottom_color:flags.0?int wallpaper:flags.1?WallPaper = ThemeSettings;
+
 webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector<Document> settings:flags.1?ThemeSettings = WebPageAttribute;
+
 messageUserVote#a28e5559 user_id:int option:bytes date:int = MessageUserVote;
 messageUserVoteInputOption#36377430 user_id:int date:int = MessageUserVote;
 messageUserVoteMultiple#e8fe0de user_id:int options:Vector<bytes> date:int = MessageUserVote;
+
 messages.votesList#823f649 flags:# count:int votes:Vector<MessageUserVote> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
+
+bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
+
+payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;
+
+dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> exclude_peers:Vector<InputPeer> = DialogFilter;
+
+dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested;
+
+statsDateRangeDays#b637edaf min_date:int max_date:int = StatsDateRangeDays;
+
+statsAbsValueAndPrev#cb43acde current:double previous:double = StatsAbsValueAndPrev;
+
+statsPercentValue#cbce2fe0 part:double total:double = StatsPercentValue;
+
+statsGraphAsync#4a27eb2d token:string = StatsGraph;
+statsGraphError#bedc9822 error:string = StatsGraph;
+statsGraph#8ea464b6 flags:# json:DataJSON zoom_token:flags.0?string = StatsGraph;
+
+messageInteractionCounters#ad4fc9bd msg_id:int views:int forwards:int = MessageInteractionCounters;
+
+stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;
 
 ---functions---
 
 invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
 invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
-initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy query:!X = X;
+initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
 invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
 invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
 invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
@@ -1157,6 +1165,9 @@ auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
 auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
 auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
 auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
+auth.exportLoginToken#b1b41517 api_id:int api_hash:string except_ids:Vector<int> = auth.LoginToken;
+auth.importLoginToken#95ac5ce4 token:bytes = auth.LoginToken;
+auth.acceptLoginToken#e894ad4d token:bytes = Authorization;
 
 account.registerDevice#68976c6f flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<int> = Bool;
 account.unregisterDevice#3076c4bf token_type:int token:string other_uids:Vector<int> = Bool;
@@ -1214,12 +1225,15 @@ account.resetWallPapers#bb3b9804 = Bool;
 account.getAutoDownloadSettings#56da0b3f = account.AutoDownloadSettings;
 account.saveAutoDownloadSettings#76f36233 flags:# low:flags.0?true high:flags.1?true settings:AutoDownloadSettings = Bool;
 account.uploadTheme#1c3db333 flags:# file:InputFile thumb:flags.0?InputFile file_name:string mime_type:string = Document;
-account.createTheme#2b7ffd7f slug:string title:string document:InputDocument = Theme;
-account.updateTheme#3b8ea202 flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument = Theme;
+account.createTheme#8432c21f flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
+account.updateTheme#5cb367d5 flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
 account.saveTheme#f257106c theme:InputTheme unsave:Bool = Bool;
 account.installTheme#7ae43737 flags:# dark:flags.0?true format:flags.1?string theme:flags.1?InputTheme = Bool;
 account.getTheme#8d9d742b format:string theme:InputTheme document_id:long = Theme;
 account.getThemes#285946f8 format:string hash:int = account.Themes;
+account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
+account.getContentSettings#8b9b4dae = account.ContentSettings;
+account.getMultiWallPapers#65ad71dc wallpapers:Vector<InputWallPaper> = Vector<WallPaper>;
 
 users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
 users.getFullUser#ca30a5b1 id:InputUser = UserFull;
@@ -1243,7 +1257,7 @@ contacts.getSaved#82f1e39f = Vector<SavedContact>;
 contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
 contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates;
 contacts.acceptContact#f831a20f id:InputUser = Updates;
-contacts.getLocated#a356056 geo_point:InputGeoPoint = Updates;
+contacts.getLocated#d348bc44 flags:# background:flags.1?true geo_point:InputGeoPoint self_expires:flags.0?int = Updates;
 
 messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
 messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
@@ -1362,6 +1376,13 @@ messages.getScheduledHistory#e2c2685b peer:InputPeer hash:int = messages.Message
 messages.getScheduledMessages#bdbb0464 peer:InputPeer id:Vector<int> = messages.Messages;
 messages.sendScheduledMessages#bd38850a peer:InputPeer id:Vector<int> = Updates;
 messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector<int> = Updates;
+messages.getPollVotes#b86e380e flags:# peer:InputPeer id:int option:flags.0?bytes offset:flags.1?string limit:int = messages.VotesList;
+messages.toggleStickerSets#b5052fea flags:# uninstall:flags.0?true archive:flags.1?true unarchive:flags.2?true stickersets:Vector<InputStickerSet> = Bool;
+messages.getDialogFilters#f19ed96d = Vector<DialogFilter>;
+messages.getSuggestedDialogFilters#a29cd42c = Vector<DialogFilterSuggested>;
+messages.updateDialogFilter#1ad4a04a flags:# id:int filter:flags.0?DialogFilter = Bool;
+messages.updateDialogFiltersOrder#c563c1e4 order:Vector<int> = Bool;
+messages.getOldFeaturedStickers#5fe7025b offset:int limit:int hash:int = messages.FeaturedStickers;
 
 updates.getState#edd4882a = updates.State;
 updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@@ -1383,7 +1404,6 @@ upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<Fil
 
 help.getConfig#c4f9186b = Config;
 help.getNearestDc#1fb33026 = NearestDc;
-<<<<<<< HEAD
 help.getAppUpdate#522d5a7d source:string = help.AppUpdate;
 help.getInviteText#4d392343 = help.InviteText;
 help.getSupport#9cdf08cd = help.Support;
@@ -1402,9 +1422,6 @@ help.getSupportName#d360e72c = help.SupportName;
 help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
 help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
 
-=======
-help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
->>>>>>> 073c3e12... GramJS: Implement signup
 channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
 channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
 channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory;
@@ -1414,7 +1431,6 @@ channels.getParticipants#123e05e9 channel:InputChannel filter:ChannelParticipant
 channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant;
 channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
 channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
-<<<<<<< HEAD
 channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates;
 channels.editAdmin#d33c8902 channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights rank:string = Updates;
 channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
@@ -1440,9 +1456,11 @@ channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel =
 channels.editCreator#8f38cd1f channel:InputChannel user_id:InputUser password:InputCheckPasswordSRP = Updates;
 channels.editLocation#58e63f6d channel:InputChannel geo_point:InputGeoPoint address:string = Bool;
 channels.toggleSlowMode#edd49ef0 channel:InputChannel seconds:int = Updates;
+channels.getInactiveChannels#11e831ee = messages.InactiveChats;
 
 bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
 bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
+bots.setBotCommands#805d46f6 commands:Vector<BotCommand> = Bool;
 
 payments.getPaymentForm#99f09745 msg_id:int = payments.PaymentForm;
 payments.getPaymentReceipt#a092a980 msg_id:int = payments.PaymentReceipt;
@@ -1450,11 +1468,13 @@ payments.validateRequestedInfo#770a8e74 flags:# save:flags.0?true msg_id:int inf
 payments.sendPaymentForm#2b8879b3 flags:# msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials = payments.PaymentResult;
 payments.getSavedInfo#227d824b = payments.SavedInfo;
 payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
+payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
 
-stickers.createStickerSet#9bd86e6a flags:# masks:flags.0?true user_id:InputUser title:string short_name:string stickers:Vector<InputStickerSetItem> = messages.StickerSet;
+stickers.createStickerSet#f1036780 flags:# masks:flags.0?true animated:flags.1?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> = messages.StickerSet;
 stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
 stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet;
 stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
+stickers.setStickerSetThumb#9a364e30 stickerset:InputStickerSet thumb:InputDocument = messages.StickerSet;
 
 phone.getCallConfig#55451fa9 = DataJSON;
 phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
@@ -1474,7 +1494,7 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
 folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
 folders.deleteFolder#1c295881 folder_id:int = Updates;
 
-// LAYER 105
-=======
-// LAYER 109
->>>>>>> ca1f18ad... GramJS: Update MTProto layer to 109
+stats.getBroadcastStats#e6300dba flags:# dark:flags.0?true channel:InputChannel tz_offset:int = stats.BroadcastStats;
+stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;
+
+// LAYER 112

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov