A high-performance, plugin-based Telegram Bot framework built with Node.js. TeleNode provides a robust foundation for building scalable Telegram bots with advanced monitoring, caching, and plugin management capabilities.
- Plugin-Based Architecture: Modular design for easy extension and customization
- High Performance: Built-in caching and performance monitoring
- Advanced Monitoring: Real-time health checks and performance metrics
- Hot Plugin Management: Load, unload, and reload plugins without restarting
- Role-Based Access Control: Granular permission system (User/Admin/Root levels)
- Rate Limiting: Built-in protection against spam and abuse
- Database Integration: MySQL support with connection pooling
- Marketplace Support: Plugin marketplace for easy discovery and installation
- Process Management: PM2 integration for production deployment
- Webhook & Polling: Flexible update modes for different deployment scenarios
- Node.js 16.0.0 or higher
- MySQL 5.7 or higher
- npm 8.0.0 or higher
-
Clone the repository
git clone https://github.com/yourusername/telenode.git cd telenode -
Install dependencies
npm install
-
Configure environment
cp .env.example .env npm run setup env
-
Setup database
npm run setup db
-
Start the bot
npm start
| Variable | Description | Default | Required |
|---|---|---|---|
APP_NAME |
Application name | TeleNode | β |
APP_ENV |
Application environment | local | β |
LOG_LEVEL |
Logging level (error,warn,info,etc.) | error | - |
LOG_CHANNEL |
Log channel (stack,daily,console) | stack | - |
BOT_TOKEN |
Telegram Bot API token | - | β |
BOT_SUDOERS |
Comma-separated list of root user IDs | - | β |
DB_HOST |
MySQL database host | localhost | β |
DB_PORT |
MySQL database port | 3306 | β |
DB_DATABASE |
Database name | - | β |
DB_USER |
Database username | - | β |
DB_PASSWORD |
Database password | - | β |
UPDATE_MODE |
Bot update mode (polling/webhook) | polling | - |
WEBHOOK_URL |
Webhook URL for webhook mode | - | - |
APP_PORT |
Application port | 8001 | β |
USE_PLUGIN_MARKETPLACE |
Enable plugin marketplace | True | - |
Run the interactive configuration wizard:
npm run setup envThis will guide you through setting up all required configuration values.
plugins/
βββ my-plugin/
β βββ index.js # Main plugin file
β βββ package.json # Plugin metadata
β βββ README.md # Plugin documentation
βββ ...
Use the CLI tool to generate a new plugin:
npm run plugin:create my-plugin -- --description "My awesome plugin"-d, --description <desc>: Plugin description-a, --author <author>: Plugin author-v, --visibility <USER|ADMIN|ROOT>: Plugin visibility (default: USER)-t, --type <NORMAL|PROXY>: Plugin type (default: NORMAL)-c, --category <category>: Plugin category (default: general)-h, --help-text <help>: Custom help text--deps <deps>: Comma-separated dependencies (package@version)
import Plugin from "../../src/plugin.js";
/**
* MyPlugin
* A sample plugin
*/
export default class MyPlugin extends Plugin {
/**
* Plugin commands
*/
get commands() {
return {
hello: this.sayHello.bind(this)
};
}
/**
* Say hello command handler
*/
async sayHello({message, args}) {
return `Hello, ${message.from.first_name}!`;
}
// Event handlers
async onText({message}) {
if (message.text.includes("ping")) {
return "pong";
}
}
}{
"name": "my-plugin",
"version": "1.0.0",
"description": "A sample plugin",
"author": "Your Name",
"plugin": {
"displayName": "MyPlugin",
"visibility": "USER",
"type": "NORMAL",
"help": "`/hello` - Say hello"
}
}name: Plugin identifier (unique)version: Plugin versiondescription: Short descriptionauthor: Author nameplugin.displayName: Display nameplugin.visibility:USER,ADMIN, orROOTplugin.type:NORMALorPROXYplugin.help: Help text
"USER"- Accessible to all users"ADMIN"- Accessible to admins and root users"ROOT"- Accessible only to root users
// Message events
onMessage, onText, onPhoto, onVideo, onAudio, onDocument, onVoice, onSticker
// Chat events
onNewChatMembers, onLeftChatMember, onNewChatTitle, onNewChatPhoto
// Interactive events
onCallbackQuery, onInlineQuery, onChosenInlineResult
// ...see docs/PLUGIN_DEVELOPMENT.md for full listCommands can return:
// Simple text
return "Hello World";
// Typed response
return {
type: "photo",
photo: "https://example.com/image.jpg",
options: { caption: "A beautiful image" }
};
// Status action
return {
type: "chatAction",
action: "typing"
};- Use built-in logger for debug/info/error logs.
- Handle errors gracefully in plugin handlers.
- Use try/catch for async operations.
TeleNode provides built-in configuration management for plugins with database persistence and caching.
// Get configuration with default value
const apiKey = await this.getConfig('api_key', 'default_key');
// Get configuration with cache refresh
const setting = await this.getConfig('setting', null, true);// Set configuration value
await this.setConfig('api_key', 'your_api_key');
// Set with additional options
await this.setConfig('setting', 'value', {
description: 'Custom setting description',
createdBy: 'admin'
});// Check if configuration exists
const exists = await this.configExists('api_key');
// Delete configuration
await this.deleteConfig('old_setting');
// Get all plugin configurations
const allConfigs = await this.getAllConfigs();
// Clear configuration cache
this.clearConfigCache('specific_key'); // Clear specific key
this.clearConfigCache(); // Clear all plugin configsexport default class WeatherPlugin extends Plugin {
get commands() {
return {
weather: this.getWeather.bind(this),
setapikey: this.setApiKey.bind(this)
};
}
async getWeather({message, args}) {
const apiKey = await this.getConfig('api_key');
if (!apiKey) {
return "Please set API key first: /setapikey YOUR_KEY";
}
const city = args.join(" ");
// Use apiKey for weather API call
return `Weather for ${city}: Sunny, 25Β°C`;
}
async setApiKey({message, args}) {
const apiKey = args[0];
if (!apiKey) {
return "Usage: /setapikey YOUR_API_KEY";
}
await this.setConfig('api_key', apiKey, {
description: 'Weather API key',
createdBy: message.from.id
});
return "β
API key saved successfully!";
}
}npm run plugin:create <name>
npm run plugin:install [plugin-name]
npm run plugin:check [plugin-name]
npm run plugin:list
npm run plugin:remove <name>Master plugin commands:
/plugins- List loaded plugins/plugin reload- Reload all plugins/plugin reload [plugin]- Reload plugin/plugin install [plugin]- Install a plugin from the marketplace/su- System management panel
Built-in monitoring:
/status # System status
/health # Health check
/cache # Cache statisticsGET /health- Application health statusGET /metrics- Performance metrics (if enabled)
npm run pm2:start
npm run pm2:logs
npm run pm2:restartExample Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8001
CMD ["npm", "start"]- Never commit
.envfiles - Use environment-specific configs
- Secure bot token and DB credentials
- Enable rate limiting in production
Access via:
/marketplaceFeatures:
- Browse plugins
- Install/update plugins
- Manage installed plugins
import Plugin from "../../src/plugin.js";
class Echo extends Plugin {
get commands() {
return {
echo: ({args}) => args.join(" ") || "Nothing to echo"
};
}
}
export default Echo;import Plugin from "../../src/plugin.js";
class Weather extends Plugin {
get commands() {
return {
weather: this.getWeather.bind(this)
};
}
async getWeather({message, args}) {
const city = args.join(" ");
if (!city) {
return "Please provide a city name. Usage: /weather <city>";
}
// Integrate weather API here
return `Weather for ${city}: Sunny, 25Β°C`;
}
}
export default Weather;- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
git clone https://github.com/uziins/telenode.git
cd telenode
npm install
npm run dev- Use ESLint
- Follow code patterns
- Add JSDoc for public APIs
- Write tests for new features
MIT License - see LICENSE for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions