Skip to content

cloudkuimages/cocoa-chan-telegram

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🍫 COCOA CHAN MD

Telegram Bot Edition - Free Version

Cocoa Chan MD

Node.js Version Telegram Bot JavaScript License

✨ Modern Telegram Bot Framework with Plugin System ✨

Telegram Channel Telegram Group Developer


🌟 Features

  • πŸ”§ Plugin System - Modular architecture with hot-reload
  • πŸ”„ Auto Reload - Automatic plugin reloading on file changes
  • πŸ“± Media Support - Send photos, videos, and documents easily
  • ⚑ Fast Performance - Built with modern Node.js v22+
  • 🎨 Beautiful UI - Colorful console output with gradient effects
  • πŸ“ Easy Configuration - Simple config-based setup
  • πŸ›‘οΈ Error Handling - Robust error management system

πŸ“‹ Requirements

  • Node.js v22 or higher (Required)
  • Telegram Bot Token (Get from @BotFather)
  • NPM or Yarn package manager

πŸš€ Quick Start

1. Clone Repository

git clone https://github.com/cloudkuimages/cocoa-chan-telegram.git
cd cocoa-chan-telegram

2. Install Dependencies

npm install
# or
yarn install

3. Configure Bot

Create config.js file:

export default {
  telegramBotToken: 'YOUR_BOT_TOKEN_HERE'
}

4. Run Bot

npm start
# or
node index.js

πŸ“ Project Structure

cocoa-chan-md/
β”œβ”€β”€ πŸ“„ index.js          # Main bot file
β”œβ”€β”€ βš™οΈ config.js         # Configuration
β”œβ”€β”€ πŸ“‚ plugins/          # Plugin directory
β”‚   β”œβ”€β”€ πŸ”Œ example.js    # Example plugin
β”‚   └── πŸ”Œ ...           # More plugins
β”œβ”€β”€ πŸ“‹ package.json      # Dependencies
└── πŸ“– README.md         # This file

πŸ”Œ Plugin Development

Create a new plugin in the plugins/ directory:

// plugins/start.js
import fs from 'fs/promises'
import path from 'path'
import { fileURLToPath } from 'url'
import moment from 'moment-timezone'
import config from '../config.js'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const pluginsDir = path.join(__dirname)

const COMMANDS_PER_PAGE = 10
const MAX_MESSAGE_LENGTH = 3500

let handler = async ({ conn, m }) => {
  const name = m.from?.first_name || 'Pengguna'
  const userId = m.from?.id
  const isOwner = config.owner.includes(userId)
  const role = isOwner ? 'Owner' : 'User'
  const waktu = moment().tz('Asia/Jakarta').format('dddd, DD MMMM YYYY HH:mm:ss')
  
  const args = m.text?.split(' ') || []
  const currentPage = parseInt(args[1]) || 1
  
  const groups = await loadCommands()
  if (!groups) {
    return conn.sendMessage(m.chat.id, 'Gagal membaca daftar plugin.', {
      reply_to_message_id: m.message_id
    })
  }
  
  const allCommands = []
  for (const [tag, commands] of Object.entries(groups)) {
    allCommands.push({
      tag: tag.charAt(0).toUpperCase() + tag.slice(1),
      commands: commands
    })
  }
  
  const totalPages = Math.ceil(allCommands.length / COMMANDS_PER_PAGE)
  const startIndex = (currentPage - 1) * COMMANDS_PER_PAGE
  const endIndex = startIndex + COMMANDS_PER_PAGE
  const pageCommands = allCommands.slice(startIndex, endIndex)
  
  let message = `Halo, ${name}!\n`
  message += `Waktu: ${waktu}\n`
  message += `Role: ${role}\n`
  message += `Halaman: ${currentPage}/${totalPages}\n\n`
  message += `Daftar perintah bot:\n\n`
  
  for (const group of pageCommands) {
    message += `${group.tag}\n`
    message += `${group.commands.map(c => `- ${c}`).join('\n')}\n\n`
  }
  
  message += `Bot aktif 24/7\n`
  message += `Dibuat oleh @CloudkuDev`
  
  const buttons = createPaginationButtons(currentPage, totalPages)
  
  const photoUrl = 'https://codeshare.cloudku.click/db/thumbnails/thumb_user_1.jpg'
  
  await conn.sendPhoto(m.chat.id, photoUrl, {
    caption: message,
    parse_mode: 'Markdown',
    reply_markup: buttons
  })
}

