Building Your First BotMate Plugin: A Step-by-Step Guide
Learn how to create and customize your first plugin for BotMate with this easy-to-follow tutorial.
The project is under heavy development, if you want to contribute, or you have any queries, please join our Telegram group and checkout Github repository.
If you're not familiar with BotMate, it’s a powerful open-source web-based platform designed to help you manage multiple bots across different platforms—all from a single, unified dashboard. BotMate features an intuitive plugin system that enhances your bots with extended functionality. By simply installing a plugin, you can unlock new capabilities for your bots in just a few clicks.
Each plugin comes with its own set of customizable configurations, which you can easily manage through the platform’s user-friendly interface. The best part? Once you’ve adjusted your settings, your bots are automatically updated—no need to restart or modify any code. With BotMate, bot management becomes effortless, giving you more time to focus on what really matters.
🌐 Website: botmate.dev 📦 Repository: GitHub - botmate 📚 Docs: Documentation 🔍 Sample Repository: botmate-openai-example
Overview
Before diving into the details, let me give you a quick rundown of what we’re going to build and the technologies we’ll be using.
We’ll be creating a plugin for BotMate that allows users to input their OpenAI API keys directly from the dashboard. This plugin will enable a Telegram bot to respond to every message it receives. Additionally, we’ll add a configuration option to specify whether the bot should respond in Telegram groups or only in personal messages.
With this plugin, users will have full control over their bot’s behavior through simple settings—no code modifications needed.
Get started
Before we dive into the development process, let’s ensure you have the necessary prerequisites in place.
Prerequisites
Node.js – Version 20 or higher
Operating System – Linux, macOS, or Android (Windows is currently untested)
pnpm – For managing the workspace and faster installations
TailwindCSS – Used for styling, as BotMate relies on it
To begin, we’ll create a new BotMate project. Run the following command in your terminal:
pnpm create botmate
This will go through a series of questions in the terminal. Please answer the questions, and then a project directory will be created.
After that, we will change our current working directory to the newly created one (i.e. project's directory) and run the following command to start the development server:
pnpm dev
Setup Page
Visit localhost:8233 to open up the BotMate dashboard. After that, click on the Telegram icon, and you will be prompted to enter a bot token. Please click here to learn how to obtain a bot token in Telegram.
After adding the bot, you will notice on the Settings page that there are no plugins available yet. We will create our plugin by running a command in the terminal.
Creating a Plugin
To create a plugin, head back to the terminal and run the following command:
pnpm botmate pm create
"pm" refers to plugin manager
This will again ask few questions related to plugin, please select "Telegram" as the platform.
After you finish creating the plugin, you should see a new folder inside the packages
directory. Take a moment to explore the newly created folder and familiarize yourself with the files. Click here to learn about the plugin structure.
Now, your plugin should be visible on the Settings page of your bot. If it's not already running, be sure to run the following command to start the development server:
Click on "Install" to install the plugin to your currently active bot. You can also install this plugin in multiple Telegram bots, and even publish it to npm for others to use (we'll cover this later in the post).
After installing, you should see a "Configure" button. When you click on it, the settings modal for the plugin will open.
Now, let's open the botmate
folder in Visual Studio Code. Before we dive into writing the plugin, let's take a moment to understand the folder structure.
You’ll notice there are two main folders: client
and server
. As their names suggest:
The
client
folder contains code for the dashboard UI, which is built using React.The
server
folder contains code for the bot, server, and database interactions, which are powered by TypeScript and Node.js.
We'll start by adding an input field in the Settings UI to accept an API key and save it in the database. To do this, we'll use an inbuilt function that stores values as key-value pairs in the database. Let's first setup our configurations types by editing src/config.types.ts
file.
export type Config = {
key: string;
};
Then in, src/client/settings.tsx
file, we will write design a basic UI for taking input from the user.
import React, { useRef } from 'react';
import { toast, usePluginConfig } from '@botmate/client';
import { Button, Input, Label } from '@botmate/ui';
import { Config } from '../config.types';
function SettingsPage() {
const config = usePluginConfig<Config>();
const apiKeyRef = useRef<HTMLInputElement>(null);
const defaultValue = config.get('key', '');
return (
<div className="space-y-4">
<div>
<Label htmlFor="key">OpenAI API Key</Label>
<Input
id="key"
placeholder="Enter your OpenAI API key (eg. sk-....P20J)"
ref={apiKeyRef}
defaultValue={defaultValue}
className="mt-1"
/>
<p className="text-sm text-muted-foreground mt-1">
You can find your API key in the OpenAI dashboard.
</p>
</div>
<Button
onClick={() => {
const apiKey = apiKeyRef.current?.value;
if (!apiKey) {
toast.error('API key is required');
return;
}
config.save('key', apiKey).then(() => {
toast.success('API key saved');
});
}}
>
Save
</Button>
</div>
);
}
export default SettingsPage;
The code above uses the usePluginConfig
hook from @botmate/client
to save the configuration of the current plugin for the active bot. It handles everything internally, so all you need to do is call the save
and get
functions.
Note: BotMate comes with hot reload, so you don't need to manually restart the server.
After saving the file, head back to the dashboard, and you should see the following UI when you click on "Configure."
Try entering the API key and click "Save." You should see a success toast notification, indicating that the value has been saved in the database.
To verify, reload the page and click on "Configure" again. You should see the input box already filled with the saved value.
Run the following code to install openai
package.
cd packages/openai-plugin
pnpm i openai
Now, let's write the server. Open server/server.ts
file and write the following code.
import { PlatformType, Plugin } from '@botmate/server';
import type { Bot } from 'grammy';
import OpenAI from 'openai';
import { Config } from '../config.types';
export class OpenAIChatbot extends Plugin {
displayName = 'OpenAI Chatbot';
platformType = PlatformType.Telegram;
client?: OpenAI;
async load() {
const cm = this.configManager<Config>();
const bot = this.bot.instance<Bot>();
bot.on('message', async (ctx) => {
if (!this.client) {
const apiKey = await cm.get('key');
if (!apiKey) {
this.logger.warn(`No API key was found for OpenAI`);
return;
}
this.client = new OpenAI({
apiKey,
});
}
try {
ctx.replyWithChatAction('typing');
const chatCompletion = await this.client.chat.completions.create({
messages: [{ role: 'user', content: ctx.message.text! }],
model: 'gpt-3.5-turbo',
});
if (chatCompletion.choices) {
const text = chatCompletion.choices[0].message.content;
if (text) {
ctx.reply(text);
}
}
} catch (error) {
this.logger.error('Error:', error);
ctx.reply('An error occurred while processing your request');
}
});
}
}
The library used for Telegram bots is grammy. The code is fairly self-explanatory. We are creating a config manager with const cm = this.configManager<Config>()
, and then loading the key
value from the saved configuration to pass to OpenAI. Upon receiving a message, we complete the message based on the input.
Enabling the Plugin
The next step is to enable the plugin from the Settings page. Plugins installed to a bot are disabled by default, so you must enable them if you want to use the plugin in your bot. The configuration data will be preserved as long as you don’t uninstall the plugin.
Now, that's it. You should see your Telegram bot reply to your message.
Next steps
Try to add a checkbox to configure whether the bot should reply in the group or only in the private.
Here is a snippet for a checkbox.
<div className="flex items-center space-x-2">
<Checkbox />
<label className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
Allow in group chat
</label>
</div>
🙂 Here is the a demo -