{"id":22514971,"url":"https://github.com/en9inerd/telebuilder","last_synced_at":"2025-08-03T16:31:30.732Z","repository":{"id":65525088,"uuid":"509606082","full_name":"en9inerd/telebuilder","owner":"en9inerd","description":"Simple Telegram bot framework based on GramJS","archived":false,"fork":false,"pushed_at":"2024-10-24T19:14:50.000Z","size":747,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-28T09:07:28.394Z","etag":null,"topics":["bot","gramjs","javascript","nodejs","telegram","telegram-api","telegram-bot","typescript"],"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/en9inerd.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":"2022-07-01T22:45:53.000Z","updated_at":"2024-10-24T19:14:53.000Z","dependencies_parsed_at":"2024-04-22T03:32:55.038Z","dependency_job_id":"453ab4ca-3d15-4c44-a29c-0bfcc1df8ff1","html_url":"https://github.com/en9inerd/telebuilder","commit_stats":{"total_commits":108,"total_committers":2,"mean_commits":54.0,"dds":"0.31481481481481477","last_synced_commit":"adf44e2b82846b70fe295dbe89f65c41df569c63"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/en9inerd%2Ftelebuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/en9inerd%2Ftelebuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/en9inerd%2Ftelebuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/en9inerd%2Ftelebuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/en9inerd","download_url":"https://codeload.github.com/en9inerd/telebuilder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228556191,"owners_count":17936433,"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":["bot","gramjs","javascript","nodejs","telegram","telegram-api","telegram-bot","typescript"],"created_at":"2024-12-07T03:27:12.467Z","updated_at":"2024-12-07T03:27:13.112Z","avatar_url":"https://github.com/en9inerd.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TeleBuilder\n\n[![npm version](https://badge.fury.io/js/telebuilder.svg)](https://badge.fury.io/js/telebuilder)\n\nTeleBuilder is a simple Telegram bot framework for building command message-centric Telegram bots in TypeScript/JavaScript. It's built on top of GramJS, allowing you to create bots and userbots with more features and fewer limitations than using frameworks based on Telegram Bot API.\n\n**Note**: TeleBuilder is still in early development and is primarily used for personal bot projects. Please report any bugs or suggest improvements.\n\n## Features\n\n- **Command-Centric Design**: Define and manage bot commands easily with a clear and concise interface.\n- **Command Locking**: Prevent a command from running while another command is in progress.\n- **Easily Configurable Command Scopes**: Limit command execution to specific users, chats, or peers.\n- **Command Config Caching**: Store current command configuration on disk for updates and restarts.\n- **Lightweight configuration management**: Load and manage configuration settings for your bot like node-config.\n\n## Installation\n\n```bash\nnpm install telebuilder\n```\n\n## Usage\n\nExample of a bot built with TeleBuilder: [zola-post-bot](https://github.com/en9inerd/zola-post-bot)\n\n### Configuration\n\nTeleBuilder uses a `ConfigService` to manage and load configuration settings for your bot. The service loads configuration files based on your environment and merges them to create a final, read-only configuration object that your application can use.\n\n#### Setting Up Configuration\n\nThe configuration files are located in the `config` directory of your project. By default, the service looks for a `default.js` configuration file, and if an environment variable `NODE_ENV` is set, it will also look for a configuration file named after the environment (e.g., `development.js`, `production.js`).\n\n#### Example Default Configuration\n\nHere is an example of what your default configuration file might look like:\n\n```typescript\n// config/default.js\nimport { readFile } from 'node:fs/promises';\n\n// App version\nconst version = JSON.parse(await readFile(new URL('../package.json', import.meta.url))).version;\n\nexport default {\n  botConfig: {\n    botDataDir: process.env.TG_BOT_DATA_DIR || './botData',\n    apiId: Number.parseInt(process.env.TG_BOT_API_ID),\n    apiHash: process.env.TG_BOT_API_HASH,\n    token: process.env.TG_BOT_TOKEN,\n    appVersion: process.env.TG_BOT_APP_VERSION || version,\n  }\n};\n```\n\n#### Accessing Configuration Values\n\nTo access the configuration values in your application, use the `config.get()` method. You can provide a key path as a string to access nested properties. For example:\n\n```typescript\nimport { config } from 'telebuilder/config';\n\nconst apiId = config.get\u003cnumber\u003e('botConfig.apiId');\nconst apiHash = config.get\u003cstring\u003e('botConfig.apiHash');\nconst token = config.get\u003cstring\u003e('botConfig.token');\n```\n\nFor more details on setting up and managing configurations, refer to the [configuration file](./config/default.js) in the project repository.\n\n### Creating a Bot\n\nEntry module for your bot application. This is where you define your bot and its commands.\nHere’s a basic example of how to create and initialize your bot:\n\n```typescript\n#!/usr/bin/env node\nimport { TelegramBotClient } from 'telebuilder';\nimport { StartCommand } from './commands/start.command.js';\n\nconst client = new TelegramBotClient({\n  commands: [\n    StartCommand,\n  ]\n});\n\nawait client.init();\n```\n\n### Defining Commands\n\nEach command is a class that implements the `Command` interface and is decorated with the `@command` decorator.\nThere are required properties and methods that you need to implement in your command class:\n- `command`: The command name that triggers the command.\n- `description`: A brief description of what the command does.\n- `scopes`: An array of `CommandScope` objects that define where the command and by whom it can be executed.\n- `langCodes`: An array of language codes for which the command is available.\n- `entryHandler`: The method that is called when the command is executed.\n\nHere is an example of a command class:\n\n```typescript\n@command\nexport class StartCommand implements Command {\n  command = 'start';\n  description = 'Start the bot';\n  scopes: CommandScope[] = [\n    {\n      name: 'Peer',\n      peer: channelAuthor\n    },\n  ];\n  langCodes = [];\n\n  @handler({\n    event: {\n      fromUsers: [channelAuthor],\n    }\n  })\n  public async entryHandler(event: NewMessageEvent): Promise\u003cvoid\u003e {\n    if (!event.client || !event?.message?.senderId) return;\n  }\n}\n```\n\n### Event/Update Handlers\n\nEvent handlers are methods that are called when a specific event occurs. You can define event handlers for different types of events, such as new messages, edited messages, callback queries and other events supported by GramJS.\nTo define an event handler, use the `@handler` decorator and provide the event type and any additional options that you want to apply to the handler. `@handler` decorator isn't required for command entry handlers.\nExample of an event handler:\n\n```typescript\n  @handler({\n    type: 'album',\n    event: {\n      chats: [channelId],\n      incoming: true,\n      outgoing: false,\n    },\n    validateCommandParams: false,\n    lock: false\n  })\n  @catchError()\n  public async getNewAlbum(event: AlbumEvent): Promise\u003cvoid\u003e {\n    // prevent edited messages from being processed\n    if (event.messages.length === 1 || !event?.client) return;\n\n    // process the album;\n  }\n```\n\n### Command Parameters\n\nCommands can take parameters that are passed by the user when executing the command like `/command param1=value1 param2=value2`.\n\nYou can define parameters for your commands using the `@params` decorator. The `@params` decorator takes an object that defines the parameters for the command. Each parameter is defined by a key-value pair where the key is the parameter name and the value is an object that defines the parameter schema. At the moment, the supported parameter types are `string`, `number`, `boolean`, and `enum`.\n\nHere is an example of how to define parameters for a command:\n\n```typescript\n  @params params: CommandParamsSchema = {\n    param1: {\n      type: 'string',\n      required: true,\n      default: '',\n    },\n    param2: {\n      type: 'number',\n      required: false,\n      default: 0,\n    },\n    param3: {\n      type: 'enum',\n      enamValues: ['value1', 'value2', 'value3'],\n      required: false,\n    },\n  };\n```\n\n### Button Menus\n\nTeleBuilder allows you to define interactive button menus using the @buttonsReg decorator.\n\n#### Defining Button Menus\n\nTo create button menus within a command class:\n\n1. **Define Button Fields**: Add class fields representing button layouts using `Buttons` type. Each button is typically created with `Button.inline`, specifying the display text and callback data.\n2. **Apply the `@buttonsReg` Decorator**: Decorate these fields with `@buttonsReg`. This decorator performs validation and preprocessing to ensure that each button's callback data is correctly linked to a handler method within the class.\n\n#### How `@buttonsReg` Works\n\nThe `@buttonsReg` decorator performs the following actions:\n\n- **Validation**: It checks that each button's callback data corresponds to an existing callback query handler method in the class. If a matching handler is not found, it throws a `DecoratorException`.\n- **Data Prefixing**: It prefixes the callback data of each button with the class name followed by a colon (`:`). This namespacing helps avoid conflicts between handlers in different classes.\n- **Handler Linking**: Ensures that the prefixed callback data matches the handler methods, facilitating correct event routing.\n\n#### Implementing Button Menus in a command class\n\nHere’s a brief example:\n\n```typescript\n@command\nexport class SessionCommand implements Command {\n  @buttonsReg woSessionButtons: Buttons = [\n    [Button.inline('Create session', Buffer.from('createSession'))]\n  ];\n\n  @handler({ type: HandlerTypes.CallbackQuery })\n  public async createSession(event: CallbackQueryEvent) {\n    // Handler implementation...\n  }\n}\n```\n\nFull example of a command class with button: [session.command.ts](https://raw.githubusercontent.com/en9inerd/gromozeka-bot/master/src/commands/session.command.ts)\n\n#### Key Points to Remember\n\n- **Callback Data Consistency**: The callback data specified in `Button.inline` (e.g., `'createSession'`) must exactly match the corresponding handler method name (`createSession`) in the class. The `@buttonsReg` decorator prefixes the callback data with the class name, so ensure handler methods are correctly named without the prefix.\n- **Decorator Responsibilities**: The `@buttonsReg` decorator ensures that:\n  - Every button has a corresponding handler method.\n  - Callback data is appropriately namespaced to prevent conflicts.\n  - Any mismatch between buttons and handlers results in a clear exception, aiding in debugging.\n- **Error Handling**: If a button's callback data does not match any handler method within the class, a `DecoratorException` is thrown, indicating the specific issue for easy resolution.\n\n### Dependency Injection\n\nTeleBuilder provides a straightforward way to manage dependencies through the use of the `@injectable` and `@inject` decorators. This system ensures that services are automatically registered and resolved within the framework’s internal container.\n\n- `@injectable`: Marks a class as a service that can be injected.\n- `@inject`: Injects the dependency into a class where it is needed.\n\nHere’s an example of how to set this up:\n\n```typescript\n@injectable\nexport class MyService {\n  public doSomething(): void {\n    console.log('Service is doing something.');\n  }\n}\n\nexport class MyComponent {\n  @inject(MyService)\n  private readonly myService!: MyService;\n\n  public performAction(): void {\n    this.myService.doSomething();\n  }\n}\n```\n\n### Error Handling\n\nTeleBuilder includes a `@catchError` decorator to help manage errors in your event handlers gracefully. By using this decorator, you can define a custom error handler that will be invoked if an error occurs during the execution of the handler.\n\nExample of error handling in a command handler:\n\n```typescript\n@catchError(async (error) =\u003e {\n  // Custom error handling logic...\n  console.error('Custom Error:', error.message);\n})\npublic async myMethod() {\n  // Method logic that might throw an error...\n}\n```\n\n### Access to Client object\n\nYou can access the underlying `TelegramClient` instance provided by GramJS using the `@client` decorator or the `getClient()` function from `telebuilder/states`.\n\nThis is useful when you need to perform operations that require direct access to the Telegram client, such as sending messages, handling events, and interacting with the Telegram API.\n\n```typescript\n@client\nprivate readonly client!: TelegramClient;\n\n//or\n\nimport { getClient } from 'telebuilder/states';\n\nconst client = getClient();\n```\n\n## License\n\nTeleBuilder is licensed under the MIT License. See [LICENSE](./LICENSE) for more information.\n\n## Contributing\n\nIf you have any suggestions or improvements, feel free to open an issue or submit a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fen9inerd%2Ftelebuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fen9inerd%2Ftelebuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fen9inerd%2Ftelebuilder/lists"}