{"id":14991409,"url":"https://github.com/eilvelia/tdl","last_synced_at":"2025-05-14T19:02:28.915Z","repository":{"id":32199828,"uuid":"131876799","full_name":"eilvelia/tdl","owner":"eilvelia","description":"Node.js bindings to TDLib 🥒","archived":false,"fork":false,"pushed_at":"2025-04-01T14:53:28.000Z","size":6377,"stargazers_count":455,"open_issues_count":3,"forks_count":55,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-13T13:57:21.364Z","etag":null,"topics":["bun","deno","libtdjson","node-addon","prebuilt-tdlib","tdjson","tdlib","telegram","telegram-api","telegram-client-api"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eilvelia.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-02T16:20:06.000Z","updated_at":"2025-04-08T06:39:47.000Z","dependencies_parsed_at":"2024-03-09T00:32:35.710Z","dependency_job_id":"b694285b-9e5d-468d-966c-d2db7659acb2","html_url":"https://github.com/eilvelia/tdl","commit_stats":{"total_commits":592,"total_committers":6,"mean_commits":98.66666666666667,"dds":0.01858108108108103,"last_synced_commit":"37c7107fa5976fe8af524940c11a7eb8b006c440"},"previous_names":["eilvelia/tdl","bannerets/tdl"],"tags_count":62,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eilvelia%2Ftdl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eilvelia%2Ftdl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eilvelia%2Ftdl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eilvelia%2Ftdl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eilvelia","download_url":"https://codeload.github.com/eilvelia/tdl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248724587,"owners_count":21151559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bun","deno","libtdjson","node-addon","prebuilt-tdlib","tdjson","tdlib","telegram","telegram-api","telegram-client-api"],"created_at":"2024-09-24T14:27:45.747Z","updated_at":"2025-05-14T19:02:28.902Z","avatar_url":"https://github.com/eilvelia.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","telegram","Bindings"],"sub_categories":["JavaScript / TypeScript (Node.js)"],"readme":"# tdl \u0026nbsp; [![npm](https://img.shields.io/npm/v/tdl.svg)](https://www.npmjs.com/package/tdl) [![CI](https://github.com/eilvelia/tdl/actions/workflows/ci.yml/badge.svg)](https://github.com/eilvelia/tdl/actions/workflows/ci.yml)\n\ntdl is a fairly simple JavaScript wrapper for [TDLib][] (Telegram Database library),\na library for creating [Telegram][] clients or bots.\n\n[TDLib]: https://github.com/tdlib/td\n[Telegram]: https://telegram.org/\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Getting started](#getting-started)\n- [API](#api)\n- [Types](#types)\n- [Other JavaScript runtimes](#other-javascript-runtimes)\n- [Troubleshooting](#troubleshooting)\n- [Issue tracker](#issue-tracker)\n\n\u003ca name=\"requirements\"\u003e\u003c/a\u003e\n## Requirements\n\n- Node.js v16 or newer\n- The tdjson shared library (`libtdjson.so` on Linux, `libtdjson.dylib` on macOS, `tdjson.dll` on Windows), of TDLib version 1.8.0 or newer\n- In rare cases, a C++ compiler and Python installed to build the node addon[^1]\n\n[^1]: tdl is packaged with pre-built addons for Windows (x86_64), GNU/Linux (x86_64, arm64; glibc \u003e= 2.22), and macOS (x86_64, arm64; v10.14+). If a pre-built binary is not available for your system, then the node addon will be built using node-gyp, requiring Python and a C++ toolchain (C++14 is required) to be installed (on Windows, MSVS or Build Tools). Pass `--build-from-source` to never use the pre-built binaries. arm64 binaries are not tested in the CI. Linux binaries are statically linked against libstdc++.\n\n\u003ca name=\"installation\"\u003e\u003c/a\u003e\n## Installation\n\n1. Install tdl: `npm install tdl`\n2. [Build][tdlib-building] TDLib or install pre-built TDLib libraries\n   (`npm install prebuilt-tdlib`)\n3. If you use TypeScript, types for TDLib are installed separately,\n   see the [Types](#types) section\n\nTo use tdl, you first need to get TDLib, which is dynamically loaded by tdl.\nThe tdjson shared library should be present in the system search paths (the\npath to libtdjson can also be manually specified in `tdl.configure`, which is\nhow `prebuilt-tdlib` is loaded).\n\n\u003e [!TIP]\n\u003e When building TDLib, the libraries can be installed into the system using\n\u003e `cmake --install .` (optionally specify the `--prefix` option, the default is\n\u003e `/usr/local`) after TDLib has been built successfully. This command may\n\u003e require `sudo`.\n\n[tdlib-building]: https://github.com/tdlib/td#building\n\n### prebuilt-tdlib\n\nInstead of building TDLib from source, you can possibly install pre-built TDLib\nlibraries distributed through the `prebuilt-tdlib` npm package. An example of\nusing libraries from `prebuilt-tdlib` is present in the section below. The\nsupported platforms are x86_64 \u0026 arm64 GNU/Linux, x86_64 \u0026 arm64 macOS, and\nx86_64 Windows. To install `prebuilt-tdlib` for a specific TDLib version\ninstead of latest, for example v1.8.30, run `npm i prebuilt-tdlib@td-1.8.30`.\nThe available versions of `prebuilt-tdlib` can be found by running\n`npm info prebuilt-tdlib dist-tags`. See the README of [prebuilt-tdlib][] for\nadditional information.\n\n[![npm](https://img.shields.io/npm/v/prebuilt-tdlib.svg?label=prebuilt-tdlib)](https://www.npmjs.com/package/prebuilt-tdlib)\n\n[prebuilt-tdlib]: packages/prebuilt-tdlib/README.md\n\n\u003ca name=\"getting-started\"\u003e\u003c/a\u003e\n## Getting started\n\n```javascript\nconst tdl = require('tdl')\n\n// If libtdjson is not present in the system search paths, the path to the\n// libtdjson shared library can be set manually, e.g.:\n//   tdl.configure({ tdjson: '/usr/local/lib/libtdjson.dylib' })\n// The library directory can be set separate from the library name,\n// example to search for libtdjson in the directory of the current script:\n//   tdl.configure({ libdir: __dirname })\n\n// Instead of building TDLib yourself, the aforementioned prebuilt-tdlib can be\n// used as follows:\n//   const { getTdjson } = require('prebuilt-tdlib')\n//   tdl.configure({ tdjson: getTdjson() })\n\nconst client = tdl.createClient({\n  apiId: 2222, // Your api_id\n  apiHash: '0123456789abcdef0123456789abcdef' // Your api_hash\n})\n// Passing apiId and apiHash is mandatory,\n// these values can be obtained at https://my.telegram.org/\n\nclient.on('error', console.error)\n\n// Aside of sending responses to your requests, TDLib pushes to you\n// events called \"updates\", which can be received as follows:\nclient.on('update', update =\u003e {\n  console.log('Received update:', update)\n})\n\nasync function main () {\n  // Log in to a Telegram account. By default, with no arguments, this function will\n  // ask for phone number etc. in the console. Instead of logging in as a user,\n  // it's also possible to log in as a bot using `client.loginAsBot('\u003cTOKEN\u003e')`.\n  await client.login()\n\n  // Invoke a TDLib method. The information regarding TDLib method list and\n  // documentation is below this code block.\n  const me = await client.invoke({ _: 'getMe' })\n  console.log('My user:', me)\n\n  // Invoke some other TDLib method.\n  const chats = await client.invoke({\n    _: 'getChats',\n    chat_list: { _: 'chatListMain' },\n    limit: 10\n  })\n  console.log('A part of my chat list:', chats)\n\n  // Close the instance so that TDLib exits gracefully and the JS runtime can\n  // finish the process.\n  await client.close()\n}\n\nmain().catch(console.error)\n```\n\nInstead of using CommonJS (`require('tdl')`), one can import tdl in an\nEcmaScript module through the interoperability with CommonJS:\n`import * as tdl from 'tdl'`. Or alternatively, import specific functions\nusing `import { createClient } from 'tdl'`.\n\nThe API reference of the TDLib methods, which are called using `client.invoke`,\ncan be found at, e.g.:\n- https://core.telegram.org/tdlib/docs/annotated.html (possibly outdated),\n- in the [td_api.tl][] file in the TDLib repository,\n- if the TypeScript types for TDLib are installed, the documentation can be\n  browsed directly in the editor, using the editor's autocompletion menu or the\n  `tdlib-types.d.ts` file (the types are annotated with JSDoc comments).\n\nIn the TDLib documentation, the `bytes` type means a **base64-encoded** string.\n`int64` accepts either a number or a string, pass string for large numbers.\n`int32`, `int53`, and `double` are the number JS type.\n\nSee also https://core.telegram.org/tdlib/getting-started for some basic\ninformation on how to use TDLib (tdl handles the authorization part with\n`client.login`). Note that the TDLib JSON interface actually sends a `@type`\nfield, but tdl renames it to `_`.\n\nSome short examples are available in the [examples/](examples/) directory.\n\n\u003c!-- TODO: Perhaps add a guide on how to read the tl schema or similar? --\u003e\n\n[td_api.tl]: https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl\n\n\u003ca name=\"api\"\u003e\u003c/a\u003e\n## API\n\n\u003e [!NOTE]\n\u003e More exhaustive documentation can be found in the\n\u003e [TypeScript declaration file](packages/tdl/index.d.ts).\n\n#### `tdl.configure(options: TDLibConfiguration) =\u003e void`\n\nConfigure several parameters such as libtdjson filename or verbosity level. This\nfunction should be called before `tdl.createClient` or `tdl.execute`. Can be\ncalled multiple times.\n\nThe possible parameters are:\n\n```javascript\ntdl.configure({\n  // Path to the library. By default, it is 'tdjson.dll' on Windows,\n  // 'libtdjson.dylib' on macOS, or 'libtdjson.so' otherwise.\n  tdjson: 'libtdjson.so',\n  // Path to the library directory. Defaults to the empty string.\n  libdir: '/usr/local/lib',\n  // Set the verbosity level of TDLib. Defaults to 1.\n  verbosityLevel: 1,\n  // Advanced options:\n  useOldTdjsonInterface: false,\n  receiveTimeout: 10,\n})\n```\n\nSome examples:\n- `tdl.configure({ tdjson: '/root/libtdjson.so', verbosityLevel: 5 })`\n- `tdl.configure({ libdir: '/usr/local/lib', tdjson: 'libtdjson.dylib.1.8.6' })`\n- `tdl.configure({ libdir: __dirname })` (use libtdjson from the directory of the current script, in CJS)\n- `tdl.configure({ tdjson: require('prebuilt-tdlib').getTdjson() })` (use libtdjson from prebuilt-tdlib)\n\nThe path concatenation of `libdir` + `tdjson` is directly passed to\n[`dlopen`][dlopen] (Unix) or [`LoadLibrary`][LoadLibraryW] (Windows).\n\nThis function must be called before TDLib is initialized, that is, before\nany of `createClient` / `execute` are called.\n\n#### `tdl.createClient(options: ClientOptions) =\u003e Client`\n\nCreate a TDLib client.\n\n```javascript\nconst client = tdl.createClient({\n  apiId: 2222, // Your api_id\n  apiHash: '0123456789abcdef0123456789abcdef' // Your api_hash\n  // ... other options ...\n})\n```\n\n`createClient` accepts options of the following interface:\n\n```typescript\ntype ClientOptions = {\n  apiId: number, // Can be obtained at https://my.telegram.org\n  apiHash: string, // Can be obtained at https://my.telegram.org\n  databaseDirectory?: string, // Path, relative to cwd (defaults to '_td_database')\n  filesDirectory?: string, // Path, relative to cwd (defaults to '_td_files')\n  databaseEncryptionKey?: string, // Optional key for database encryption\n  useTestDc?: boolean, // Use test telegram server (defaults to false)\n  tdlibParameters?: Object, // Raw TDLib parameters\n  skipOldUpdates?: boolean // Advanced option\n}\n```\n\nOf these fields, only `apiId` and `apiHash` are required. Any other field can be\nomitted. They are more thoroughly described in the documentation comments\nof the TypeScript types.\n\nThe `tdlibParameters` option is described in\nhttps://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1tdlib_parameters.html.\n\nBy default, in tdl, `tdlibParameters` is set to:\n\n```javascript\ntdlibParameters: {\n  use_message_database: true,\n  use_secret_chats: false,\n  system_language_code: 'en',\n  application_version: '1.0',\n  device_model: 'Unknown device',\n  system_version: 'Unknown',\n  api_id: options.apiId,\n  api_hash: options.apiHash,\n  database_directory: options.databaseDirectory,\n  files_directory: options.filesDirectory,\n  use_test_dc: options.useTestDc\n}\n```\n\nIn a real application, you likely want to change `device_model` and other\nparameters.\n\n#### `client.login(arg?: LoginDetails | (() =\u003e LoginDetails)) =\u003e Promise\u003cvoid\u003e`\n\nAttach an update handler to log you in to your Telegram account.\n\n```javascript\nawait client.login()\n```\n\nBy default, tdl asks the user for their phone number, auth code, and 2FA\npassword (if needed) on the terminal. You can override the defaults with custom\nfunctions that return promises, for example:\n\n```javascript\n// Example\nawait client.login({\n  async getPhoneNumber(retry) {\n    if (retry) throw new Error('Invalid phone number')\n    return '+9996620001'\n  },\n  async getAuthCode(retry) {\n    if (retry) throw new Error('Invalid auth code')\n    return '22222'\n  },\n  async getPassword(passwordHint, retry) {\n    if (retry) throw new Error('Invalid password')\n    return 'mypassword'\n  },\n  async getName() {\n    return { firstName: 'John', lastName: 'Doe' }\n  }\n})\n```\n\n`getName` is called if the user is not signed up.\n\n`client.login` is a pretty basic function that supports only a subset of\nauthentication methods available on Telegram. It is possible (and advisable for\nlarger apps) not to use the `client.login` helper and implement the\nauthorization process manually, handling `authorizationStateWaitPhoneNumber` and\nother updates.\n\nThis function accepts the following interface:\n\n```typescript\ninterface LoginDetails {\n  getPhoneNumber?: (retry?: boolean) =\u003e Promise\u003cstring\u003e,\n  getEmailAddress?: () =\u003e Promise\u003cstring\u003e,\n  getEmailCode?: () =\u003e Promise\u003cstring\u003e,\n  confirmOnAnotherDevice?: (link: string) =\u003e void,\n  getAuthCode?: (retry?: boolean) =\u003e Promise\u003cstring\u003e,\n  getPassword?: (passwordHint: string, retry?: boolean) =\u003e Promise\u003cstring\u003e,\n  getName?: () =\u003e Promise\u003c{ firstName: string, lastName?: string }\u003e\n}\ndeclare function login(details?: LoginDetails | (() =\u003e LoginDetails)): Promise\u003cvoid\u003e\n```\n\n`getEmailAddress` and `getEmailCode` are called in TDLib \u003e= v1.8.6 only.\n\n#### `client.loginAsBot(token: string | (() =\u003e string | Promise\u003cstring\u003e)) =\u003e Promise\u003cvoid\u003e`\n\nInstead of logging in as a user, you can log in as a bot using a bot token.\n\n```javascript\nawait client.loginAsBot('YOUR_BOT_TOKEN') // Enter your token from @BotFather\n```\n\n#### `client.on(event: string, callback: Function) =\u003e Client`\n\nAttach an event listener. The `'update'` event can be used to iterate through\nreceived updates.\n\n```javascript\nfunction onUpdate (update) {\n  console.log('New update:', update)\n}\nclient.on('update', onUpdate)\nclient.on('error', console.error)\n```\n\nIf an exception is thrown inside your event listener, it is emitted as the\n`'error'` event (other things like invalid client options or potential internal\nerrors can also be emitted as `'error'`). Ideally, you should always have a\nlistener on `client.on('error')`, otherwise an unhandled promise rejection will\nappear.\n\nThe other available event is `'close'`. After `close` (the\n`authorizationStateClosed` update), it isn't possible to send requests and the\nclient should not be used anymore.\n\nYou may consider using reactive libraries like RxJS or most.js for convenient\nevent processing. Since tdl v8.0.0, there's an alternative method to receive\nupdates using async iterators, see `iterUpdates` below.\n\n`client.addListener` is an alias for `client.on`.\n\n#### `client.once(event: string, callback: Function) =\u003e Client`\n\nAttach a one-time listener; otherwise similar to `client.on`.\n\n#### `client.off(event: string, listener: Function) =\u003e boolean`\n\nRemove an event listener.\n\n```javascript\nfunction listener (u) {\n  console.log('New update:', u)\n  if (u?.authorization_state?._ === 'authorizationStateReady')\n    client.off('update', listener) // Removes the listener\n}\nclient.on('update', listener)\n```\n\nThe returned value indicates whether the listener has been successfully removed\nor not.\n\n`client.removeListener` is an alias for `client.off`.\n\n#### `client.iterUpdates() =\u003e AsyncIterableIterator\u003cTd.Update\u003e`\n\nAn alternative approach (added in tdl v8.0.0) to get updates is to use async\niterators instead of `client.on('update', ...)`:\n\n```javascript\nfor await (const update of client.iterUpdates()) {\n  console.log('Received update:', update)\n  if (update._ === 'updateOption' \u0026\u0026 update.name === 'my_id') {\n    console.log(`My ID is ${update.value.value}!`)\n    break\n  }\n}\n```\n\n#### `client.invoke(query: Request) =\u003e Promise\u003cResponse\u003e`\n\nCall a TDLib method asynchronously. If the request fails, the promise rejects\nwith `TDLibError` containing the error code and error message.\n\nFor information regarding the TDLib API list, see the\n[Getting started](#getting-started) section of this README.\n\n```javascript\nconst chats = await client.invoke({\n  _: 'getChats',\n  chat_list: { _: 'chatListMain' },\n  limit: 4000\n})\n```\n\n```javascript\nawait client.invoke({\n  _: 'sendMessage',\n  chat_id: 123456789,\n  input_message_content: {\n    _: 'inputMessageText',\n    text: {\n      _: 'formattedText',\n      text: '👻'\n    }\n  }\n})\n```\n\n#### `client.close() =\u003e Promise\u003cvoid\u003e`\n\nClose the TDLib client.\n\n```javascript\nawait client.close()\n```\n\n#### `tdl.execute(query: Request) =\u003e Td.error | Response`\n\nCall a TDLib method synchronously. This function can be used only with the\nmethods marked as \"can be called synchronously\" in the TDLib documentation.\n\n```javascript\nconst res = tdl.execute({\n  _: 'getTextEntities',\n  text: '@telegram /test_command https://telegram.org telegram.me'\n})\n```\n\n`client.execute` is equivalent to `tdl.execute`.\n\n#### `tdl.setLogMessageCallback(maxVerbosityLevel: number, cb: Function | null) =\u003e void`\n\nSet the callback that is called when a message is added to the TDLib log. This\ncorresponds to the `td_set_log_message_callback` tdjson function. The callback\noverrides the previously set callback.\n\n\u003ca name=\"types\"\u003e\u003c/a\u003e\n## Types\n\n\u003e [!TIP]\n\u003e It is generally significantly more convenient to use tdl with TypeScript,\n\u003e which enables autocompletion along with the documentation for more than 2500\n\u003e TDLib methods and structures.\n\nWhile tdl works with any TDLib version (above the requirement), the TypeScript\ntypes have to be installed specifically for the TDLib version you use. This can\nbe done via a small `tdl-install-types` utility, which downloads and generates\ntypes for you. It can be called using `npx tdl-install-types` without a separate\ninstallation step.\n\n```console\n$ npx tdl-install-types [\u003coptions\u003e] [\u003ctarget\u003e]\n```\n\n(Type \"y\" in case it asks to install the `tdl-install-types` package.)\n\nThis utility can generate types for a given tdjson library file, for the\ninstalled version of prebuilt-tdlib, for a certain TDLib git ref, or for a\ntd_api.tl file. Various examples of using `tdl-install-types`:\n\n```console\n$ npx tdl-install-types prebuilt-tdlib # generate types for the installed prebuilt-tdlib\n$ npx tdl-install-types # similar to the above one, try to install types for prebuilt-tdlib\n$ npx tdl-install-types ./libtdjson.so # generate types for this shared library file in the cwd\n$ npx tdl-install-types 0ada45c3618108a62806ce7d9ab435a18dac1aab # types for this TDLib commit\n$ npx tdl-install-types master # types for this TDLib branch\n$ npx tdl-install-types v1.8.0 # types for the git tag in the TDLib repository\n$ npx tdl-install-types ./td_api.tl # generate types based on the td_api.tl file in the cwd\n```\n\nBy default, the types are generated into a `tdlib-types.d.ts` file that you can\ngit-commit. The declaration file should be inside your project to work. When you\nupdate the version of TDLib, don't forget to also update the types: it's\nimportant to keep the types in sync with the interface TDLib actually uses.\n\nSee `npx tdl-install-types --help` for additional information.\n\nThe types can be imported by using the `tdlib-types` module name:\n\n```typescript\nimport type * as Td from 'tdlib-types'\n// And use as: Td.message, Td.user, ...\n```\n\nThat is, a package named `tdlib-types` does not need to be installed separately.\n\nNote that when using `npx`, the version of `tdl-install-types` might be cached\nand outdated if you are not appending the `@latest` tag\n(`npx tdl-install-types@latest --help`). You can also install the utility\nglobally or per-project as a dev dependency.\n\n[![npm](https://img.shields.io/npm/v/tdl-install-types.svg?label=tdl-install-types)](https://www.npmjs.com/package/tdl-install-types)\n\n\u003ca name=\"other-javascript-runtimes\"\u003e\u003c/a\u003e\n## Other JavaScript runtimes\n\nSince [bun][] is Node.js-compatible and [supports Node-API][bun-napi], tdl\ngenerally works out of the box, however the stability may not be the best yet.\n\n[deno][] can also import tdl through the node compatibility via\n`import * as tdl from 'npm:tdl'`. To use tdl in deno, you must ensure that your\ndeno version is 1.44.2 (2024-06-13) or greater. The Node-API implementation was\nbroken in older deno versions and can easily result in segfaults. There's a\nsmall example in `examples/deno-example.ts`.\n\ntdl depends on native libraries and cannot be used in the browser. TDLib itself,\nhowever, can work in the browser if you compile it to WebAssembly. There is an\noutdated official [tdweb][] library, for example. Previously, tdl implemented\nbasic browser support as well, but the idea has been dropped.\n\n[bun]: https://bun.sh/\n[bun-napi]: https://github.com/oven-sh/bun/issues/158\n[deno]: https://deno.com/\n[tdweb]: https://www.npmjs.com/package/tdweb\n\n\u003ca name=\"troubleshooting\"\u003e\u003c/a\u003e\n## Troubleshooting\n\nSome of the possible errors include:\n\n### \"Dynamic Loading Error\"\n\n- `Dynamic Loading Error: Win32 error 126` (Windows)\n- `Dynamic Loading Error: dlopen(…) image not found` (macOS)\n- `…cannot open shared object file: No such file or directory` (Linux)\n\nThe tdjson shared library or one of its dependencies (for example, libssl)\ncannot be found. To troubleshoot dependency issues, try to run\n`ldd libtdjson.so` on Linux or `otool -L libtdjson.dylib` on macOS. On Windows,\nyou can use an app like Dependency Walker.\n\nCheck the documentation of [dlopen][] (Linux), [dlopen][dlopen-macos] (macOS),\n[Dynamic-Link Library Search Order][dllso] (Windows) to make sure the shared\nlibrary is present in the search paths. By default, Linux does not search in the\ncurrent working directory, while macOS does.\n\nWith `prebuilt-tdlib`, everything should work out of the box (on supported\nplatforms).\n\n[dllso]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications\n[dlopen-macos]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlopen.3.html\n\n[dlopen]: https://www.man7.org/linux/man-pages/man3/dlopen.3.html\n[LoadLibraryW]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw\n\n### \"No such file or directory\"\n\n- `fatal error: napi.h: no such file or directory`\n- `error: no such file or directory: …/node-modules/node-addon-api`\n\nThe path to the directory in which you execute `npm install` likely contains\nspaces, which is not supported by gyp:\nhttps://github.com/nodejs/node-gyp/issues/65#issuecomment-368820565.\n\n### Messages from certain chats are not received or are delayed\n\nThis is likely caused by missing `openChat` calls. Call the `openChat` method\nwith the chat from which you want to receive messages (can be called multiple\ntimes). Also ensure that you are not using a too old version of TDLib. Search\nfor \"openChat\" in TDLib issues for more information.\n\n### \"No native build was found\"\n\n- `No native build was found for platform=…`\n\nA pre-built node addon is not available for your system[^1], and the node addon\nhas not been built from source. The C and C++ compilers, `python3`, `make`\nshould be available on your system to build the tdl's node addon; `npm install`\n(or `npm ci` or similar) should be run to build the addon. Also note that, for\nexample, when building a Docker container, you generally cannot just copy the\nnode modules from the host system.\n\n### \"tdjson is already loaded\"\n\n- `tdjson is already loaded`\n\nIf you use `node:worker_threads`, there are some caveats. tdl with the new\ntdjson interface can be used in only one thread. With the old tdjson interface,\ni.e. `tdl.configure({ useOldTdjsonInterface: true })`, it is possible to\nuse tdl in multiple worker threads, however `tdjson` and `libdir` options of\n`tdl.configure` will be ignored on subsequent tdl initializations. You might\nalso want to set `tdl.configure({ verbosityLevel: 'default' })` so the verbosity\nlevel is set only once. The client should not be shared to other threads.\n\n### OpenSSL incompatibility\n\n- `Error while reading RSA public key`\n\nYou can get this error if libtdjson is dynamically linked against OpenSSL, and\nsome of the symbols got resolved into Node.js instead of the system OpenSSL.\nThis error should not occur if you use `prebuilt-tdlib`.\n\nNote that Node.js also uses OpenSSL (the distributed binaries are statically\nlinked against it) and exports the OpenSSL symbols. In the result, there are\ntwo versions of OpenSSL in the same application. Then, using standard dlopen,\nespecially on Linux, most of the symbols will be resolved into libcrypto\ninside the Node.js binary, not into the system libcrypto. It still can work\ncorrectly if the versions are ABI-compatible, i.e. if TDLib is linked against an\nOpenSSL version sufficiently similar to the version that Node.js uses\n(`node -p \"process.versions.openssl\"`).\n\ntdl tries to get around the symbol conflict issues by using `RTLD_DEEPBIND`\nwhen available, so these issues should be rare in practice (unless you use\nmusl). Additionally, `prebuilt-tdlib` links OpenSSL statically into the binary\nfile.\n\nYou can use `lldb` or `gdb` to check whether the symbols get resolved into\nNode.js. For example, open `lldb -- node index.js` and set these breakpoints:\n\n```\nbreak set -r EVP_ -s node\nbreak set -r AES_ -s node\nbreak set -r BIO_ -s node\nbreak set -r RSA_ -s node\nbreak set -r CRYPTO_ -s node\n```\n\nIt's also possible to set breakpoints inside the system OpenSSL:\n\n```\nbreak set -r . -s libcrypto.so.1.1\nbreak set -r . -s libssl.so.1.1\n```\n\nTo solve this issue, try to link TDLib statically against OpenSSL (the\n`OPENSSL_USE_STATIC_LIBS` option in cmake) or link it against the OpenSSL\nversion that Node.js uses.\n\nAnother possible option is to rebuild Node.js from source, linking it\ndynamically against the same system OpenSSL. That way, there is only one\ninstance of OpenSSL in the application. For example, using [nvm][], you can\ninstall Node.js v18 from source on GNU/Linux via this command:\n\n```console\n$ nvm install -s 18 --shared-openssl --shared-openssl-includes=/usr/include/ --shared-openssl-libpath=/usr/lib/x86_64-linux-gnu/\n```\n\n[nvm]: https://github.com/nvm-sh/nvm\n\nHowever, it's inconvenient for most users to rebuild Node.js.\n\nAnother hypothetical solution is to rebuild TDLib with the OpenSSL headers\ndistributed in Node.js (`\u003cpath-to-node\u003e/include/node/`) without linking it to\nanything, simply leaving the undefined symbols. Using this option, there is also\nonly one OpenSSL. The author hasn't checked that this works or that Node exports\nall the symbols needed for TDLib. With this option, TDLib also should be rebuilt\nevery time Node.js updates the OpenSSL dependency.\n\nThis issue doesn't apply to Electron because it doesn't export OpenSSL symbols.\n\n### Segmentation fault\n\nThe cause of the segfault might be the same as the above one. If tdl crashes\nwith segmentation fault, open an issue.\n\n\u003ca name=\"issue-tracker\"\u003e\u003c/a\u003e\n## Issue tracker\n\nReporting bugs (besides feature requests and other stuff) is very welcome in the\ntdl's GitHub issue tracker. However, while the author can answer some questions\non how to use TDLib itself, they do not know the entirety of TDLib API, and it\nmay be better (and faster to get the response) to ask questions related to TDLib\nspecifics in the `t.me/tdlibchat` group.\n\n---\n\n[🥒](https://github.com/search?q=repo%3Atdlib%2Ftd%20cucumber\u0026type=code)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feilvelia%2Ftdl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feilvelia%2Ftdl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feilvelia%2Ftdl/lists"}