Skip to main content
Squeek
Product tourFeaturesAtmospherePlatformsPrivacyBots
UAEN
Download
Product tourFeaturesAtmospherePlatformsPrivacyBotsDownloads
Back home

For developers

Bots in Squeek

A bot is an account that a program answers for. It shows up in search, you can message it, and you can add it to a group or a channel. Here is how to create one from your phone and get it running in a few minutes.

On this page

  1. Create a bot in the app
  2. Run the bot on Node.js
  3. Commands and description
  4. Edit, delete, react
  5. Send a message with a link
  6. Files
  7. Buttons under a message
  8. Posting later
  9. A bot that keeps order
  10. A bot without a server of its own
  11. Post to a channel without the library

1Create a bot in the app

  1. Open “Profile” → “My bots”.
  2. Tap “Create bot”. Enter a name — this is how the bot appears in chats, for example Weather — and a username: Latin letters only, and it must end with bot, for example weather_bot.
  3. Tap “Create”. A dialog shows the token — a long string like 7:a91f…:3c0d…. Tap “Share” and send it to yourself (Saved messages, email, anywhere) or long-press to copy it.

The token is shown once

It is the bot’s password: whoever has the token can write as the bot. Do not publish it and do not commit it to git.

The bot now exists: it appears in search as @weather_bot with a “bot” badge, you can message it, and you can add it to a group or a channel.

2Run the bot on Node.js

The program that answers for the bot runs on your computer or server. You need Node.js and the squeek-bot library.

bash
mkdir my-bot && cd my-bot && npm init -y && npm install squeek-bot

Create bot.js:

bot.js
const { SqueekBot } = require('squeek-bot');

const bot = new SqueekBot('7:a91f…:3c0d…'); // the token from the app

bot.on('message', async (msg) => {
  console.log(msg.from.name, ':', msg.text);
  if (msg.text === '/hi') await msg.reply('Hi! 🐀');
});

bot.on('connected', () => console.log('bot is online'));

bot.start();
bash
node bot.js

Now send /hi to the bot from the app — it replies.

  • message — an incoming message. msg.from.name is the sender, msg.text is the text, and msg.reply(text) answers in the same chat.
  • connected — the bot has connected to the server.
  • bot.start() — opens the connection and starts receiving messages.

3Commands and description

Someone opening a chat with a bot for the first time has no idea what to type. So a bot has a description — the line under its name — and a command menu: it shows on the bot's profile and drops down in the composer as soon as you type «/». A chat with a bot opens with a **Start** button, which sends /start.

  1. In **My bots**, tap the pencil next to the bot.
  2. Write the description and the commands, one per line, as /weather — forecast for tomorrow.
  3. Save. The menu is there for everyone who opens a chat with it.

The program can do the same when it starts — handy when there are many commands, or when they change with the code:

js
bot.on('connected', async () => {
  await bot.setDescription('Tells you the weather. Ask it with /weather.');
  await bot.setCommands([
    { command: 'weather', description: 'Forecast for tomorrow' },
    { command: 'rain', description: 'Will it rain today' },
  ]);
});

bot.on('message', async (msg) => {
  if (msg.text === '/start') await msg.reply('Hi! /weather tells you the forecast.');
});

The menu is only a menu: what a command does is your program's business. The server just shows the list.

4Edit, delete, react

A bot can rewrite its own message instead of sending a second one — «running → done» in one line. It can also delete its own message for everyone, and put an emoji on someone else's.

js
bot.on('message', async (msg) => {
  if (msg.text !== '/backup') return;

  await msg.react('👀');
  const id = await bot.send(msg.chat.id, 'Backup: running…');

  await makeBackup();
  await bot.editMessage(msg.chat.id, id, 'Backup: done ✅');
});

5Send a message with a link

The simplest way to make the bot say something is a webhook: a link with a secret in it, and a single POST to it does the job. No sign-in, no token, no library — good for cron, a script, or anything that can call a URL.

  1. In “My bots”, tap the link icon next to the bot.
  2. Copy the link — it is shown once. It looks like https://api.squeek.net/hooks/7/….
The bot writes to you
curl https://api.squeek.net/hooks/7/<secret> \
  -H 'content-type: application/json' \
  -d '{"text":"Backup finished"}'

The message appears in your chat with the bot. To post to a channel instead, add ?chat=@channel_handle — the bot has to be an admin there:

The bot posts to a channel
curl 'https://api.squeek.net/hooks/7/<secret>?chat=@my_channel' \
  -H 'content-type: application/json' \
  -d '{"text":"A new version is on the site"}'

