telegram-mtproto
Version:
Telegram MTProto library
120 lines (112 loc) • 4.51 kB
JavaScript
const ConstructorBuilder = require('./constructor-builder')
const util = require('util')
const utility = require('../utility')
const getLogger = require('../../logger')
const logger = getLogger('mtp:TypeBuilder')
// Extend the 'constructor' with the Type generated by the 'superTLSchema'
function inheritsTlSchema(construct, superTlSchema) {
const NewType = buildType('abstract', superTlSchema)
util.inherits(construct, NewType)
construct.s_ = NewType
construct.super_ = NewType.super_
construct.util = NewType.util
construct.requireTypeByName = NewType.requireTypeByName
construct.requireTypeFromBuffer = NewType.requireTypeFromBuffer
construct.logger = NewType.logger
}
// Types builder
const buildTypes = (schemas, types, targetModule, isTypeFunction) => {
for (let i = 0; i < schemas.length; i++) {
const type = schemas[i]
// Vector is already defined by class TypeVector
if ('vector' !== type.predicate &&
( !types || types.indexOf(type[isTypeFunction ? 'method' : 'type']) > -1)) {
let typeName
if (isTypeFunction) {
typeName = type.method
const newFunction = buildTypeFunction(targetModule._id, type)
setType(typeName, targetModule, newFunction, true)
} else {
typeName = type.predicate
const newConstructor = buildType(targetModule._id, type)
setType(typeName, targetModule, newConstructor, false)
}
}
}
}
function setType(typeName, targetModule, type, isTypeFunction) {
if (targetModule && typeName && typeName.length > 0) {
const index = typeName.indexOf('.')
if (index < 0) {
typeName = isTypeFunction ? typeName : utility.capitalize(typeName)
return targetModule[typeName] = type
} else if (index === 0) {
setType(typeName.slice(1), targetModule, type, isTypeFunction)
} else if (index === (typeName.length - 1)) {
setType(typeName.slice(0, -1), targetModule, type, isTypeFunction)
}
else {
const pkg = typeName.slice(0, index)
targetModule[pkg] = targetModule[pkg] ? targetModule[pkg] : {}
setType(typeName.slice(index + 1), targetModule[pkg], type, isTypeFunction)
}
}
}
// Build a new `TypeLanguage` type parsing the `TL-Schema constructor`
const buildType = (buildModule, tlSchema) =>
new ConstructorBuilder(buildModule, tlSchema).getType()
// Build a new `TypeLanguage` function parsing the `TL-Schema method`
function buildTypeFunction(buildModule, tlSchema) {
const methodName = tlSchema.method
// Start creating the body of the new Type function
let body =
'\tvar self = arguments.callee;\n' +
'\tvar callback = options.callback;\n' +
'\tvar channel = options.channel;\n' +
'\tif (!channel) {\n' +
'\t\tvar msg = \'The \\\'channel\\\' option is missing, it\\\'s mandatory\';\n' +
'\t\tself.logger.error(msg);\n' +
'\t\tif(callback) {\n' +
'\t\t\tcallback(new TypeError(msg));\n' +
'\t\t}\n' +
'\t\treturn;\n' +
'\t}\n'
body +=
'\tvar reqPayload = new self.Type(options)\n' +
// '\tdebugger\n' +
'\tchannel.callMethod(reqPayload, callback)\n'
// '\tchannel.request(reqPayload).then(e => callback(null, e), callback);\n'
logger.debug('Body for %s type function:', methodName)
logger.debug(`\n${ body}`)
// Create the new Type function
const typeFunction = new Function('options', body)
typeFunction._name = methodName
typeFunction.requireTypeFromBuffer = ConstructorBuilder.requireTypeFromBuffer
// Create the function payload class re-calling TypeBuilder constructor.
typeFunction.Type = new ConstructorBuilder(buildModule, tlSchema, true).getType()
typeFunction.logger = getLogger(`${buildModule }.${ methodName}`)
return typeFunction
}
function registerTypeById(type) {
ConstructorBuilder.registerTypeById(type)
}
function requireTypeFromBuffer(buffer) {
return ConstructorBuilder.requireTypeFromBuffer(buffer)
}
function registerTypeByName(name, type) {
ConstructorBuilder.registerTypeByName(name, type)
}
function requireTypeByName(name, type) {
return ConstructorBuilder.requireTypeByName(name, type)
}
module.exports = {
buildType,
buildTypes,
buildTypeFunction,
inheritsTlSchema,
registerTypeById,
requireTypeFromBuffer,
registerTypeByName,
requireTypeByName
}