Ovaj dokument opisuje kako kreirati i konfigurisati Telegram bota za Panic Button aplikaciju.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KREIRANJE BOTA PREKO @BotFather β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. Otvori Telegram i pronaΔi @BotFather β
β β
β 2. PoΕ‘alji komandu: /newbot β
β β
β 3. BotFather pita za ime bota: β
β > Patrola Bot β
β β
β 4. BotFather pita za username (mora zavrΕ‘iti sa "bot"): β
β > patrola_skola_bot β
β β
β 5. BotFather ti daje TOKEN: β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Done! Congratulations on your new bot. β β
β β β β
β β Use this token to access the HTTP API: β β
β β 123456789:ABCdefGHIjklMNOpqrsTUVwxyz_0123456789 β β
β β β β
β β Keep your token secure and store it safely. β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β β οΈ SAΔUVAJ TOKEN! Nikada ga ne objavljuj javno. β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DODATNA PODEΕ AVANJA (opciono) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β PoΕ‘alji @BotFather sledeΔe komande: β
β β
β /setdescription β
β > Patrola Bot - Notifikacije o alarmima za bezbednost dece β
β β
β /setabouttext β
β > Bot za koordinaciju roditeljskih patrola oko Ε‘kola β
β β
β /setuserpic β
β > [Upload sliku/logo] β
β β
β /setcommands β
β > start - Pokreni bota β
β > help - PomoΔ β
β > status - Status sistema β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KREIRANJE TELEGRAM GRUPE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. U Telegram-u klikni na β‘ (hamburger menu) β
β β
β 2. "New Group" β
β β
β 3. Dodaj bar jednog Δlana (moΕΎe biti tvoj drugi nalog ili @patrola_skola_bot) β
β β
β 4. Unesi ime grupe: β
β > OΕ KovaΔiΔ - Patrola β
β β
β 5. Klikni β da kreiraΕ‘ grupu β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β POSTAVLJANJE BOTA KAO ADMINA β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β β οΈ VAΕ½NO: Bot MORA biti admin da bi mogao slati poruke u grupu! β
β β
β 1. Otvori grupu β
β β
β 2. Klikni na ime grupe (header) da otvoriΕ‘ info β
β β
β 3. Klikni na βοΈ (Edit) β
β β
β 4. "Administrators" β
β β
β 5. "Add Administrator" β
β β
β 6. PronaΔi i izaberi @patrola_skola_bot β
β β
β 7. Dodeli permisije (minimum): β
β β Post messages β
β β Edit messages β
β β
β 8. Klikni "Done" β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Metoda 1: Preko getUpdates API-ja
# 1. PoΕ‘alji bilo koju poruku u grupu
# 2. Pozovi API (zameni <TOKEN> sa tvojim tokenom):
curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
# 3. U JSON response-u, naΔi:
# {
# "message": {
# "chat": {
# "id": -100123456789, <-- OVO JE CHAT_ID
# "title": "OΕ KovaΔiΔ - Patrola",
# "type": "supergroup"
# }
# }
# }
# NAPOMENA: ID grupe je NEGATIVAN broj (poΔinje sa -)# Metoda 2: Koristi @userinfobot
# 1. Dodaj @userinfobot u grupu
# 2. Bot Δe automatski poslati info o grupi, ukljuΔujuΔi ID
# 3. Zatim moΕΎeΕ‘ ukloniti bota{
"ok": true,
"result": [
{
"update_id": 123456789,
"message": {
"message_id": 1,
"from": {
"id": 12345678,
"first_name": "Marko"
},
"chat": {
"id": -1001234567890,
"title": "OΕ KovaΔiΔ - Patrola",
"type": "supergroup"
},
"date": 1705671600,
"text": "Test"
}
}
]
}# Test slanja poruke u grupu
curl -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "-1001234567890",
"text": "π Test poruka - Patrola Bot je uspeΕ‘no povezan!",
"parse_mode": "Markdown"
}'
# OΔekivani response:
# {
# "ok": true,
# "result": {
# "message_id": 2,
# "chat": {"id": -1001234567890, ...},
# "text": "π Test poruka - Patrola Bot je uspeΕ‘no povezan!"
# }
# }# Simuliraj alarm poruku
curl -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{
"chat_id": "-1001234567890",
"text": "π¨ *ALARM*\n\nπ Lokacija: [Otvori mapu](https://maps.google.com/?q=44.8125,20.4612)\nπ¬ \"Prate me\"\nπ€ Od: Marko P.\n\nπ [Otvori u aplikaciji](https://patrola.rs/alarm/test)",
"parse_mode": "Markdown",
"disable_web_page_preview": false
}'# Postavi u Convex
npx convex env set TELEGRAM_BOT_TOKEN "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
npx convex env set TELEGRAM_CHAT_ID "-1001234567890"
npx convex env set APP_URL "https://patrola.rs"
# Proveri
npx convex env list// convex/telegram.ts
import { internalAction } from "./_generated/server";
import { v } from "convex/values";
export const sendMessage = internalAction({
args: {
text: v.string(),
parseMode: v.optional(v.string()),
},
handler: async (ctx, { text, parseMode = "Markdown" }) => {
const botToken = process.env.TELEGRAM_BOT_TOKEN;
const chatId = process.env.TELEGRAM_CHAT_ID;
if (!botToken || !chatId) {
throw new Error("Telegram not configured");
}
const response = await fetch(
`https://api.telegram.org/bot${botToken}/sendMessage`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
chat_id: chatId,
text,
parse_mode: parseMode,
disable_web_page_preview: false,
}),
}
);
const result = await response.json();
if (!result.ok) {
console.error("Telegram API error:", result);
throw new Error(result.description || "Failed to send message");
}
return result;
},
});| Endpoint | Metoda | Opis |
|---|---|---|
/getMe |
GET | Info o botu |
/getUpdates |
GET | Dobij nove poruke |
/sendMessage |
POST | PoΕ‘alji poruku |
/editMessageText |
POST | Izmeni poruku |
/deleteMessage |
POST | ObriΕ‘i poruku |
interface SendMessageParams {
chat_id: string | number; // ID grupe
text: string; // Tekst poruke
parse_mode?: "Markdown" | "HTML" | "MarkdownV2";
disable_web_page_preview?: boolean;
disable_notification?: boolean;
reply_to_message_id?: number;
reply_markup?: InlineKeyboardMarkup;
}*bold*
_italic_
`code`
```code block```
[link](http://example.com)// Poruka sa dugmiΔima
const message = {
chat_id: chatId,
text: "π¨ *ALARM*\n\nNeko treba pomoΔ!",
parse_mode: "Markdown",
reply_markup: {
inline_keyboard: [
[
{
text: "π Preuzimam",
url: "https://patrola.rs/alarm/abc123?action=take"
}
],
[
{
text: "π Lokacija",
url: "https://maps.google.com/?q=44.81,20.46"
}
]
]
}
};// Setup webhook za primanje poruka od bota
// 1. Registruj webhook
// POST https://api.telegram.org/bot<TOKEN>/setWebhook
// body: { "url": "https://xxx.convex.site/telegram-webhook" }
// 2. Convex HTTP endpoint
import { httpAction } from "./_generated/server";
export const telegramWebhook = httpAction(async (ctx, request) => {
const body = await request.json();
// Handle bot commands
if (body.message?.text?.startsWith("/")) {
const command = body.message.text.split(" ")[0];
const chatId = body.message.chat.id;
switch (command) {
case "/start":
await sendWelcomeMessage(chatId);
break;
case "/status":
await sendStatusMessage(chatId);
break;
}
}
return new Response("OK");
});// Kada bot detektuje da je dodat u grupu, Ε‘alje kod
export const handleBotAdded = internalAction({
args: {
chatId: v.string(),
chatTitle: v.string(),
},
handler: async (ctx, { chatId, chatTitle }) => {
// GeneriΕ‘i kod
const code = `TG-${Math.random().toString(36).substring(2, 8).toUpperCase()}`;
// SaΔuvaj u bazu
await ctx.runMutation(internal.telegram.saveLinkCode, {
code,
chatId,
chatTitle,
expiresAt: Date.now() + 15 * 60 * 1000, // 15 min
});
// PoΕ‘alji poruku sa kodom
await ctx.runAction(internal.telegram.sendMessage, {
chatId,
text: `π Zdravo! Ja sam PatrolaBot.
Da poveΕΎete ovu grupu sa aplikacijom, admin treba da unese ovaj kod u app:
π *KOD: ${code}*
Kod vaΕΎi 15 minuta.`,
});
},
});| Problem | ReΕ‘enje |
|---|---|
| Bot ne Ε‘alje poruke | Proveri da li je bot ADMIN u grupi |
| "Chat not found" | Proveri CHAT_ID (mora biti negativan za grupe) |
| "Bot was blocked" | Korisnik je blokirao bota |
| Rate limit exceeded | Implementiraj queue za poruke |
| "Forbidden" | Bot nema permisije u grupi |
# 1. Proveri da li bot radi
curl "https://api.telegram.org/bot<TOKEN>/getMe"
# 2. Proveri recent updates
curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
# 3. Proveri webhook status (ako koristiΕ‘)
curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"
# 4. Test poruka
curl -X POST "https://api.telegram.org/bot<TOKEN>/sendMessage" \
-d "chat_id=<CHAT_ID>&text=test"βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BEZBEDNOSNE PREPORUKE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β β Nikada ne objavljuj BOT_TOKEN javno β
β β Koristi environment variables β
β β Rotiraj token ako je kompromitovan (/revoke @BotFather) β
β β Minimalna poruka u TG (detalji u app-u) β
β β Verifikuj webhook requests (ako koristiΕ‘) β
β β Rate limit za slanje poruka β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Dokument kreiran: Januar 2026