The link is the access

Whoever has the link writes as the bot. If it ends up in the wrong hands, create a new one in the app — the old one stops working at once.

6Files

A private chat is only with the person who opened it

A bot never writes first: the person starts the chat. If they remove it, or block the bot, the bot goes quiet until they write again. That holds for text and files alike.

A bot can send a file to any chat it is in. The library takes care of the encryption.

js
const chart = await fs.promises.readFile('cpu.png');

await bot.sendFile(chatId, { name: 'cpu.png', data: chart, mimeType: 'image/png' }, 'Last hour');

The whole file is held in memory while it is sent — fine for a chart or a log, not for a film.

7Buttons under a message

A bot can hang up to five buttons under a message. Everyone reads the label; the data goes back to the bot alone — a press is stored nowhere and shown to nobody else.

js
await bot.send(chatId, 'Restart the server?', {
  buttons: [
    { label: 'Yes', data: 'restart:yes' },
    { label: 'Not now', data: 'restart:no' },
  ],
});

bot.on('button', async (press) => {
  if (press.data !== 'restart:yes') return;

  await bot.send(press.chatId, press.from.name + ' said yes; restarting…');
  await restart();
});

The server checks data against the buttons the message actually carries, so a bot only ever receives something it wrote itself.

8Posting later

Write now, publish whenever — a good-morning post at six, with nobody holding a phone. Channels only, including their discussions (the tabs of a channel). The queue is looked at every minute.

js
const id = await bot.schedule(chatId, 'Good morning 🐀', new Date('2026-10-01T06:00:00Z'));

await bot.scheduled(chatId);   // what has not gone out yet
await bot.unschedule(id);      // take it back

9A bot that keeps order

Make the bot an admin or a moderator of a group or channel and it can do what a person of that rank can: mute, ban, delete messages. With the same limits, too — it cannot touch anyone ranked above it.

js
bot.on('message', async (msg) => {
  if (!looksLikeSpam(msg.text)) return;

  await bot.deleteMessage(msg.id);
  await bot.mute(msg.chat.id, msg.from.id, 60, 'spam');
});
  • bot.mute(chatId, userId, minutes, reason?) — quiet for a while.
  • bot.ban(chatId, userId, reason?) — out, for good.
  • bot.unrestrict(chatId, userId) — lift a mute or a ban.
  • bot.deleteMessage(messageId) — take a message down for everyone.

10A bot without a server of its own

Hearing messages normally means a process running day and night. Without one, a bot can name a URL instead, and the server POSTs every message to it. The bot then lives anywhere that speaks HTTP: a free host, a function, a box at home.

js
const { url, secret } = await bot.setWebhook('https://my-bot.example/squeek');
// keep the secret — it signs every delivery
your handler, express for instance
app.post('/squeek', express.raw({ type: '*/*' }), async (req, res) => {
  const msg = await bot.readWebhook(req.body.toString(), req.get('x-squeek-signature'), SECRET);

  res.sendStatus(200);          // answer first, work after

  if (msg?.text === '/hi') await msg.reply('Hi there! 🐀');
});

readWebhook checks the signature and decrypts the message. When the signature does not match it throws, so a stranger's request never reaches your code.

11Post to a channel without the library

If the bot only posts to a channel, you do not need the library at all. Make the bot a channel admin and send two HTTP requests from any language. Private chats and groups do need the library.

The token has three colon-separated parts: botId:…:secret. Signing in takes the first (botId) and the third (secret).

Get an accessToken
curl https://api.squeek.net/auth/bot \
  -H 'content-type: application/json' \
  -d '{"botId":7,"secret":"3c0d…"}'

The response contains accessToken. Then post to the channel, where chatId is the channel’s id:

Send a message
curl https://api.squeek.net/messages \
  -H "authorization: Bearer <accessToken>" \
  -H 'content-type: application/json' \
  -d '{"chatId":17,"content":"Hello, channel"}'

A poll is the same request with a poll field:

Send a poll
curl https://api.squeek.net/messages \
  -H "authorization: Bearer <accessToken>" \
  -H 'content-type: application/json' \
  -d '{"chatId":17,"content":"When do we meet?","poll":{"question":"When do we meet?","options":["Friday","Saturday"]}}'
Squeek

A warm messenger for close conversations and quiet evenings.

Product

DownloadsFeaturesBots

Legal

PrivacyTerms

Contact us

adminsqueek@gmail.com
UAEN

© 2026 Squeek. All rights reserved.

Made with warmth from the burrow.