tdl
Version:
Node.js bindings to TDLib (Telegram Database library)
199 lines (198 loc) • 7.34 kB
JavaScript
;
/// <reference types="prebuilt-tdlib" />
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnknownError = exports.TDLibError = exports.execute = void 0;
exports.configure = configure;
exports.init = init;
exports.setLogMessageCallback = setLogMessageCallback;
exports.createClient = createClient;
exports.createBareClient = createBareClient;
const path = __importStar(require("node:path"));
const debug_1 = __importDefault(require("debug"));
const client_1 = require("./client");
Object.defineProperty(exports, "TDLibError", { enumerable: true, get: function () { return client_1.TDLibError; } });
Object.defineProperty(exports, "UnknownError", { enumerable: true, get: function () { return client_1.UnknownError; } });
const addon_1 = require("./addon");
const util_1 = require("./util");
const debug = (0, debug_1.default)('tdl');
let tdjsonAddon = null;
const defaultLibraryFile = (() => {
switch (process.platform) {
case 'win32': return 'tdjson.dll';
case 'darwin': return 'libtdjson.dylib';
default: return 'libtdjson.so';
}
})();
const cfg = {
tdjson: defaultLibraryFile,
libdir: '',
verbosityLevel: 1,
receiveTimeout: 10,
useOldTdjsonInterface: false
};
function configure(opts = {}) {
if (tdjsonAddon)
throw Error('TDLib is already initialized; too late to configure');
if (opts.tdjson != null)
cfg.tdjson = opts.tdjson;
if (opts.libdir != null)
cfg.libdir = opts.libdir;
if (opts.verbosityLevel != null)
cfg.verbosityLevel = opts.verbosityLevel;
if (opts.receiveTimeout != null)
cfg.receiveTimeout = opts.receiveTimeout;
if (opts.useOldTdjsonInterface != null)
cfg.useOldTdjsonInterface = opts.useOldTdjsonInterface;
}
function init() {
if (tdjsonAddon != null)
return;
debug('Initializing the node addon');
const lib = path.join(cfg.libdir, cfg.tdjson);
tdjsonAddon = (0, addon_1.loadAddon)(lib, cfg.useOldTdjsonInterface);
if (cfg.verbosityLevel !== 'default') {
debug('Executing setLogVerbosityLevel', cfg.verbosityLevel);
const request = JSON.stringify({
'@type': 'setLogVerbosityLevel',
new_verbosity_level: cfg.verbosityLevel
});
const response = !cfg.useOldTdjsonInterface
? tdjsonAddon.tdnew.execute(request)
: tdjsonAddon.tdold.execute(null, request);
debug('setLogVerbosityLevel response:', response);
}
}
const execute = function execute(request) {
if (tdjsonAddon == null) {
init();
if (tdjsonAddon == null)
throw Error('TDLib is uninitialized');
}
debug('execute', request);
request = JSON.stringify((0, util_1.deepRenameKey)('_', '@type', request));
const response = !cfg.useOldTdjsonInterface
? tdjsonAddon.tdnew.execute(request)
: tdjsonAddon.tdold.execute(null, request);
return (0, util_1.deepRenameKey)('@type', '_', JSON.parse(response));
};
exports.execute = execute;
function setLogMessageCallback(maxVerbosityLevel, callback) {
if (tdjsonAddon == null) {
init();
if (tdjsonAddon == null)
throw Error('TDLib is uninitialized');
}
tdjsonAddon.setLogMessageCallback(maxVerbosityLevel, callback);
}
const clientMap = new Map();
let tdnInitialized = false;
let runningReceiveLoop = false;
// Loop for the new tdjson interface
async function receiveLoop() {
debug('Starting tdn receive loop');
if (tdjsonAddon == null)
throw new Error('TDLib is uninitialized');
runningReceiveLoop = true;
try {
tdjsonAddon.tdnew.ref();
while (true) {
if (clientMap.size < 1) {
debug('Stopping receive loop');
break;
}
const responseString = await tdjsonAddon.tdnew.receive();
if (responseString == null) {
debug('Receive loop: got empty response');
continue;
}
const res = JSON.parse(responseString);
const clientId = res['@client_id'];
const client = clientId != null ? clientMap.get(clientId) : undefined;
if (client == null) {
debug(`Cannot find client_id ${clientId}`);
continue;
}
delete res['@client_id']; // Note that delete is somewhat slow
client.handleReceive(res);
}
}
finally {
runningReceiveLoop = false;
tdjsonAddon.tdnew.unref();
}
}
function createAnyClient(opts, bare = false) {
if (tdjsonAddon == null) {
init();
if (tdjsonAddon == null)
throw Error('TDLib is uninitialized');
}
const managingOpts = {
bare,
receiveTimeout: cfg.receiveTimeout,
executeFunc: exports.execute,
useOldTdjsonInterface: false
};
if (cfg.useOldTdjsonInterface) {
const tdoManaging = { ...managingOpts, useOldTdjsonInterface: true };
return new client_1.Client(tdjsonAddon, tdoManaging, opts);
}
if (!tdnInitialized) {
tdjsonAddon.tdnew.init(cfg.receiveTimeout);
tdnInitialized = true;
}
const client = new client_1.Client(tdjsonAddon, managingOpts, opts);
const clientId = client.getClientId();
clientMap.set(clientId, client);
client.once('close', () => {
debug(`Deleting client_id ${clientId}`);
clientMap.delete(clientId);
});
if (!runningReceiveLoop)
receiveLoop();
return client;
}
function createClient(opts) {
return createAnyClient(opts);
}
function createBareClient() {
return createAnyClient({}, true);
}
// TODO: We could possibly export an unsafe/unstable getRawTdjson() : Tdjson
// function that allows to access underlying tdjson functions