Skip to content

HirooSy/HIROBOT

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

85 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

H I R O - B O T :dependabot:

Important

This project is still a work in progress. If you encounter any bugs, please let me know.


  • Multi Sessions.
  • Database Node:Sqlite / Mongodb / MySQL.
  • AI Rich and Button message.
  • Auto-Heal Files.
  • Fast Website.
  • No Encrypted Files.

AI INFO
'Model Used:'
Gemini 3.1 Lite-Flash > Daily conversation
Gemini 3.1 Lite       > Daily conversation but more complex
Gemma-4-31b-it        > For system Auto-heal / coding
Gemma-4-26b-a4b-it    > For system Auto-heal / coding

How Auto-heal works :

Plugin Error
↓
Detect error line, Read stack trace
↓
Auto-Heal using AI Gemma 4
↓
Write file & Save
↓
Done

How to add a new tool

All MCP Helper
            -- Session / chat history --
            getSession(jid)                  get chat history array for a chat
            resetSession(jid)                clear chat history for a chat
            getPinnedNotesReadOnly(jid)      get notes pinned to a chat

            -- Talking to the AI / agent loop --
            runAgent(conn, m, text, opts)     run a full AI turn, get a reply
            runAgentConfirmed(conn, m, opts)  resume an agent turn awaiting confirmation
            callTool(name, args)             call another registered tool by name
            listTools() / countTools()       list / count registered tools

            -- Identity & permissions --
            getUserIdentity(jid, db, conn)    get sender's name/number/owner/timezone
            checkGroupAdminOrOwner(groupJid)  check if sender is group admin/owner
            readGroupSettings(groupJid)       read group settings from brain storage
            readOwnerList()                   list registered bot owners

            -- Persistent storage ("brain") --
            loadBrain() / saveBrain(brain)         read/write ai-brain.json
            ensureBrainGroupSlot(brain, jid)       ensure a group slot exists in brain

            -- Web & media --
            searchWebGrounded(query)                     grounded web search
            captureWebsiteScreenshot(url)                screenshot a webpage
            fetchWebsiteHtmlFallback(url)                fetch raw HTML of a page
            peekFetchBuffer(url, headers)                peek a file buffer from a URL
            peekFetchVideoBuffer(url, maxBytes, headers) peek a video buffer from a URL
            detectPlatform(url)                          detect platform (YouTube/TikTok/etc)
            peekAnalyzeWithVision(mediaItems, platform, url, context)  analyze media with vision model
            buildMediaPart(m)                            extract image/video/audio from a message
            fetchSocialMulti(url)                         download helper for social media
            downloadUserImageAsUrl(m)                    upload user's image, get back a URL

            -- File & data tools --
            readFileToolCore(file_path, offset)   core logic behind "read file" tool
            buildSimpleDiff(oldStr, newStr)       build a text diff between two strings
            parseDbKeyPath(key_path)              parse a dotted key path for db access

            -- Plugin execution (advanced/internal) --
            resolvePlugin(command)                      find which plugin matches a command
            resolveCustomPrefixPlugin(rawInput)         same, for custom-prefix commands
            execPluginCommand(command, argsStr, opts)   run an existing bot plugin/command
            execEval(code, opts)                        evaluate raw JS code (owner-only, dangerous)
            classifyPluginRisk(name, plugin)            classify a plugin's risk level
            accessLabel(level) / riskBadge(level)       risk-level label/badge helpers
            pluginRequirements(plugin)                  get a plugin's access requirements
            getDangerousDocReason(m)                    check if a message/doc looks risky

            -- Error handling & internals (rarely needed in tools) --
            handleError(conn, m, err, pluginName)   central error handler/reporter
            isTransientApiError(err)                check if an API error is transient
            getApiKeys() / getNextKey() / rotateKey() / resetRateLimit(jid)  API key pool mgmt
            normalizeApiKeys(input)                 format/clean a raw API key list
            getPersonality()                        get bot's configured personality/system prompt
            MODELS                                  map of available AI models
            setCurrentContext(...) / hasPending() / confirmPending() / cancelPending()
                                                     internal turn/state mgmt (used by mcp.js itself)