async function loadCommands() {
  const groups = {}
  
  try {
    const files = await fs.readdir(pluginsDir)
    
    for (const file of files) {
      if (!file.endsWith('.js')) continue
      
      const filePath = path.join(pluginsDir, file)
      const modulePath = `file://${filePath}?v=${Date.now()}`
      
      try {
        const plugin = (await import(modulePath)).default
        if (!plugin?.command || !plugin?.tags) continue
        
        const commands = Array.isArray(plugin.command) 
          ? plugin.command 
          : [plugin.command]
        const tags = Array.isArray(plugin.tags) 
          ? plugin.tags 
          : [plugin.tags]
        
        for (const tag of tags) {
          if (!groups[tag]) groups[tag] = []
          groups[tag].push(commands.map(cmd => `/${cmd}`).join(', '))
        }
      } catch (pluginErr) {
        console.error(`Error loading plugin ${file}:`, pluginErr)
        continue
      }
    }
    
    return groups
  } catch (err) {
    console.error('Error reading plugins directory:', err)
    return null
  }
}

function createPaginationButtons(currentPage, totalPages) {
  const keyboard = []
  
  const navRow = []
  
  if (currentPage > 1) {
    navRow.push({
      text: 'Sebelumnya',
      callback_data: `menu_${currentPage - 1}`
    })
  }
  
  if (currentPage < totalPages) {
    navRow.push({
      text: 'Selanjutnya',
      callback_data: `menu_${currentPage + 1}`
    })
  }
  
  if (navRow.length > 0) {
    keyboard.push(navRow)
  }
  
  if (totalPages > 3) {
    const jumpRow = []
    
    if (currentPage > 2) {
      jumpRow.push({
        text: '1',
        callback_data: 'menu_1'
      })
      
      if (currentPage > 3) {
        jumpRow.push({
          text: '...',
          callback_data: 'menu_noop'
        })
      }
    }
    
    for (let i = Math.max(1, currentPage - 1); i <= Math.min(totalPages, currentPage + 1); i++) {
      jumpRow.push({
        text: i === currentPage ? `[${i}]` : `${i}`,
        callback_data: `menu_${i}`
      })
    }
    
    if (currentPage < totalPages - 1) {
      if (currentPage < totalPages - 2) {
        jumpRow.push({
          text: '...',
          callback_data: 'menu_noop'
        })
      }
      
      jumpRow.push({
        text: `${totalPages}`,
        callback_data: `menu_${totalPages}`
      })
    }
    
    if (jumpRow.length > 0) {
      keyboard.push(jumpRow)
    }
  }
  
  keyboard.push([
    {
      text: 'Website',
      url: 'https://cloudkutube.eu'
    },
    {
      text: 'Channel',
      url: 'https://t.me/cloudkudev'
    }
  ])
  
  keyboard.push([
    {
      text: 'Developer',
      url: 'https://t.me/cloudkudev'
    }
  ])
  
  return {
    inline_keyboard: keyboard
  }
}

handler.callback = async ({ conn, callback_query }) => {
  const data = callback_query.data
  
  if (!data.startsWith('menu_')) return
  
  const page = data.replace('menu_', '')
  if (page === 'noop') {
    return conn.answerCallbackQuery(callback_query.id, {
      text: 'Navigasi cepat'
    })
  }
  
  const pageNum = parseInt(page)
  if (isNaN(pageNum)) return
  
  const fakeMessage = {
    from: callback_query.from,
    chat: { id: callback_query.message.chat.id },
    message_id: callback_query.message.message_id,
    text: `/menu ${pageNum}`
  }
  
  try {
    await conn.deleteMessage(callback_query.message.chat.id, callback_query.message.message_id)
  } catch (err) {
    console.error('Error deleting message:', err)
  }
  
  await handler({ conn, m: fakeMessage })
  await conn.answerCallbackQuery(callback_query.id)
}

handler.command = ['start', 'menu']
handler.help = ['start', 'menu']
handler.tags = ['main']

export default handler

Plugin API

  • conn - Telegram bot instance
  • m - Message object
  • text - Command arguments

Global Functions

  • global.sendMedia(conn, chatId, filePath, caption) - Send media files
  • global.loading(m, conn, done) - Show loading indicator

🎨 Console Output

The bot features beautiful console logging with:

  • 🌈 Gradient ASCII Art - Eye-catching startup banner
  • πŸ“Š Colored Logs - Different colors for different log types
  • πŸ” Message Tracking - Real-time message monitoring
  • ⚑ Plugin Status - Live plugin loading feedback

βš™οΈ Configuration

Edit config.js to customize:

export default {
  telegramBotToken: 'YOUR_BOT_TOKEN',
}

🀝 Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open Pull Request

πŸ“ž Support & Community

Platform Link Description
πŸ“’ Channel @CocoaChanChannel Latest updates & announcements
πŸ’¬ Group @CocoaChanGroup Community support & discussions
πŸ‘¨β€πŸ’» Developer @cloudkudev Direct contact with developer

πŸ› Bug Reports

Found a bug? Please report it:

  1. Join our Telegram Group
  2. Contact developer: @cloudkudev
  3. Provide detailed information about the issue

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

⭐ Star History

Star History Chart


Made with ❀️ by AlfiDev

⭐ Star this repo if you found it helpful! ⭐

Footer

About

Base Bot Telegram Plugins ESM Like Bot Whatsapp

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors