UNPKG

tdlib-native

Version:

🚀 Telegram TDLib native nodejs wrapper

199 lines (198 loc) • 4.89 kB
import path from "path"; import { getAddonFolderPath } from "./path.mjs"; import { createRequire } from "module"; import { promiseWithResolvers } from "../shared/async.mjs"; import { family } from "detect-libc"; const builtinAddonPath = path.resolve( getAddonFolderPath(), "..", "..", "build", "Release", "td.node" ); async function loadAddon(addonPath = builtinAddonPath) { const baseDirectory = getAddonFolderPath(); const load = createRequire(baseDirectory); const addon = load(addonPath); return addon; } async function getTDLibPath() { let packageName = `@tdlib-native/tdjson-${process.platform}-${process.arch}`; if (process.platform === "android") { packageName += "-glibc"; } if (process.platform === "linux") { packageName += `-${await family()}`; } try { const { tdlibPath } = await import(packageName); return tdlibPath; } catch (error) { throw new Error( `There is no prebuilt TDLib for your platform (${process.platform} ${process.arch}). You can ask for it: https://github.com/AlexXanderGrib/node-tdlib/issues`, { cause: error } ); } } class ReceiveQueueEntry { constructor(client, promise) { this.client = client; this.promise = promise; Object.freeze(this); } } class ClientMeta { constructor(timeout) { this.timeout = timeout; } destroyed = false; } class TDLibAddon { /** * Creates an instance of TDLibAddon. * @param {Addon} _addon * @memberof TDLibAddon */ constructor(_addon) { this._addon = _addon; } /** * * * @static * @param {string} [tdlibPath] Resolves to prebuild TDLib for your platform * @param {string} [addonPath] * @returns {Promise<TDLib>} * @memberof TDLibAddon */ static async create(tdlibPath, addonPath) { tdlibPath ??= await getTDLibPath(); const addon = await loadAddon(addonPath); addon.load_tdjson(tdlibPath); return new TDLibAddon(addon); } _isTDLib = true; _clients = /* @__PURE__ */ new WeakMap(); /** * * * @readonly * @memberof TDLibAddon */ get name() { return "addon"; } /** * * * @returns {TDLibClient} {TDLibClient} * @memberof TDLibAddon */ create(timeout) { const client = this._addon.td_json_client_create(timeout); this._clients.set(client, new ClientMeta(timeout)); return client; } _getMeta(client) { const meta = this._clients.get(client); if (!meta) { throw new Error("Unknown client"); } return meta; } /** * * * @param {TDLibClient} client * @memberof TDLibAddon * @returns {Promise<void>} */ async destroy(client) { if (this._getMeta(client).destroyed) { throw new Error("Client already destroyed"); } for (const entry of this._queue) { if (entry.client === client) { entry.promise.reject(new Error("Client is destroyed")); } } await this._thread; this._addon.td_json_client_destroy(client); } /** * * * @param {(TDLibClient | null)} client * @param {string} json * @returns {(string | null)} {(string | null)} * @memberof TDLibAddon */ execute(client, json) { return this._addon.td_json_client_execute(client, json); } _queue = []; _thread; async _receive() { while (this._queue.length > 0) { const task = this._queue.shift(); if (!task) break; await this._addon.td_json_client_receive(task.client).then(task.promise.resolve, task.promise.reject); } } /** * * * @param {TDLibClient} client * @returns {Promise<string|null>} {(Promise<string | null>)} * @memberof TDLibAddon */ receive(client) { const meta = this._getMeta(client); if (meta.destroyed) { return Promise.reject(new Error("Client is destroyed")); } const entryWithSameClient = this._queue.find((entry2) => entry2.client === client); if (entryWithSameClient) { return Promise.reject(new Error("This client is already receiving updates")); } const promise = promiseWithResolvers(); const entry = new ReceiveQueueEntry(client, promise); this._queue.push(entry); if (!this._thread) { this._thread = this._receive().finally(() => { this._thread = void 0; }); } return promise.promise; } /** * * * @param {TDLibClient} client * @param {string} json * @memberof TDLibAddon * @returns {void} */ send(client, json) { if (this._getMeta(client).destroyed) { throw new Error("Client is destroyed"); } this._addon.td_json_client_send(client, json); } /** * * * @param {function(errorMessage: string): void=} callback * @memberof TDLibAddon * @returns {void} */ setLogMessageCallback(level, callback) { this._addon.td_set_log_message_callback(level, callback); } } export { TDLibAddon };