/*
  ctx()   -> Returns the current chat state (always fresh, since it's a function
             call, not a stored variable). Common fields:
               - currentJid : the id of the chat/user sending the message
               - conn       : the active WhatsApp connection (for manual sendMessage)
               - isOwner    : true if the sender is the bot owner

  getMcp() -> Async function to access helpers from mcp.js. Must be called
              INSIDE execute(), never at the top of the file -- importing
              mcp.js directly at the top would cause a circular import
              deadlock, since mcp.js is the one loading this file in the
              first place.
*/
import { ctx, getMcp } from '../context.js'

export default [
    {
        name: 'check_weather',
        description: 'Check the weather for a specific city. Use it when a user asks for the weather, e.g., "What\'s the weather like in Jakarta?"',
        parameters: {
            city: { type: 'string', description: 'City name, e.g. "Jakarta"', required: true }
        },
        execute: async ({ city }) => {
            const { currentJid } = ctx()
            if (!currentJid) return 'Chat context not available'

            // const { runAgent } = await getMcp() // only if you need a helper from mcp.js

            return `Weather in ${city}: sunny, 30Β°C`
        }
    }
]
SEND MESSAGE
//---Basic---
conn.reply(m.chat, 'Hello world!', m)

conn.sendFile(m.chat, media, filename, caption, m)
// media > buffer / fs path
// voice note > { ptt: true }
// document > { document: true }

conn.sendContact(m.chat, [
  ['6281234567890', 'HirooSy'],
  ['6289876543210', 'Hiro']
], m)

conn.react(m.chat, 'πŸ‘', m.key)
//---location interactive ---
conn.sendLocUrl(m.chat, 'https://example.com/thumb.jpg', 'Title', 'Address', 'Text', 'Footer', 'https://github.com/hiroosy', m)

//--- Url Preview ---
conn.sendUrlPreview(
  m.chat,
  'https://example.com/thumb.jpg',
  'https://example.com Hello World!',
  'Url Preview Title',
  'Url Description',
  'IMAGE',   // true for highQuality, or ['IMAGE', true]
  m
)

//--- Carousel ---
conn.sendButton(m.chat, {
    text: 'Interactive with Carousel!',
    footer: 'HirooSy',
    cards: [
        {
            image: { url: './path/to/image.jpg' },
            caption: 'Image 1',
            footer: 'Image 1',
            nativeFlow: [{ text: 'Source', url: 'https://example.com', useWebview: true }]
        },
        {
            image: { url: 'https://example.com/image.png' },
            caption: 'Image 2',
            footer: 'Image 2',
            ltoText: 'New Coupon!',
            ltoCode: 'HiroBot',
            ltoUrl: 'https://example.com',
            nativeFlow: [{ text: 'Source', url: 'https://example.com' }]
        }
    ]
}, m)

//--- Interactive buttons ---
conn.sendButton(m.chat, {
    image: { url: './path/to/image.jpg' },
    caption: 'Interactive!',
    footer: 'My Bot',
    optionText: 'Select Options',
    optionTitle: 'Select Options',
    ltoText: 'HirooSy',
    ltoCode: 'Hiro bot',
    ltoUrl: 'https://example.com',
    nativeFlow: [
        { text: 'πŸ‘‹πŸ» Greeting', id: '#Greeting' },
        { text: 'πŸ“ž Call', call: '628123456789' },
        { text: 'πŸ“‹ Copy', copy: 'Hiro bot' }, 
        { text: '🌐 Source', url: 'https://example.com', useWebview: true },
        {
            text: 'πŸ“‹ Select',
            sections: [
                { title: '✨ Section 1', rows: [{ header: '', title: '🏷️ Coupon', description: '', id: '#CouponCode' }] },
                { title: '✨ Section 2', highlight_label: 'πŸ”₯ Popular', rows: [{ header: '', title: 'πŸ’­ Secret Ingredient', description: '', id: '#SecretIngredient' }] }
            ],
        }
    ]
}, m)

