npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sotele-hub

v1.0.1

Published

A comprehensive, single-file TypeScript library for Telegram bot development with socket-like architecture

Readme

# soTeleHub

[![npm version](https://badge.fury.io/js/sotele-hub.svg)](https://badge.fury.io/js/sotele-hub)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)

> A comprehensive, **single-file** TypeScript library for Telegram bot development with socket-like architecture, similar to WhatsApp Baileys.

## ✨ Features

- 🚀 **Socket-like Architecture** - Event-driven design similar to Baileys
- 📘 **Full TypeScript Support** - Complete type definitions 
- 📄 **Single File** - Everything in one file, easy to use
- 🔧 **Zero Dependencies** - No external dependencies required
- 🎯 **Easy to Use** - Simple and intuitive API
- 🔌 **Plugin System** - Extensible architecture
- 💬 **Conversation Flow** - Built-in conversation management
- 🛡️ **Rate Limiting** - Anti-spam protection
- 🔄 **Auto Retry** - Robust error handling
- 📱 **Polling & Webhooks** - Support for both methods

## 🚀 Quick Start

### Installation

```bash
npm install sotele-hub
# or
yarn add sotele-hub

Basic Usage

import { createBot } from 'sotele-hub';

const bot = createBot('YOUR_BOT_TOKEN');

// Handle text messages
bot.on('text', (message) => {
  console.log('Received:', message.text);
  bot.reply(message, 'Hello!');
});

// Handle commands
bot.command('start', (message) => {
  bot.reply(message, 'Welcome to my bot!');
});

// Start polling
bot.startPolling();

Advanced Example

import { createBot, inlineKeyboard } from 'sotele-hub';

const bot = createBot('YOUR_BOT_TOKEN', {
  timeout: 30000,
  retryDelay: 1000,
  maxRetries: 3
});

// Middleware
bot.use(async (update, bot) => {
  console.log('Processing update:', update.update_id);
  return true; // Continue processing
});

// Inline keyboards
bot.command('keyboard', (message) => {
  const keyboard = inlineKeyboard()
    .text('Button 1', 'btn1')
    .text('Button 2', 'btn2')
    .row()
    .url('Website', 'https://example.com')
    .build();
  
  bot.replyWithKeyboard(message, 'Choose:', keyboard);
});

// Callback queries
bot.on('callback_query', (query) => {
  bot.answerCallbackQuery({
    callback_query_id: query.id,
    text: `You clicked: ${query.data}`
  });
});

// Sessions
bot.command('count', (message) => {
  const session = bot.getSession(message.chat.id);
  session.count = (session.count || 0) + 1;
  bot.setSession(message.chat.id, session);
  
  bot.reply(message, `Count: ${session.count}`);
});

// Conversations
bot.command('ask', (message) => {
  bot.reply(message, 'What is your name?');
  
  bot.startConversation(message.chat.id, async (msg, bot) => {
    await bot.reply(msg, `Nice to meet you, ${msg.text}!`);
    return 'end';
  });
});

bot.startPolling();

📖 API Reference

Core Methods

Bot Creation

import { createBot, SoTeleHub } from 'sotele-hub';

const bot = createBot(token: string, options?: BotConfig);
// or
const bot = new SoTeleHub({ token, ...options });

Messaging

// Send messages
await bot.sendMessage({ chat_id, text });
await bot.sendPhoto({ chat_id, photo });
await bot.sendDocument({ chat_id, document });

// Reply helpers
await bot.reply(message, 'Hello!');
await bot.replyWithPhoto(message, photo);
await bot.replyWithKeyboard(message, text, keyboard);

Events

// Message events
bot.on('text', (message) => {});
bot.on('photo', (message) => {});
bot.on('callback_query', (query) => {});

// Commands
bot.command('start', (message) => {});
bot.onText(/\/echo (.+)/, (message, match) => {});

Keyboards

import { inlineKeyboard, replyKeyboard } from 'sotele-hub';

// Inline keyboard
const inline = inlineKeyboard()
  .text('Button', 'data')
  .url('Link', 'https://example.com')
  .build();

// Reply keyboard
const reply = replyKeyboard()
  .text('Home')
  .requestLocation('📍 Location')
  .resize()
  .build();

Sessions & Conversations

// Sessions
const session = bot.getSession(chatId);
bot.setSession(chatId, data);
bot.clearSession(chatId);

// Conversations
bot.startConversation(chatId, handler);
bot.endConversation(chatId);

🔌 Plugin System

// Create custom plugin
const myPlugin = {
  install(bot) {
    bot.use(async (update) => {
      // Custom logic
      return true;
    });
  }
};

bot.addPlugin('myPlugin', myPlugin);

🛠️ Utilities

import { 
  escapeMarkdown, 
  escapeHTML, 
  mention, 
  formatDuration,
  validateToken 
} from 'sotele-hub';

const escaped = escapeMarkdown('Hello *world*!');
const userMention = mention(user, 'HTML');
const isValid = validateToken(token);

📱 Webhook Support

const express = require('express');
const { createBot } = require('sotele-hub');

const app = express();
const bot = createBot(process.env.BOT_TOKEN);

app.use(express.json());

app.post('/webhook', (req, res) => {
  bot.emit('update', req.body);
  res.sendStatus(200);
});

// Set webhook
await bot.setWebhook({ url: 'https://yourdomain.com/webhook' });

app.listen(3000);

🔧 Configuration

interface BotConfig {
  token: string;
  baseUrl?: string;          // Default: 'https://api.telegram.org'
  timeout?: number;          // Default: 30000
  retryDelay?: number;       // Default: 1000
  maxRetries?: number;       // Default: 3
  allowedUpdates?: string[]; // Default: []
}

📝 Examples

Check out the examples/ folder for more comprehensive examples:

  • basic-bot.js - Simple echo bot
  • advanced-bot.js - Bot with keyboards and sessions
  • typescript-bot.ts - TypeScript example with full typing

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT © Your Name

🆚 Comparison with Other Libraries

| Feature | soTeleHub | node-telegram-bot-api | telegraf | |---------|-----------|----------------------|----------| | TypeScript | ✅ Full support | ❌ Community types | ✅ Built-in | | Single File | ✅ Yes | ❌ No | ❌ No | | Socket-like | ✅ Yes | ❌ No | ❌ No | | Zero Deps | ✅ Yes | ❌ No | ❌ No | | Size | 🟢 Small | 🟡 Medium | 🔴 Large | | Learning Curve | 🟢 Easy | 🟡 Medium | 🔴 Hard |

🚀 Why soTeleHub?

  1. Single File: Everything you need in one file - no complex folder structures
  2. Socket-like: Familiar event-driven architecture like Baileys for WhatsApp
  3. TypeScript First: Built with TypeScript, full type safety out of the box
  4. Zero Dependencies: No external dependencies, smaller bundle size
  5. Comprehensive: All Telegram Bot API features covered
  6. Easy Migration: Simple to migrate from other libraries

Made with ❤️ by developers, for developers.


## 🔨 scripts/build-esm.js

```javascript
const fs = require('fs');
const path = require('path');

// Convert CJS to ESM
function convertToESM(dir) {
  if (!fs.existsSync(dir)) return;
  
  const files = fs.readdirSync(dir);
  
  files.forEach(file => {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);
    
    if (stat.isDirectory()) {
      convertToESM(filePath);
    } else if (file.endsWith('.js')) {
      let content = fs.readFileSync(filePath, 'utf8');
      
      // Convert exports
      content = content.replace(/exports\./g, 'export ');
      content = content.replace(/module\.exports\s*=\s*/g, 'export default ');
      
      // Convert require statements
      content = content.replace(
        /const\s+(.+?)\s+=\s+require\(['"](.+?)['"]\)/g,
        'import $1 from "$2"'
      );
      
      // Rename to .esm.js
      const esmPath = filePath.replace('.js', '.esm.js');
      fs.writeFileSync(esmPath, content);
      fs.unlinkSync(filePath);
    }
  });
}

// Create ESM build
convertToESM('dist/esm');

// Create package.json for ESM
const esmPackage = { type: 'module' };
fs.writeFileSync('dist/esm/package.json', JSON.stringify(esmPackage, null, 2));

console.log('✅ ESM build created successfully');

📄 examples/basic-bot.js

const { createBot } = require('sotele-hub');

const bot = createBot(process.env.BOT_TOKEN);

// Basic echo bot
bot.on('text', (message) => {
  if (!message.text.startsWith('/')) {
    bot.reply(message, `You said: ${message.text}`);
  }
});

bot.command('start', (message) => {
  bot.reply(message, '👋 Hello! Send me any message and I will echo it back.');
});

bot.command('help', (message) => {
  const helpText = `
🤖 **Bot Commands:**

/start - Start the bot
/help - Show this help
/ping - Check if bot is alive
/info - Show your info

Just send me any text and I'll echo it back!
  `;
  bot.reply(message, helpText);
});

bot.command('ping', (message) => {
  bot.reply(message, '🏓 Pong! Bot is alive and working.');
});

bot.command('info', (message) => {
  const info = `
👤 **Your Information:**
• Name: ${message.from.first_name} ${message.from.last_name || ''}
• Username: ${message.from.username ? '@' + message.from.username : 'None'}
• ID: \`${message.from.id}\`
• Chat Type: ${message.chat.type}
  `;
  bot.reply(message, info);
});

// Start the bot
bot.startPolling()
  .then(() => {
    console.log('✅ Bot started successfully!');
  })
  .catch((error) => {
    console.error('❌ Failed to start bot:', error);
  });

📄 examples/advanced-bot.js

const { createBot, inlineKeyboard, replyKeyboard } = require('sotele-hub');

const bot = createBot(process.env.BOT_TOKEN, {
  timeout: 30000,
  retryDelay: 1000
});

// Middleware for logging
bot.use(async (update) => {
  console.log(`📩 Update ${update.update_id} received`);
  return true;
});

// Start command with reply keyboard
bot.command('start', (message) => {
  const keyboard = replyKeyboard()
    .text('📊 Stats').text('⚙️ Settings')
    .row()
    .text('🎮 Games').text('❓ Help')
    .resize()
    .build();

  bot.replyWithKeyboard(message, '🎉 Welcome! Choose an option:', keyboard);
});

// Handle reply keyboard responses
bot.on('text', (message) => {
  if (message.text && !message.text.startsWith('/')) {
    switch (message.text) {
      case '📊 Stats':
        bot.reply(message, '📈 Your stats: Messages sent: 42, Commands used: 15');
        break;
      case '⚙️ Settings':
        showSettings(message);
        break;
      case '🎮 Games':
        showGames(message);
        break;
      case '❓ Help':
        bot.reply(message, '💡 Use the keyboard buttons or type /help for commands.');
        break;
    }
  }
});

// Settings with inline keyboard
function showSettings(message) {
  const keyboard = inlineKeyboard()
    .text('🔔 Notifications', 'setting_notifications')
    .text('🌙 Theme', 'setting_theme')
    .row()
    .text('🌐 Language', 'setting_language')
    .text('🔒 Privacy', 'setting_privacy')
    .row()
    .text('« Back to Menu', 'back_menu')
    .build();

  bot.replyWithKeyboard(message, '⚙️ Settings Panel:', keyboard);
}

// Games menu
function showGames(message) {
  const keyboard = inlineKeyboard()
    .text('🎲 Dice', 'game_dice')
    .text('🎯 Darts', 'game_darts')
    .row()
    .text('🏀 Basketball', 'game_basketball')
    .text('⚽ Football', 'game_football')
    .row()
    .text('« Back to Menu', 'back_menu')
    .build();

  bot.replyWithKeyboard(message, '🎮 Choose a game:', keyboard);
}

// Handle callback queries
bot.on('callback_query', (query) => {
  const data = query.data;

  bot.answerCallbackQuery({
    callback_query_id: query.id,
    text: `Selected: ${data.replace('_', ' ')}`
  });

  switch (data) {
    case 'setting_notifications':
      bot.sendMessage({
        chat_id: query.message.chat.id,
        text: '🔔 Notifications are currently: ON\nToggle with /notifications'
      });
      break;

    case 'game_dice':
      bot.sendDice({ chat_id: query.message.chat.id, emoji: '🎲' });
      break;

    case 'game_darts':
      bot.sendDice({ chat_id: query.message.chat.id, emoji: '🎯' });
      break;

    case 'back_menu':
      bot.command('start', query.message);
      break;
  }
});

// Session-based counter
bot.command('count', (message) => {
  const session = bot.getSession(message.chat.id);
  session.count = (session.count || 0) + 1;
  bot.setSession(message.chat.id, session);
  
  bot.reply(message, `🔢 Counter: ${session.count}\nUse /reset to reset counter.`);
});

bot.command('reset', (message) => {
  bot.clearSession(message.chat.id);
  bot.reply(message, '🔄 Counter reset to 0!');
});

// Conversation example
bot.command('feedback', (message) => {
  bot.reply(message, '💬 Please send your feedback message:');
  
  bot.startConversation(message.chat.id, async (msg, bot) => {
    const feedback = msg.text;
    
    // Save feedback (in real app, save to database)
    console.log(`Feedback from ${msg.from.first_name}: ${feedback}`);
    
    await bot.reply(msg, '✅ Thank you for your feedback! It has been recorded.');
    return 'end';
  });
});

// Error handling
bot.on('polling_error', (error) => {
  console.error('❌ Polling error:', error);
});

// Start the bot
bot.startPolling()
  .then(() => {
    console.log('🚀 Advanced bot started successfully!');
  })
  .catch(console.error);

🚀 Quick Setup Commands

# Create project
mkdir my-telegram-bot && cd my-telegram-bot

# Initialize npm
npm init -y

# Install dependencies
npm install typescript ts-node @types/node --save-dev
npm install rimraf prettier eslint --save-dev

# Install soTeleHub (after publishing)
npm install sotele-hub

# Create bot file
echo "import { createBot } from 'sotele-hub';

const bot = createBot(process.env.BOT_TOKEN!);

bot.command('start', (message) => {
  bot.reply(message, 'Hello from soTeleHub! 🚀');
});

bot.startPolling().then(() => {
  console.log('Bot started!');
});" > bot.ts

# Add to package.json scripts
npm pkg set scripts.dev="ts-node bot.ts"
npm pkg set scripts.build="tsc"

# Set bot token and run
export BOT_TOKEN="your_bot_token_here"
npm run dev

Perfect! Sekarang soTeleHub sudah menjadi single file library yang mudah digunakan dan siap untuk dipublish ke NPM! 🎉

🎯 Keunggulan Single File Version:

  1. ✅ Satu File Aja - Semua dalam src/index.ts, mudah maintain
  2. ✅ Zero Dependencies - Tidak butuh dependency external
  3. ✅ TypeScript Native - Full type support
  4. ✅ Socket-like Architecture - Mirip Baileys
  5. ✅ Comprehensive - Semua fitur Telegram Bot API
  6. ✅ Easy Setup - Tinggal npm install sotele-hub

🚀 Cara Publish:

# Setup project
mkdir sotele-hub && cd sotele-hub
# Copy all files above

# Install dev dependencies
npm install

# Build
npm run build

# Test locally
npm pack

# Publish to NPM
npm login
npm publish --access public

Setelah publish, developer bisa langsung pakai:

npm install sotele-hub
const { createBot } = require('sotele-hub');
const bot = createBot('TOKEN');
bot.command('start', msg => bot.reply(msg, 'Hello!'));
bot.startPolling();