|
@@ -1,10 +1,10 @@
|
|
|
-const fs = require('fs');
|
|
|
-const util = require('util');
|
|
|
-const { crc32 } = require('crc');
|
|
|
-const SourceBuilder = require('../sourcebuilder');
|
|
|
-const { snakeToCamelCase, variableSnakeToCamelCase } = require('../utils');
|
|
|
+const fs = require('fs')
|
|
|
+const util = require('util')
|
|
|
+const { crc32 } = require('crc')
|
|
|
+const SourceBuilder = require('../sourcebuilder')
|
|
|
+const { snakeToCamelCase, variableSnakeToCamelCase } = require('../utils')
|
|
|
|
|
|
-const AUTO_GEN_NOTICE = '/*! File generated by TLObjects\' generator. All changes will be ERASED !*/';
|
|
|
+const AUTO_GEN_NOTICE = '/*! File generated by TLObjects\' generator. All changes will be ERASED !*/'
|
|
|
|
|
|
const AUTO_CASTS = {
|
|
|
InputPeer: 'utils.get_input_peer(await client.get_input_entity(%s))',
|
|
@@ -17,11 +17,11 @@ const AUTO_CASTS = {
|
|
|
InputMessage: 'utils.get_input_message(%s)',
|
|
|
InputDocument: 'utils.get_input_document(%s)',
|
|
|
InputChatPhoto: 'utils.get_input_chat_photo(%s)',
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const NAMED_AUTO_CASTS = {
|
|
|
'chat_id,int': 'await client.get_peer_id(%s, add_mark=False)',
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// Secret chats have a chat_id which may be negative.
|
|
|
// With the named auto-cast above, we would break it.
|
|
@@ -31,9 +31,9 @@ const NAMED_AUTO_CASTS = {
|
|
|
// NOTE: This works because the auto-cast is not recursive.
|
|
|
// There are plenty of types that would break if we
|
|
|
// did recurse into them to resolve them.
|
|
|
-const NAMED_BLACKLIST = new Set(['messages.discardEncryption']);
|
|
|
+const NAMED_BLACKLIST = new Set(['messages.discardEncryption'])
|
|
|
|
|
|
-const BASE_TYPES = ['string', 'bytes', 'int', 'long', 'int128', 'int256', 'double', 'Bool', 'true'];
|
|
|
+// const BASE_TYPES = ['string', 'bytes', 'int', 'long', 'int128', 'int256', 'double', 'Bool', 'true'];
|
|
|
|
|
|
// Patched types {fullname: custom.ns.Name}
|
|
|
|
|
@@ -44,23 +44,23 @@ const BASE_TYPES = ['string', 'bytes', 'int', 'long', 'int128', 'int256', 'doubl
|
|
|
message: 'message.Message',
|
|
|
messageService: 'message.Message',
|
|
|
};*/
|
|
|
-const PATCHED_TYPES = {};
|
|
|
+const PATCHED_TYPES = {}
|
|
|
|
|
|
const writeModules = (outDir, depth, kind, namespaceTlobjects, typeConstructors) => {
|
|
|
// namespace_tlobjects: {'namespace', [TLObject]}
|
|
|
- fs.mkdirSync(outDir, { recursive: true });
|
|
|
+ fs.mkdirSync(outDir, { recursive: true })
|
|
|
|
|
|
for (const [ns, tlobjects] of Object.entries(namespaceTlobjects)) {
|
|
|
- const file = `${outDir}/${ns === 'null' ? 'index' : ns}.js`;
|
|
|
- const stream = fs.createWriteStream(file);
|
|
|
- const builder = new SourceBuilder(stream);
|
|
|
- const dotDepth = '.'.repeat(depth || 1);
|
|
|
+ const file = `${outDir}/${ns === 'null' ? 'index' : ns}.js`
|
|
|
+ const stream = fs.createWriteStream(file)
|
|
|
+ const builder = new SourceBuilder(stream)
|
|
|
+ const dotDepth = '.'.repeat(depth || 1)
|
|
|
|
|
|
- builder.writeln(AUTO_GEN_NOTICE);
|
|
|
- builder.writeln(`const { TLObject } = require('${dotDepth}/tlobject');`);
|
|
|
+ builder.writeln(AUTO_GEN_NOTICE)
|
|
|
+ builder.writeln(`const { TLObject } = require('${dotDepth}/tlobject');`)
|
|
|
|
|
|
if (kind !== 'TLObject') {
|
|
|
- builder.writeln(`const { ${kind} } = require('${dotDepth}/tlobject');`);
|
|
|
+ builder.writeln(`const { ${kind} } = require('${dotDepth}/tlobject');`)
|
|
|
}
|
|
|
|
|
|
// Add the relative imports to the namespaces,
|
|
@@ -68,17 +68,17 @@ const writeModules = (outDir, depth, kind, namespaceTlobjects, typeConstructors)
|
|
|
if (!ns) {
|
|
|
const imports = Object.keys(namespaceTlobjects)
|
|
|
.filter(Boolean)
|
|
|
- .join(`, `);
|
|
|
+ .join(`, `)
|
|
|
|
|
|
- builder.writeln(`const { ${imports} } = require('.');`);
|
|
|
+ builder.writeln(`const { ${imports} } = require('.');`)
|
|
|
}
|
|
|
|
|
|
// Import struct for the .__bytes__(self) serialization
|
|
|
- builder.writeln('const struct = require(\'python-struct\');');
|
|
|
- builder.writeln(`const Helpers = require('../../utils/Helpers');`);
|
|
|
+ builder.writeln('const struct = require(\'python-struct\');')
|
|
|
+ builder.writeln(`const Helpers = require('../../utils/Helpers');`)
|
|
|
|
|
|
- const typeNames = new Set();
|
|
|
- const typeDefs = [];
|
|
|
+ const typeNames = new Set()
|
|
|
+ const typeDefs = []
|
|
|
/*
|
|
|
// Find all the types in this file and generate type definitions
|
|
|
// based on the types. The type definitions are written to the
|
|
@@ -114,38 +114,38 @@ const writeModules = (outDir, depth, kind, namespaceTlobjects, typeConstructors)
|
|
|
}
|
|
|
}*/
|
|
|
|
|
|
- const imports = {};
|
|
|
- const primitives = new Set(['int', 'long', 'int128', 'int256', 'double', 'string', 'bytes', 'Bool', 'true']);
|
|
|
+ const imports = {}
|
|
|
+ const primitives = new Set(['int', 'long', 'int128', 'int256', 'double', 'string', 'bytes', 'Bool', 'true'])
|
|
|
|
|
|
// Find all the types in other files that are used in this file
|
|
|
// and generate the information required to import those types.
|
|
|
for (const t of tlobjects) {
|
|
|
for (const arg of t.args) {
|
|
|
- let name = arg.type;
|
|
|
+ let name = arg.type
|
|
|
|
|
|
if (!name || primitives.has(name)) {
|
|
|
- continue;
|
|
|
+ continue
|
|
|
}
|
|
|
|
|
|
- let importSpace = `${dotDepth}/tl/types`;
|
|
|
+ let importSpace = `${dotDepth}/tl/types`
|
|
|
|
|
|
if (name.includes('.')) {
|
|
|
- const [namespace] = name.split('.');
|
|
|
- name = name.split('.');
|
|
|
- importSpace += `/${namespace}`;
|
|
|
+ const [namespace] = name.split('.')
|
|
|
+ name = name.split('.')
|
|
|
+ importSpace += `/${namespace}`
|
|
|
}
|
|
|
|
|
|
if (!typeNames.has(name)) {
|
|
|
- typeNames.add(name);
|
|
|
+ typeNames.add(name)
|
|
|
|
|
|
if (name === 'date') {
|
|
|
- imports.datetime = ['datetime'];
|
|
|
- continue;
|
|
|
+ imports.datetime = ['datetime']
|
|
|
+ continue
|
|
|
} else if (!(importSpace in imports)) {
|
|
|
- imports[importSpace] = new Set();
|
|
|
+ imports[importSpace] = new Set()
|
|
|
}
|
|
|
|
|
|
- imports[importSpace].add(`Type${name}`);
|
|
|
+ imports[importSpace].add(`Type${name}`)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -169,34 +169,34 @@ const writeModules = (outDir, depth, kind, namespaceTlobjects, typeConstructors)
|
|
|
// Generate the class for every TLObject
|
|
|
for (const t of tlobjects) {
|
|
|
if (t.fullname in PATCHED_TYPES) {
|
|
|
- builder.writeln(`const ${t.className} = null; // Patched`);
|
|
|
+ builder.writeln(`const ${t.className} = null; // Patched`)
|
|
|
} else {
|
|
|
- writeSourceCode(t, kind, builder, typeConstructors);
|
|
|
- builder.currentIndent = 0;
|
|
|
+ writeSourceCode(t, kind, builder, typeConstructors)
|
|
|
+ builder.currentIndent = 0
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Write the type definitions generated earlier.
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln()
|
|
|
|
|
|
for (const line of typeDefs) {
|
|
|
- builder.writeln(line);
|
|
|
+ builder.writeln(line)
|
|
|
}
|
|
|
- writeModuleExports(tlobjects, builder);
|
|
|
+ writeModuleExports(tlobjects, builder)
|
|
|
if (file.indexOf('index.js') > 0) {
|
|
|
for (const [ns] of Object.entries(namespaceTlobjects)) {
|
|
|
if (ns !== 'null') {
|
|
|
- builder.writeln('let %s = require(\'./%s\');', ns, ns);
|
|
|
+ builder.writeln('let %s = require(\'./%s\');', ns, ns)
|
|
|
}
|
|
|
}
|
|
|
for (const [ns] of Object.entries(namespaceTlobjects)) {
|
|
|
if (ns !== 'null') {
|
|
|
- builder.writeln('module.exports.%s = %s;', ns, ns);
|
|
|
+ builder.writeln('module.exports.%s = %s;', ns, ns)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const writeReadResult = (tlobject, builder) => {
|
|
|
// Only requests can have a different response that's not their
|
|
@@ -205,7 +205,7 @@ const writeReadResult = (tlobject, builder) => {
|
|
|
// The default behaviour is reading a TLObject too, so no need
|
|
|
// to override it unless necessary.
|
|
|
if (!tlobject.isFunction) {
|
|
|
- return;
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
// https://core.telegram.org/mtproto/serialize#boxed-and-bare-types
|
|
@@ -215,23 +215,23 @@ const writeReadResult = (tlobject, builder) => {
|
|
|
// Currently only un-boxed responses are Vector<int>/Vector<long>.
|
|
|
// If this weren't the case, we should check upper case after
|
|
|
// max(index('<'), index('.')) (and if it is, it's boxed, so return).
|
|
|
- const m = tlobject.result.match(/Vector<(int|long)>/);
|
|
|
+ const m = tlobject.result.match(/Vector<(int|long)>/)
|
|
|
if (!m) {
|
|
|
- return;
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
// builder.endBlock();
|
|
|
- builder.writeln('readResult(reader){');
|
|
|
- builder.writeln('reader.readInt(); // Vector ID');
|
|
|
- builder.writeln('let temp = [];');
|
|
|
- builder.writeln('let len = reader.readInt(); //fix this');
|
|
|
- builder.writeln('for (let i=0;i<len;i++){');
|
|
|
- const read = m[1][0].toUpperCase() + m[1].slice(1);
|
|
|
- builder.writeln('temp.push(reader.read%s())', read);
|
|
|
- builder.endBlock();
|
|
|
- builder.writeln('return temp');
|
|
|
- builder.endBlock();
|
|
|
-};
|
|
|
+ builder.writeln('readResult(reader){')
|
|
|
+ builder.writeln('reader.readInt(); // Vector ID')
|
|
|
+ builder.writeln('let temp = [];')
|
|
|
+ builder.writeln('let len = reader.readInt(); //fix this')
|
|
|
+ builder.writeln('for (let i=0;i<len;i++){')
|
|
|
+ const read = m[1][0].toUpperCase() + m[1].slice(1)
|
|
|
+ builder.writeln('temp.push(reader.read%s())', read)
|
|
|
+ builder.endBlock()
|
|
|
+ builder.writeln('return temp')
|
|
|
+ builder.endBlock()
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* Writes the source code corresponding to the given TLObject
|
|
@@ -242,69 +242,69 @@ const writeReadResult = (tlobject, builder) => {
|
|
|
* importing and documentation strings.
|
|
|
*/
|
|
|
const writeSourceCode = (tlobject, kind, builder, typeConstructors) => {
|
|
|
- writeClassConstructor(tlobject, kind, typeConstructors, builder);
|
|
|
- writeResolve(tlobject, builder);
|
|
|
+ writeClassConstructor(tlobject, kind, typeConstructors, builder)
|
|
|
+ writeResolve(tlobject, builder)
|
|
|
// writeToJson(tlobject, builder);
|
|
|
- writeToBytes(tlobject, builder);
|
|
|
- builder.currentIndent--;
|
|
|
- writeFromReader(tlobject, builder);
|
|
|
- writeReadResult(tlobject, builder);
|
|
|
- builder.currentIndent--;
|
|
|
- builder.writeln('}');
|
|
|
-};
|
|
|
+ writeToBytes(tlobject, builder)
|
|
|
+ builder.currentIndent--
|
|
|
+ writeFromReader(tlobject, builder)
|
|
|
+ writeReadResult(tlobject, builder)
|
|
|
+ builder.currentIndent--
|
|
|
+ builder.writeln('}')
|
|
|
+}
|
|
|
|
|
|
const writeClassConstructor = (tlobject, kind, typeConstructors, builder) => {
|
|
|
- builder.writeln();
|
|
|
- builder.writeln();
|
|
|
- builder.writeln(`class ${tlobject.className} extends ${kind} {`);
|
|
|
+ builder.writeln()
|
|
|
+ builder.writeln()
|
|
|
+ builder.writeln(`class ${tlobject.className} extends ${kind} {`)
|
|
|
|
|
|
// Write the __init__ function if it has any argument
|
|
|
if (!tlobject.realArgs.length) {
|
|
|
- return;
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
// Note : this is needed to be able to access them
|
|
|
// with or without an instance
|
|
|
- builder.writeln(`static CONSTRUCTOR_ID = 0x${tlobject.id.toString(16).padStart(8, '0')};`);
|
|
|
- builder.writeln(`static SUBCLASS_OF_ID = 0x${crc32(tlobject.result).toString(16)};`);
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln(`static CONSTRUCTOR_ID = 0x${tlobject.id.toString(16).padStart(8, '0')};`)
|
|
|
+ builder.writeln(`static SUBCLASS_OF_ID = 0x${crc32(tlobject.result).toString(16)};`)
|
|
|
+ builder.writeln()
|
|
|
|
|
|
- builder.writeln('/**');
|
|
|
+ builder.writeln('/**')
|
|
|
|
|
|
if (tlobject.isFunction) {
|
|
|
- builder.write(`:returns ${tlobject.result}: `);
|
|
|
+ builder.write(`:returns ${tlobject.result}: `)
|
|
|
} else {
|
|
|
- builder.write(`Constructor for ${tlobject.result}: `);
|
|
|
+ builder.write(`Constructor for ${tlobject.result}: `)
|
|
|
}
|
|
|
|
|
|
- const constructors = typeConstructors[tlobject.result];
|
|
|
+ const constructors = typeConstructors[tlobject.result]
|
|
|
|
|
|
if (!constructors) {
|
|
|
- builder.writeln('This type has no constructors.');
|
|
|
+ builder.writeln('This type has no constructors.')
|
|
|
} else if (constructors.length === 1) {
|
|
|
- builder.writeln(`Instance of ${constructors[0].className}`);
|
|
|
+ builder.writeln(`Instance of ${constructors[0].className}`)
|
|
|
} else {
|
|
|
- builder.writeln(`Instance of either ${constructors.map((c) => c.className).join(', ')}`);
|
|
|
+ builder.writeln(`Instance of either ${constructors.map((c) => c.className).join(', ')}`)
|
|
|
}
|
|
|
|
|
|
- builder.writeln('*/');
|
|
|
- builder.writeln(`constructor(args) {`);
|
|
|
- builder.writeln(`super();`);
|
|
|
+ builder.writeln('*/')
|
|
|
+ builder.writeln(`constructor(args) {`)
|
|
|
+ builder.writeln(`super();`)
|
|
|
|
|
|
// Class-level variable to store its Telegram's constructor ID
|
|
|
- builder.writeln(`this.CONSTRUCTOR_ID = 0x${tlobject.id.toString(16).padStart(8, '0')};`);
|
|
|
- builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(tlobject.result).toString(16)};`);
|
|
|
+ builder.writeln(`this.CONSTRUCTOR_ID = 0x${tlobject.id.toString(16).padStart(8, '0')};`)
|
|
|
+ builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(tlobject.result).toString(16)};`)
|
|
|
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln()
|
|
|
|
|
|
// Set the arguments
|
|
|
for (const arg of tlobject.realArgs) {
|
|
|
if (!arg.canBeInferred) {
|
|
|
builder.writeln(
|
|
|
- `this.${variableSnakeToCamelCase(arg.name)}: ${a.typeHint()} = args.${variableSnakeToCamelCase(
|
|
|
- arg.name
|
|
|
- )}${a.isFlag || a.canBeInferred ? ' || null' : ''};`
|
|
|
- );
|
|
|
+ `this.${variableSnakeToCamelCase(arg.name)} = args.${variableSnakeToCamelCase(
|
|
|
+ arg.name,
|
|
|
+ )}${arg.isFlag || arg.canBeInferred ? ' || null' : ''};`,
|
|
|
+ )
|
|
|
|
|
|
// Currently the only argument that can be
|
|
|
// inferred are those called 'random_id'
|
|
@@ -312,26 +312,26 @@ const writeClassConstructor = (tlobject, kind, typeConstructors, builder) => {
|
|
|
// Endianness doesn't really matter, and 'big' is shorter
|
|
|
let code = `Helpers.readBigIntFromBuffer(Helpers.generateRandomBytes(${
|
|
|
arg.type === 'long' ? 8 : 4
|
|
|
- }),false,true)`;
|
|
|
+ }),false,true)`
|
|
|
|
|
|
if (arg.isVector) {
|
|
|
// Currently for the case of "messages.forwardMessages"
|
|
|
// Ensure we can infer the length from id:Vector<>
|
|
|
if (!tlobject.realArgs.find((a) => a.name === 'id').isVector) {
|
|
|
- throw new Error(`Cannot infer list of random ids for ${tlobject}`);
|
|
|
+ throw new Error(`Cannot infer list of random ids for ${tlobject}`)
|
|
|
}
|
|
|
|
|
|
- code = `new Array(id.length).fill().map(_ => ${code})`;
|
|
|
+ code = `new Array(id.length).fill().map(_ => ${code})`
|
|
|
}
|
|
|
|
|
|
- builder.writeln(`this.randomId = args.randomId !== undefined ? args.randomId : ${code};`);
|
|
|
+ builder.writeln(`this.randomId = args.randomId !== undefined ? args.randomId : ${code};`)
|
|
|
} else {
|
|
|
- throw new Error(`Cannot infer a value for ${arg}`);
|
|
|
+ throw new Error(`Cannot infer a value for ${arg}`)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- builder.endBlock();
|
|
|
-};
|
|
|
+ builder.endBlock()
|
|
|
+}
|
|
|
|
|
|
const writeResolve = (tlobject, builder) => {
|
|
|
if (
|
|
@@ -339,45 +339,45 @@ const writeResolve = (tlobject, builder) => {
|
|
|
tlobject.realArgs.some(
|
|
|
(arg) =>
|
|
|
arg.type in AUTO_CASTS ||
|
|
|
- (`${arg.name},${arg.type}` in NAMED_AUTO_CASTS && !NAMED_BLACKLIST.has(tlobject.fullname))
|
|
|
+ (`${arg.name},${arg.type}` in NAMED_AUTO_CASTS && !NAMED_BLACKLIST.has(tlobject.fullname)),
|
|
|
)
|
|
|
) {
|
|
|
- builder.writeln('async resolve(client, utils) {');
|
|
|
+ builder.writeln('async resolve(client, utils) {')
|
|
|
|
|
|
for (const arg of tlobject.realArgs) {
|
|
|
- let ac = AUTO_CASTS[arg.type];
|
|
|
+ let ac = AUTO_CASTS[arg.type]
|
|
|
|
|
|
if (!ac) {
|
|
|
- ac = NAMED_AUTO_CASTS[`${arg.name},${arg.type}`];
|
|
|
+ ac = NAMED_AUTO_CASTS[`${arg.name},${arg.type}`]
|
|
|
|
|
|
if (!ac) {
|
|
|
- continue;
|
|
|
+ continue
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (arg.isFlag) {
|
|
|
- builder.writeln(`if (this.${arg.name}) {`);
|
|
|
+ builder.writeln(`if (this.${arg.name}) {`)
|
|
|
}
|
|
|
|
|
|
if (arg.isVector) {
|
|
|
- builder.write(`const _tmp = [];`);
|
|
|
- builder.writeln(`for (const _x of this.${arg.name}) {`);
|
|
|
- builder.writeln(`_tmp.push(%s);`, util.format(ac, '_x'));
|
|
|
- builder.endBlock();
|
|
|
- builder.writeln(`this.${arg.name} = _tmp;`);
|
|
|
+ builder.write(`const _tmp = [];`)
|
|
|
+ builder.writeln(`for (const _x of this.${arg.name}) {`)
|
|
|
+ builder.writeln(`_tmp.push(%s);`, util.format(ac, '_x'))
|
|
|
+ builder.endBlock()
|
|
|
+ builder.writeln(`this.${arg.name} = _tmp;`)
|
|
|
} else {
|
|
|
- builder.writeln(`this.${arg.name} = %s`, util.format(ac, `this.${arg.name}`));
|
|
|
+ builder.writeln(`this.${arg.name} = %s`, util.format(ac, `this.${arg.name}`))
|
|
|
}
|
|
|
|
|
|
if (arg.isFlag) {
|
|
|
- builder.currentIndent--;
|
|
|
- builder.writeln('}');
|
|
|
+ builder.currentIndent--
|
|
|
+ builder.writeln('}')
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- builder.endBlock();
|
|
|
+ builder.endBlock()
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
/**
|
|
|
const writeToJson = (tlobject, builder) => {
|
|
|
builder.writeln('toJson() {');
|
|
@@ -424,79 +424,79 @@ const writeResolve = (tlobject, builder) => {
|
|
|
};
|
|
|
*/
|
|
|
const writeToBytes = (tlobject, builder) => {
|
|
|
- builder.writeln('get bytes() {');
|
|
|
+ builder.writeln('get bytes() {')
|
|
|
|
|
|
// Some objects require more than one flag parameter to be set
|
|
|
// at the same time. In this case, add an assertion.
|
|
|
- const repeatedArgs = {};
|
|
|
+ const repeatedArgs = {}
|
|
|
for (const arg of tlobject.args) {
|
|
|
if (arg.isFlag) {
|
|
|
if (!repeatedArgs[arg.flagIndex]) {
|
|
|
- repeatedArgs[arg.flagIndex] = [];
|
|
|
+ repeatedArgs[arg.flagIndex] = []
|
|
|
}
|
|
|
- repeatedArgs[arg.flagIndex].push(arg);
|
|
|
+ repeatedArgs[arg.flagIndex].push(arg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
for (const ra of Object.values(repeatedArgs)) {
|
|
|
if (ra.length > 1) {
|
|
|
- const cnd1 = [];
|
|
|
- const cnd2 = [];
|
|
|
- const names = [];
|
|
|
+ const cnd1 = []
|
|
|
+ const cnd2 = []
|
|
|
+ const names = []
|
|
|
|
|
|
for (const a of ra) {
|
|
|
- cnd1.push(`this.${a.name} || this.${a.name}!==null`);
|
|
|
- cnd2.push(`this.${a.name}===null || this.${a.name}===false`);
|
|
|
- names.push(a.name);
|
|
|
+ cnd1.push(`this.${a.name} || this.${a.name}!==null`)
|
|
|
+ cnd2.push(`this.${a.name}===null || this.${a.name}===false`)
|
|
|
+ names.push(a.name)
|
|
|
}
|
|
|
builder.writeln(
|
|
|
'if (!((%s) && (%s)))\n\t throw new Error(\'%s paramaters must all be false-y or all true\')',
|
|
|
cnd1.join(' && '),
|
|
|
cnd2.join(' && '),
|
|
|
- names.join(', ')
|
|
|
- );
|
|
|
+ names.join(', '),
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
- builder.writeln('return Buffer.concat([');
|
|
|
- builder.currentIndent++;
|
|
|
- const b = Buffer.alloc(4);
|
|
|
- b.writeUInt32LE(tlobject.id, 0);
|
|
|
+ builder.writeln('return Buffer.concat([')
|
|
|
+ builder.currentIndent++
|
|
|
+ const b = Buffer.alloc(4)
|
|
|
+ b.writeUInt32LE(tlobject.id, 0)
|
|
|
// First constructor code, we already know its bytes
|
|
|
- builder.writeln('Buffer.from("%s","hex"),', b.toString('hex'));
|
|
|
+ builder.writeln('Buffer.from("%s","hex"),', b.toString('hex'))
|
|
|
for (const arg of tlobject.args) {
|
|
|
if (writeArgToBytes(builder, arg, tlobject.args)) {
|
|
|
- builder.writeln(',');
|
|
|
+ builder.writeln(',')
|
|
|
}
|
|
|
}
|
|
|
- builder.writeln('])');
|
|
|
- builder.endBlock();
|
|
|
-};
|
|
|
+ builder.writeln('])')
|
|
|
+ builder.endBlock()
|
|
|
+}
|
|
|
|
|
|
// writeFromReader
|
|
|
const writeFromReader = (tlobject, builder) => {
|
|
|
- builder.writeln('static fromReader(reader) {');
|
|
|
+ builder.writeln('static fromReader(reader) {')
|
|
|
for (const arg of tlobject.args) {
|
|
|
if (arg.name !== 'flag') {
|
|
|
if (arg.name !== 'x') {
|
|
|
- builder.writeln('let %s', '_' + arg.name + ';');
|
|
|
+ builder.writeln('let %s', '_' + arg.name + ';')
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// TODO fix this really
|
|
|
- builder.writeln('let _x;');
|
|
|
- builder.writeln('let len;');
|
|
|
+ builder.writeln('let _x;')
|
|
|
+ builder.writeln('let len;')
|
|
|
|
|
|
for (const arg of tlobject.args) {
|
|
|
- writeArgReadCode(builder, arg, tlobject.args, '_' + arg.name);
|
|
|
+ writeArgReadCode(builder, arg, tlobject.args, '_' + arg.name)
|
|
|
}
|
|
|
- const temp = [];
|
|
|
+ const temp = []
|
|
|
for (const a of tlobject.realArgs) {
|
|
|
- temp.push(`${variableSnakeToCamelCase(a.name)}:_${a.name}`);
|
|
|
+ temp.push(`${variableSnakeToCamelCase(a.name)}:_${a.name}`)
|
|
|
}
|
|
|
- builder.writeln('return new this({%s})', temp.join(',\n\t'));
|
|
|
- builder.endBlock();
|
|
|
-};
|
|
|
+ builder.writeln('return new this({%s})', temp.join(',\n\t'))
|
|
|
+ builder.endBlock()
|
|
|
+}
|
|
|
// writeReadResult
|
|
|
|
|
|
/**
|
|
@@ -511,21 +511,21 @@ const writeFromReader = (tlobject, builder) => {
|
|
|
*/
|
|
|
const writeArgToBytes = (builder, arg, args, name = null) => {
|
|
|
if (arg.genericDefinition) {
|
|
|
- return; // Do nothing, this only specifies a later type
|
|
|
+ return // Do nothing, this only specifies a later type
|
|
|
}
|
|
|
|
|
|
if (name === null) {
|
|
|
- name = `this.${arg.name}`;
|
|
|
+ name = `this.${arg.name}`
|
|
|
}
|
|
|
|
|
|
- name = variableSnakeToCamelCase(name);
|
|
|
+ name = variableSnakeToCamelCase(name)
|
|
|
// The argument may be a flag, only write if it's not None AND
|
|
|
// if it's not a True type.
|
|
|
// True types are not actually sent, but instead only used to
|
|
|
// determine the flags.
|
|
|
if (arg.isFlag) {
|
|
|
if (arg.type === 'true') {
|
|
|
- return; // Exit, since true type is never written
|
|
|
+ return // Exit, since true type is never written
|
|
|
} else if (arg.isVector) {
|
|
|
// Vector flags are special since they consist of 3 values,
|
|
|
// so we need an extra join here. Note that empty vector flags
|
|
@@ -534,99 +534,99 @@ const writeArgToBytes = (builder, arg, args, name = null) => {
|
|
|
'(%s === undefined || %s === false || %s ===null) ? Buffer.alloc(0) :Buffer.concat([',
|
|
|
name,
|
|
|
name,
|
|
|
- name
|
|
|
- );
|
|
|
+ name,
|
|
|
+ )
|
|
|
} else {
|
|
|
- builder.write('(%s === undefined || %s === false || %s ===null) ? Buffer.alloc(0) : [', name, name, name);
|
|
|
+ builder.write('(%s === undefined || %s === false || %s ===null) ? Buffer.alloc(0) : [', name, name, name)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (arg.isVector) {
|
|
|
if (arg.useVectorId) {
|
|
|
- builder.write('Buffer.from(\'15c4b51c\', \'hex\'),');
|
|
|
+ builder.write('Buffer.from(\'15c4b51c\', \'hex\'),')
|
|
|
}
|
|
|
|
|
|
- builder.write('struct.pack(\'<i\', %s.length),', name);
|
|
|
+ builder.write('struct.pack(\'<i\', %s.length),', name)
|
|
|
|
|
|
// Cannot unpack the values for the outer tuple through *[(
|
|
|
// since that's a Python >3.5 feature, so add another join.
|
|
|
- builder.write('Buffer.concat(%s.map(x => ', name);
|
|
|
+ builder.write('Buffer.concat(%s.map(x => ', name)
|
|
|
// Temporary disable .is_vector, not to enter this if again
|
|
|
// Also disable .is_flag since it's not needed per element
|
|
|
- const oldFlag = arg.isFlag;
|
|
|
- arg.isVector = arg.isFlag = false;
|
|
|
- writeArgToBytes(builder, arg, args, 'x');
|
|
|
- arg.isVector = true;
|
|
|
- arg.isFlag = oldFlag;
|
|
|
+ const oldFlag = arg.isFlag
|
|
|
+ arg.isVector = arg.isFlag = false
|
|
|
+ writeArgToBytes(builder, arg, args, 'x')
|
|
|
+ arg.isVector = true
|
|
|
+ arg.isFlag = oldFlag
|
|
|
|
|
|
- builder.write('))');
|
|
|
+ builder.write('))')
|
|
|
} else if (arg.flagIndicator) {
|
|
|
// Calculate the flags with those items which are not None
|
|
|
if (!args.some((f) => f.isFlag)) {
|
|
|
// There's a flag indicator, but no flag arguments so it's 0
|
|
|
- builder.write('Buffer.alloc(4)');
|
|
|
+ builder.write('Buffer.alloc(4)')
|
|
|
} else {
|
|
|
- builder.write('struct.pack(\'<I\', ');
|
|
|
+ builder.write('struct.pack(\'<I\', ')
|
|
|
builder.write(
|
|
|
args
|
|
|
.filter((flag) => flag.isFlag)
|
|
|
.map(
|
|
|
(flag) =>
|
|
|
`(this.${variableSnakeToCamelCase(
|
|
|
- flag.name
|
|
|
+ flag.name,
|
|
|
)} === undefined || this.${variableSnakeToCamelCase(
|
|
|
- flag.name
|
|
|
+ flag.name,
|
|
|
)} === false || this.${variableSnakeToCamelCase(flag.name)} === null) ? 0 : ${1 <<
|
|
|
- flag.flagIndex}`
|
|
|
+ flag.flagIndex}`,
|
|
|
)
|
|
|
- .join(' | ')
|
|
|
- );
|
|
|
- builder.write(')');
|
|
|
+ .join(' | '),
|
|
|
+ )
|
|
|
+ builder.write(')')
|
|
|
}
|
|
|
} else if (arg.type === 'int') {
|
|
|
- builder.write('struct.pack(\'<i\', %s)', name);
|
|
|
+ builder.write('struct.pack(\'<i\', %s)', name)
|
|
|
} else if (arg.type === 'long') {
|
|
|
- builder.write('Helpers.readBufferFromBigInt(%s,8,true,true)', name);
|
|
|
+ builder.write('Helpers.readBufferFromBigInt(%s,8,true,true)', name)
|
|
|
} else if (arg.type === 'int128') {
|
|
|
- builder.write('Helpers.readBufferFromBigInt(%s,16,true,true)', name);
|
|
|
+ builder.write('Helpers.readBufferFromBigInt(%s,16,true,true)', name)
|
|
|
} else if (arg.type === 'int256') {
|
|
|
- builder.write('Helpers.readBufferFromBigInt(%s,32,true,true)', name);
|
|
|
+ builder.write('Helpers.readBufferFromBigInt(%s,32,true,true)', name)
|
|
|
} else if (arg.type === 'double') {
|
|
|
- builder.write('struct.pack(\'<d\', %s.toString())', name);
|
|
|
+ builder.write('struct.pack(\'<d\', %s.toString())', name)
|
|
|
} else if (arg.type === 'string') {
|
|
|
- builder.write('TLObject.serializeBytes(%s)', name);
|
|
|
+ builder.write('TLObject.serializeBytes(%s)', name)
|
|
|
} else if (arg.type === 'Bool') {
|
|
|
- builder.write('%s ? 0xb5757299 : 0x379779bc', name);
|
|
|
+ builder.write('%s ? 0xb5757299 : 0x379779bc', name)
|
|
|
} else if (arg.type === 'true') {
|
|
|
// These are actually NOT written! Only used for flags
|
|
|
} else if (arg.type === 'bytes') {
|
|
|
- builder.write('TLObject.serializeBytes(%s)', name);
|
|
|
+ builder.write('TLObject.serializeBytes(%s)', name)
|
|
|
} else if (arg.type === 'date') {
|
|
|
- builder.write('TLObject.serializeDatetime(%s)', name);
|
|
|
+ builder.write('TLObject.serializeDatetime(%s)', name)
|
|
|
} else {
|
|
|
// Else it may be a custom type
|
|
|
- builder.write('%s.bytes', name);
|
|
|
+ builder.write('%s.bytes', name)
|
|
|
|
|
|
// If the type is not boxed (i.e. starts with lowercase) we should
|
|
|
// not serialize the constructor ID (so remove its first 4 bytes).
|
|
|
- let boxed = arg.type.charAt(arg.type.indexOf('.') + 1);
|
|
|
- boxed = boxed === boxed.toUpperCase();
|
|
|
+ let boxed = arg.type.charAt(arg.type.indexOf('.') + 1)
|
|
|
+ boxed = boxed === boxed.toUpperCase()
|
|
|
|
|
|
if (!boxed) {
|
|
|
- builder.write('.slice(4)');
|
|
|
+ builder.write('.slice(4)')
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (arg.isFlag) {
|
|
|
- builder.write(']');
|
|
|
+ builder.write(']')
|
|
|
|
|
|
if (arg.isVector) {
|
|
|
- builder.write(')');
|
|
|
+ builder.write(')')
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
-};
|
|
|
+ return true
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* Writes the read code for the given argument, setting the
|
|
@@ -641,267 +641,267 @@ const writeArgToBytes = (builder, arg, args, name = null) => {
|
|
|
*/
|
|
|
const writeArgReadCode = (builder, arg, args, name) => {
|
|
|
if (arg.genericDefinition) {
|
|
|
- return; // Do nothing, this only specifies a later type
|
|
|
+ return // Do nothing, this only specifies a later type
|
|
|
}
|
|
|
// The argument may be a flag, only write that flag was given!
|
|
|
- let wasFlag = false;
|
|
|
+ let wasFlag = false
|
|
|
if (arg.isFlag) {
|
|
|
// Treat 'true' flags as a special case, since they're true if
|
|
|
// they're set, and nothing else needs to actually be read.
|
|
|
if (arg.type === 'true') {
|
|
|
- builder.writeln('%s = Boolean(flags & %s);', name, 1 << arg.flagIndex);
|
|
|
- return;
|
|
|
+ builder.writeln('%s = Boolean(flags & %s);', name, 1 << arg.flagIndex)
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
- wasFlag = true;
|
|
|
- builder.writeln('if (flags & %s) {', 1 << arg.flagIndex);
|
|
|
+ wasFlag = true
|
|
|
+ builder.writeln('if (flags & %s) {', 1 << arg.flagIndex)
|
|
|
// Temporary disable .is_flag not to enter this if
|
|
|
// again when calling the method recursively
|
|
|
- arg.isFlag = false;
|
|
|
+ arg.isFlag = false
|
|
|
}
|
|
|
|
|
|
if (arg.isVector) {
|
|
|
if (arg.useVectorId) {
|
|
|
// We have to read the vector's constructor ID
|
|
|
- builder.writeln('reader.readInt();');
|
|
|
+ builder.writeln('reader.readInt();')
|
|
|
}
|
|
|
|
|
|
- builder.writeln('%s = [];', name);
|
|
|
- builder.writeln('len = reader.readInt();');
|
|
|
- builder.writeln('for (let i=0;i<len;i++){');
|
|
|
+ builder.writeln('%s = [];', name)
|
|
|
+ builder.writeln('len = reader.readInt();')
|
|
|
+ builder.writeln('for (let i=0;i<len;i++){')
|
|
|
|
|
|
// Temporary disable .is_vector, not to enter this if again
|
|
|
- arg.isVector = false;
|
|
|
- writeArgReadCode(builder, arg, args, '_x');
|
|
|
- builder.writeln('%s.push(_x);', name);
|
|
|
- arg.isVector = true;
|
|
|
+ arg.isVector = false
|
|
|
+ writeArgReadCode(builder, arg, args, '_x')
|
|
|
+ builder.writeln('%s.push(_x);', name)
|
|
|
+ arg.isVector = true
|
|
|
} else if (arg.flagIndicator) {
|
|
|
// Read the flags, which will indicate what items we should read next
|
|
|
- builder.writeln('let flags = reader.readInt();');
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln('let flags = reader.readInt();')
|
|
|
+ builder.writeln()
|
|
|
} else if (arg.type === 'int') {
|
|
|
- builder.writeln('%s = reader.readInt();', name);
|
|
|
+ builder.writeln('%s = reader.readInt();', name)
|
|
|
} else if (arg.type === 'long') {
|
|
|
- builder.writeln('%s = reader.readLong();', name);
|
|
|
+ builder.writeln('%s = reader.readLong();', name)
|
|
|
} else if (arg.type === 'int128') {
|
|
|
- builder.writeln('%s = reader.readLargeInt(128);', name);
|
|
|
+ builder.writeln('%s = reader.readLargeInt(128);', name)
|
|
|
} else if (arg.type === 'int256') {
|
|
|
- builder.writeln('%s = reader.readLargeInt(256);', name);
|
|
|
+ builder.writeln('%s = reader.readLargeInt(256);', name)
|
|
|
} else if (arg.type === 'double') {
|
|
|
- builder.writeln('%s = reader.readDouble();', name);
|
|
|
+ builder.writeln('%s = reader.readDouble();', name)
|
|
|
} else if (arg.type === 'string') {
|
|
|
- builder.writeln('%s = reader.tgReadString();', name);
|
|
|
+ builder.writeln('%s = reader.tgReadString();', name)
|
|
|
} else if (arg.type === 'Bool') {
|
|
|
- builder.writeln('%s = reader.tgReadBool();', name);
|
|
|
+ builder.writeln('%s = reader.tgReadBool();', name)
|
|
|
} else if (arg.type === 'true') {
|
|
|
- builder.writeln('%s = true;', name);
|
|
|
+ builder.writeln('%s = true;', name)
|
|
|
} else if (arg.type === 'bytes') {
|
|
|
- builder.writeln('%s = reader.tgReadBytes();', name);
|
|
|
+ builder.writeln('%s = reader.tgReadBytes();', name)
|
|
|
} else if (arg.type === 'date') {
|
|
|
- builder.writeln('%s = reader.tgReadDate();', name);
|
|
|
+ builder.writeln('%s = reader.tgReadDate();', name)
|
|
|
} else {
|
|
|
// Else it may be a custom type
|
|
|
if (!arg.skipConstructorId) {
|
|
|
- builder.writeln('%s = reader.tgReadObject();', name);
|
|
|
+ builder.writeln('%s = reader.tgReadObject();', name)
|
|
|
} else {
|
|
|
// Import the correct type inline to avoid cyclic imports.
|
|
|
// There may be better solutions so that we can just access
|
|
|
// all the types before the files have been parsed, but I
|
|
|
// don't know of any.
|
|
|
- const sepIndex = arg.type.indexOf('.');
|
|
|
- let ns;
|
|
|
- let t;
|
|
|
+ const sepIndex = arg.type.indexOf('.')
|
|
|
+ let ns
|
|
|
+ let t
|
|
|
|
|
|
if (sepIndex === -1) {
|
|
|
- ns = '.';
|
|
|
- t = arg.type;
|
|
|
+ ns = '.'
|
|
|
+ t = arg.type
|
|
|
} else {
|
|
|
- ns = '.' + arg.type.slice(0, sepIndex);
|
|
|
- t = arg.type.slice(sepIndex + 1);
|
|
|
+ ns = '.' + arg.type.slice(0, sepIndex)
|
|
|
+ t = arg.type.slice(sepIndex + 1)
|
|
|
}
|
|
|
|
|
|
- const className = snakeToCamelCase(t);
|
|
|
+ const className = snakeToCamelCase(t)
|
|
|
|
|
|
// There would be no need to import the type if we're in the
|
|
|
// file with the same namespace, but since it does no harm
|
|
|
// and we don't have information about such thing in the
|
|
|
// method we just ignore that case.
|
|
|
- builder.writeln('let %s = require("%s");', className, ns);
|
|
|
- builder.writeln('%s = %s.fromReader(reader);', name, className);
|
|
|
+ builder.writeln('let %s = require("%s");', className, ns)
|
|
|
+ builder.writeln('%s = %s.fromReader(reader);', name, className)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// End vector and flag blocks if required (if we opened them before)
|
|
|
if (arg.isVector) {
|
|
|
- builder.writeln('}');
|
|
|
+ builder.writeln('}')
|
|
|
}
|
|
|
|
|
|
if (wasFlag) {
|
|
|
- builder.endBlock();
|
|
|
- builder.writeln('else {');
|
|
|
- builder.writeln('%s = null', name);
|
|
|
- builder.endBlock();
|
|
|
+ builder.endBlock()
|
|
|
+ builder.writeln('else {')
|
|
|
+ builder.writeln('%s = null', name)
|
|
|
+ builder.endBlock()
|
|
|
// Restore .isFlag;
|
|
|
- arg.isFlag = true;
|
|
|
+ arg.isFlag = true
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const writePatched = (outDir, namespaceTlobjects) => {
|
|
|
- fs.mkdirSync(outDir, { recursive: true });
|
|
|
+ fs.mkdirSync(outDir, { recursive: true })
|
|
|
|
|
|
for (const [ns, tlobjects] of Object.entries(namespaceTlobjects)) {
|
|
|
- const file = `${outDir}/${ns === 'null' ? 'index' : ns}.js`;
|
|
|
- const stream = fs.createWriteStream(file);
|
|
|
- const builder = new SourceBuilder(stream);
|
|
|
+ const file = `${outDir}/${ns === 'null' ? 'index' : ns}.js`
|
|
|
+ const stream = fs.createWriteStream(file)
|
|
|
+ const builder = new SourceBuilder(stream)
|
|
|
|
|
|
- builder.writeln(AUTO_GEN_NOTICE);
|
|
|
- builder.writeln('const struct = require(\'python-struct\');');
|
|
|
- builder.writeln(`const { TLObject, types, custom } = require('..');`);
|
|
|
- builder.writeln(`const Helpers = require('../../utils/Helpers');`);
|
|
|
+ builder.writeln(AUTO_GEN_NOTICE)
|
|
|
+ builder.writeln('const struct = require(\'python-struct\');')
|
|
|
+ builder.writeln(`const { TLObject, types, custom } = require('..');`)
|
|
|
+ builder.writeln(`const Helpers = require('../../utils/Helpers');`)
|
|
|
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln()
|
|
|
|
|
|
for (const t of tlobjects) {
|
|
|
- builder.writeln('class %s extends custom.%s {', t.className, PATCHED_TYPES[t.fullname]);
|
|
|
- builder.writeln(`static CONSTRUCTOR_ID = 0x${t.id.toString(16)}`);
|
|
|
- builder.writeln(`static SUBCLASS_OF_ID = 0x${crc32(t.result).toString('16')}`);
|
|
|
- builder.writeln();
|
|
|
- builder.writeln('constructor() {');
|
|
|
- builder.writeln('super();');
|
|
|
- builder.writeln(`this.CONSTRUCTOR_ID = 0x${t.id.toString(16)}`);
|
|
|
- builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(t.result).toString('16')}`);
|
|
|
+ builder.writeln('class %s extends custom.%s {', t.className, PATCHED_TYPES[t.fullname])
|
|
|
+ builder.writeln(`static CONSTRUCTOR_ID = 0x${t.id.toString(16)}`)
|
|
|
+ builder.writeln(`static SUBCLASS_OF_ID = 0x${crc32(t.result).toString('16')}`)
|
|
|
+ builder.writeln()
|
|
|
+ builder.writeln('constructor() {')
|
|
|
+ builder.writeln('super();')
|
|
|
+ builder.writeln(`this.CONSTRUCTOR_ID = 0x${t.id.toString(16)}`)
|
|
|
+ builder.writeln(`this.SUBCLASS_OF_ID = 0x${crc32(t.result).toString('16')}`)
|
|
|
|
|
|
- builder.endBlock();
|
|
|
+ builder.endBlock()
|
|
|
|
|
|
// writeToJson(t, builder);
|
|
|
- writeToBytes(t, builder);
|
|
|
- writeFromReader(t, builder);
|
|
|
-
|
|
|
- builder.writeln();
|
|
|
- builder.endBlock();
|
|
|
- builder.currentIndent = 0;
|
|
|
- builder.writeln('types.%s%s = %s', t.namespace ? `${t.namespace}.` : '', t.className, t.className);
|
|
|
- builder.writeln();
|
|
|
+ writeToBytes(t, builder)
|
|
|
+ writeFromReader(t, builder)
|
|
|
+
|
|
|
+ builder.writeln()
|
|
|
+ builder.endBlock()
|
|
|
+ builder.currentIndent = 0
|
|
|
+ builder.writeln('types.%s%s = %s', t.namespace ? `${t.namespace}.` : '', t.className, t.className)
|
|
|
+ builder.writeln()
|
|
|
}
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const writeAllTLObjects = (tlobjects, layer, builder) => {
|
|
|
- builder.writeln(AUTO_GEN_NOTICE);
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln(AUTO_GEN_NOTICE)
|
|
|
+ builder.writeln()
|
|
|
|
|
|
- builder.writeln('const { types, functions, patched } = require(\'.\');');
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln('const { types, functions, patched } = require(\'.\');')
|
|
|
+ builder.writeln()
|
|
|
|
|
|
// Create a constant variable to indicate which layer this is
|
|
|
- builder.writeln(`const LAYER = %s;`, layer);
|
|
|
- builder.writeln();
|
|
|
+ builder.writeln(`const LAYER = %s;`, layer)
|
|
|
+ builder.writeln()
|
|
|
|
|
|
// Then create the dictionary containing constructor_id: class
|
|
|
- builder.writeln('const tlobjects = {');
|
|
|
+ builder.writeln('const tlobjects = {')
|
|
|
|
|
|
// Fill the dictionary (0x1a2b3c4f: tl.full.type.path.Class)
|
|
|
for (const tlobject of tlobjects) {
|
|
|
- builder.write('0x0%s: ', tlobject.id.toString(16).padStart(8, '0'));
|
|
|
+ builder.write('0x0%s: ', tlobject.id.toString(16).padStart(8, '0'))
|
|
|
|
|
|
if (tlobject.fullname in PATCHED_TYPES) {
|
|
|
- builder.write('patched');
|
|
|
+ builder.write('patched')
|
|
|
} else {
|
|
|
- builder.write(tlobject.isFunction ? 'functions' : 'types');
|
|
|
+ builder.write(tlobject.isFunction ? 'functions' : 'types')
|
|
|
}
|
|
|
|
|
|
if (tlobject.namespace) {
|
|
|
- builder.write('.%s', tlobject.namespace);
|
|
|
+ builder.write('.%s', tlobject.namespace)
|
|
|
}
|
|
|
|
|
|
- builder.writeln('.%s,', tlobject.className);
|
|
|
+ builder.writeln('.%s,', tlobject.className)
|
|
|
}
|
|
|
|
|
|
- builder.endBlock(true);
|
|
|
- builder.writeln('');
|
|
|
- builder.writeln('module.exports = {');
|
|
|
- builder.writeln('LAYER,');
|
|
|
- builder.writeln('tlobjects');
|
|
|
- builder.endBlock(true);
|
|
|
-};
|
|
|
+ builder.endBlock(true)
|
|
|
+ builder.writeln('')
|
|
|
+ builder.writeln('module.exports = {')
|
|
|
+ builder.writeln('LAYER,')
|
|
|
+ builder.writeln('tlobjects')
|
|
|
+ builder.endBlock(true)
|
|
|
+}
|
|
|
|
|
|
const generateTLObjects = (tlobjects, layer, importDepth, outputDir) => {
|
|
|
// Group everything by {namespace :[tlobjects]} to generate index.js
|
|
|
- const namespaceFunctions = {};
|
|
|
- const namespaceTypes = {};
|
|
|
- const namespacePatched = {};
|
|
|
+ const namespaceFunctions = {}
|
|
|
+ const namespaceTypes = {}
|
|
|
+ const namespacePatched = {}
|
|
|
|
|
|
// Group {type: [constructors]} to generate the documentation
|
|
|
- const typeConstructors = {};
|
|
|
+ const typeConstructors = {}
|
|
|
|
|
|
for (const tlobject of tlobjects) {
|
|
|
if (tlobject.isFunction) {
|
|
|
if (!namespaceFunctions[tlobject.namespace]) {
|
|
|
- namespaceFunctions[tlobject.namespace] = [];
|
|
|
+ namespaceFunctions[tlobject.namespace] = []
|
|
|
}
|
|
|
|
|
|
- namespaceFunctions[tlobject.namespace].push(tlobject);
|
|
|
+ namespaceFunctions[tlobject.namespace].push(tlobject)
|
|
|
} else {
|
|
|
if (!namespaceTypes[tlobject.namespace]) {
|
|
|
- namespaceTypes[tlobject.namespace] = [];
|
|
|
+ namespaceTypes[tlobject.namespace] = []
|
|
|
}
|
|
|
|
|
|
if (!typeConstructors[tlobject.result]) {
|
|
|
- typeConstructors[tlobject.result] = [];
|
|
|
+ typeConstructors[tlobject.result] = []
|
|
|
}
|
|
|
|
|
|
- namespaceTypes[tlobject.namespace].push(tlobject);
|
|
|
- typeConstructors[tlobject.result].push(tlobject);
|
|
|
+ namespaceTypes[tlobject.namespace].push(tlobject)
|
|
|
+ typeConstructors[tlobject.result].push(tlobject)
|
|
|
|
|
|
if (tlobject.fullname in PATCHED_TYPES) {
|
|
|
if (!namespacePatched[tlobject.namespace]) {
|
|
|
- namespacePatched[tlobject.namespace] = [];
|
|
|
+ namespacePatched[tlobject.namespace] = []
|
|
|
}
|
|
|
|
|
|
- namespacePatched[tlobject.namespace].push(tlobject);
|
|
|
+ namespacePatched[tlobject.namespace].push(tlobject)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- writeModules(`${outputDir}/functions`, importDepth, 'TLRequest', namespaceFunctions, typeConstructors);
|
|
|
- writeModules(`${outputDir}/types`, importDepth, 'TLObject', namespaceTypes, typeConstructors);
|
|
|
- writePatched(`${outputDir}/patched`, namespacePatched);
|
|
|
+ writeModules(`${outputDir}/functions`, importDepth, 'TLRequest', namespaceFunctions, typeConstructors)
|
|
|
+ writeModules(`${outputDir}/types`, importDepth, 'TLObject', namespaceTypes, typeConstructors)
|
|
|
+ writePatched(`${outputDir}/patched`, namespacePatched)
|
|
|
|
|
|
- const filename = `${outputDir}/alltlobjects.js`;
|
|
|
- const stream = fs.createWriteStream(filename);
|
|
|
- const builder = new SourceBuilder(stream);
|
|
|
+ const filename = `${outputDir}/AllTLObjects.js`
|
|
|
+ const stream = fs.createWriteStream(filename)
|
|
|
+ const builder = new SourceBuilder(stream)
|
|
|
|
|
|
- writeAllTLObjects(tlobjects, layer, builder);
|
|
|
-};
|
|
|
+ writeAllTLObjects(tlobjects, layer, builder)
|
|
|
+}
|
|
|
|
|
|
const cleanTLObjects = (outputDir) => {
|
|
|
for (let d of ['functions', 'types', 'patched']) {
|
|
|
- d = `${outputDir}/d`;
|
|
|
+ d = `${outputDir}/d`
|
|
|
|
|
|
if (fs.statSync(d).isDirectory()) {
|
|
|
- fs.rmdirSync(d);
|
|
|
+ fs.rmdirSync(d)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const tl = `${outputDir}/alltlobjects.js`;
|
|
|
+ const tl = `${outputDir}/AllTLObjects.js`
|
|
|
|
|
|
if (fs.statSync(tl).isFile()) {
|
|
|
- fs.unlinkSync(tl);
|
|
|
+ fs.unlinkSync(tl)
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
const writeModuleExports = (tlobjects, builder) => {
|
|
|
- builder.writeln('module.exports = {');
|
|
|
+ builder.writeln('module.exports = {')
|
|
|
|
|
|
for (const t of tlobjects) {
|
|
|
- builder.writeln(`${t.className},`);
|
|
|
+ builder.writeln(`${t.className},`)
|
|
|
}
|
|
|
|
|
|
- builder.currentIndent--;
|
|
|
- builder.writeln('};');
|
|
|
-};
|
|
|
+ builder.currentIndent--
|
|
|
+ builder.writeln('};')
|
|
|
+}
|
|
|
|
|
|
module.exports = {
|
|
|
generateTLObjects,
|
|
|
cleanTLObjects,
|
|
|
-};
|
|
|
+}
|