//--- Ai Rich ---
await conn.aiRich()
    .setTitle('Ai Rich Message') 
    .addText('[HyperLink](https://example.com)\nCitation [](https://example.com)'\n[x^2+y^2=r^2|100|100](https://example.com/latex.png))
    .addImage('https://example.com/image.png')
    .addCode('javascript', `console.log('Hello World')`)
    .addTable([
        ['Name', 'HirooSy'],
        ['Bio', 'Im developer'],
        ['Age', '67']
    ])
    .addSource([['https://example.com/favicon.ico', 'https://example.com', 'Source']])
    .addTip('Tip Text')
    .addSuggest(['Continue', 'Cancel'])
    .send(m.chat, { quoted: m })

//--- Sticker Pack ---
// Media = buffer / path
conn.sendStickerPack(m.chat, {
   cover: { url: media },
   stickers: [
      { data: { url: media } },
      { data: { url: media } },
   ],
   name: 'My Sticker Pack',
   publisher: 'Publisher stickerpack',
   description: 'Description pack'
})
MORE INFO
.
β”œβ”€β”€ lib
β”‚   β”œβ”€β”€ ai               // Ai system
β”‚   β”œβ”€β”€ config.js        // Set your bot's preference here
β”‚   β”œβ”€β”€ connection.js    // connection manager
β”‚   β”œβ”€β”€ database.js      // database manager
β”‚   β”œβ”€β”€ handler.js       // event handler
β”‚   β”œβ”€β”€ helper.js        // lib helper
β”‚   β”œβ”€β”€ import.js        // plugin importer
β”‚   β”œβ”€β”€ main.js          // Tunnel, all interval
β”‚   β”œβ”€β”€ scraper          // Scrapers
β”‚   β”œβ”€β”€ server.js        // Website endpoint
β”‚   β”œβ”€β”€ simple.js        // Functions conn
β”‚   β”œβ”€β”€ start.js         // Start script
β”‚   β”œβ”€β”€ store.js         // Store connection
β”‚   β”œβ”€β”€ tools            // Tools
β”‚   └── views            // HTML folder
β”œβ”€β”€ data                 // Sessions, database, TMP, Tunnel data, All .json
β”œβ”€β”€ plugins              // commands here
β”œβ”€β”€ .env                 // Set your tokens here
β”œβ”€β”€ package.json
└── README.md

Plugin format

πŸͺ§ Handler Style :
let handler = async (m, { conn }) => {
  // Your code here
};

handler.command = Array / String
handler.help = Array / String
handler.rowner = Boolean
handler.owner = Boolean
handler.mods = Boolean
handler.group = Boolean
handler.private = Boolean
handler.botAdmin = Boolean
handler.premium = Boolean
handler.admin = Boolean
handler.limit = Boolean / Numberic
handler.level = Numberic
handler.customPrefix = String
handler.ai = Array
handler.dym = Array / String

export default handler
let handler = (m) => m;
handler.before = async (m, { conn }) => {
  //your code here
};
export default handler;

πŸͺ§ Export style :

export default {
   run: async (m, { conn }) => {
      // your code here
   },
   command: Array / String,
   tags: Array / String,
   help: Array / String,
   rowner: Boolean,
   owner: Boolean,
   mods: Boolean,
   group: Boolean,
   private: Boolean,
   botAdmin: Boolean,
   premium: Boolean,
   admin: Boolean,
   limit: Boolean / Numberic,
   level: Numberic,
   customPrefix: String,
   ai: Array,
   dym: Array / String,
}
export default {
  async before(m, { conn }) {
     // your code here
  },
};


Warning

REQUIRE NODEJS V22+

$ git clone https://github.com/HirooSy/HIROBOT.git
$ npm install
$ cp .env.example .env
$ nano .env
$ npm start