Bot Development & Automation 2026: Discord, Telegram, Slack i nie tylko - kompletny przewodnik

2026-05-27#discord#telegram#slack

Bot Development & Automation 2026: Discord, Telegram, Slack i nie tylko

Wyobraź sobie, że Twój serwer Discord działa sam. Moderation odbywa się automatycznie. Nowi użytkownicy są witani personalnie. System economy zachęca do aktywności. A to wszystko działa 24/7, bez ani jednej minuty Twojego czasu.

To nie utopia. To custom bot development.

W 2026 roku boty to nie tylko zabawki dla geeks. To infrastruktura biznesowa dla communities liczących setki tysięcy użytkowników, automatyzacje generujące przychód dla firm, i AI asystenci, którzy zastępują całe działy customer support.

Przez ostatnie lata zbudowałem dziesiątki botów - od prostych moderation systems po zaawansowane platformy z Stripe payments, GPT-4 integracją i real-time analytics. W tym artykule dzielę się wszystkim, co wiem o bot development na Discord, Telegram, Slack i innych platformach.

Spis treści

  1. Dlaczego boty to przyszłość - liczby i trendy
  2. Architektura: Jak myśleć o botach jak inżynier
  3. Discord Bot Development - od zera do produkcji
  4. Telegram Bot Development - potęga inline i webhooks
  5. Slack Bot Automation - enterprise-grade solutions
  6. AI-Powered Bots - integracja z GPT-4 i Claude
  7. Databases & Caching - MongoDB, Redis, PostgreSQL
  8. Payment Integration - Stripe, PayPal w botach
  9. Skalowanie i hosting production botów
  10. Case Studies - prawdziwe projekty
  11. Pełny ekosystem: Multi-Platform Bot Architecture

1. Dlaczego boty to przyszłość

Rynek botów w liczbach (2026)

Boty nie są trendem. To fundamentalna zmiana w komunikacji cyfrowej:

🔥 Rynek i adopcja:

  • Discord: 500+ milionów użytkowników, over 1 million active bots (Discord Developer Portal 2026)
  • Telegram: 900+ milionów aktywnych użytkowników, boty generują $2.1B przychodu rocznie
  • Slack: 32 miliony użytkowników dziennie, 90% Fortune 100 korzysta z Slack bots
  • Chatbot market: Wyceniany na $27.3 miliarda w 2030 (Grand View Research)

Dlaczego firmy inwestują w boty:

ROI z automatyzacji botów (dane rzeczywiste):

Customer Support Bot:
  → Redukuje ticekty o 40-70%
  → Czas odpowiedzi: 30 min → 2 sekundy
  → Koszt obsługi: $15/ticket → $0.05/ticket

Community Management Bot:
  → Moderation 24/7 (vs człowiek: 8h/dzień)
  → Zero human error w spam detection
  → Engagement +35% przez gamification

E-commerce Bot:
  → Order tracking automation
  → Payment confirmations instant
  → Revenue per bot: $500-$5000/miesiąc

Który typ bota wybrać?

Zanim zaczniesz kodować, musisz wiedzieć co chcesz osiągnąć. Oto mapa typów botów:

| Typ | Platforma | Złożoność | Potencjalny przychód | |-----|-----------|-----------|---------------------| | Moderation Bot | Discord | ⭐⭐ | $99-499/serwer | | Economy/Leveling | Discord | ⭐⭐⭐ | $199-999/serwer | | Music Bot | Discord | ⭐⭐⭐ | Freemium + premium | | Customer Support | Telegram | ⭐⭐ | $299-1499/miesiąc | | Payment Bot | Telegram | ⭐⭐⭐⭐ | $499-2999/projekt | | Workspace Automation | Slack | ⭐⭐⭐ | $999-4999/rok | | AI Assistant | Dowolna | ⭐⭐⭐⭐⭐ | $299-9999/projekt |


2. Architektura: Jak myśleć o botach jak inżynier

Event-Driven Architecture

Każdy bot działa na tej samej zasadzie: słuchaj zdarzeń → reaguj. Ale to jak reagujesz decyduje o jakości bota.

[Platform API] ──── WebSocket/Polling ────► [Bot Core]
                                                │
                         ┌──────────────────────┤
                         ▼                      ▼
                    [Event Router]        [Command Handler]
                         │                      │
              ┌──────────┤              ┌────────┤
              ▼          ▼              ▼        ▼
         [Commands]  [Auto-Mod]    [Database]  [AI API]
              │          │              │        │
              └──────────┴──────────────┴────────┘
                                  │
                            [Response Layer]
                                  │
                    ┌─────────────┴────────────┐
                    ▼                          ▼
              [Platform API]             [Webhooks/External]

Trzy filary production bota

1. Reliability (niezawodność) Bot musi działać 24/7. Zero downtime = zero strat. Używam:

  • Process managers: PM2 (Node.js) lub Supervisor (Python)
  • Health checks: Endpoint /health sprawdzany co 30s
  • Auto-restart: Graceful shutdown + restart przy crashach
  • Logging: Winston (Node.js) lub Loguru (Python) z rotacją logów

2. Performance (wydajność) Latency to wszystko. Użytkownik czeka na odpowiedź bota w ciągu milisekund.

  • Caching: Redis dla często używanych danych (prefix commands, user settings)
  • Database indexing: Indeksy na polach userId, guildId, timestamp
  • Rate limiting: Kolejkowanie requestów do API żeby nie przekroczyć limitów
  • Lazy loading: Ładuj moduły tylko gdy potrzebne

3. Security (bezpieczeństwo) Boty mają dostęp do danych tysięcy użytkowników. Bezpieczeństwo nie jest opcją.

  • Permission checks: Sprawdzaj role PRZED każdą komendą
  • Input validation: Nigdy nie ufaj user input
  • Token security: Secrets w .env, nigdy w kodzie
  • Rate limiting per user: Chroń przed spam/abuse

3. Discord Bot Development - od zera do produkcji

Dlaczego Discord.js?

Discord.js v14 to de facto standard dla Node.js Discord botów. Dlaczego go wybieram:

  • TypeScript support - typy dla wszystkich Discord API objectów
  • Slash Commands - nowoczesny interface zamiast prefix commands
  • Sharding - skalowanie do tysięcy serwerów
  • Voice support - audio streaming dla music botów
  • Collectors - awaitMessages, awaitReactions dla interaktywnych flow'ów

Setup bota - projekt struktury

discord-bot/
├── src/
│   ├── commands/
│   │   ├── moderation/
│   │   │   ├── ban.ts
│   │   │   ├── kick.ts
│   │   │   └── timeout.ts
│   │   ├── economy/
│   │   │   ├── balance.ts
│   │   │   ├── daily.ts
│   │   │   └── shop.ts
│   │   └── utility/
│   │       ├── help.ts
│   │       └── ping.ts
│   ├── events/
│   │   ├── ready.ts
│   │   ├── interactionCreate.ts
│   │   └── guildMemberAdd.ts
│   ├── utils/
│   │   ├── database.ts
│   │   ├── logger.ts
│   │   └── permissions.ts
│   └── index.ts
├── .env
├── package.json
└── tsconfig.json

Slash Commands z TypeScript (production-ready)

// src/commands/moderation/ban.ts
import {
  ChatInputCommandInteraction,
  SlashCommandBuilder,
  PermissionFlagsBits,
  GuildMember,
  EmbedBuilder
} from 'discord.js';
import { logModAction } from '../../utils/logger';
import { db } from '../../utils/database';

export const data = new SlashCommandBuilder()
  .setName('ban')
  .setDescription('Ban użytkownika z serwera')
  .addUserOption(option =>
    option.setName('target')
      .setDescription('Użytkownik do zbanowania')
      .setRequired(true)
  )
  .addStringOption(option =>
    option.setName('reason')
      .setDescription('Powód bana')
      .setRequired(false)
      .setMaxLength(512)
  )
  .addIntegerOption(option =>
    option.setName('delete_days')
      .setDescription('Ile dni wiadomości usunąć (0-7)')
      .setMinValue(0)
      .setMaxValue(7)
  )
  .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers);

export async function execute(interaction: ChatInputCommandInteraction) {
  // 1. Defer reply - daje 15 minut na odpowiedź
  await interaction.deferReply({ ephemeral: true });

  const target = interaction.options.getMember('target') as GuildMember;
  const reason = interaction.options.getString('reason') ?? 'Brak powodu';
  const deleteDays = interaction.options.getInteger('delete_days') ?? 0;

  // 2. Validation - zawsze sprawdź zanim wykonasz
  if (!target) {
    return interaction.editReply('❌ Nie znaleziono użytkownika na serwerze.');
  }

  if (!target.bannable) {
    return interaction.editReply('❌ Nie mogę zbanować tego użytkownika (wyższe uprawnienia).');
  }

  if (target.id === interaction.user.id) {
    return interaction.editReply('❌ Nie możesz zbanować samego siebie.');
  }

  // 3. Execute
  try {
    await target.ban({
      reason: `${reason} | Moderator: ${interaction.user.tag}`,
      deleteMessageSeconds: deleteDays * 86400
    });

    // 4. Log do bazy danych
    await db.collection('mod_logs').insertOne({
      action: 'BAN',
      targetId: target.id,
      targetTag: target.user.tag,
      moderatorId: interaction.user.id,
      moderatorTag: interaction.user.tag,
      reason,
      guildId: interaction.guildId,
      timestamp: new Date()
    });

    // 5. Rich embed response
    const embed = new EmbedBuilder()
      .setColor(0xFF0000)
      .setTitle('🔨 Użytkownik zbanowany')
      .addFields(
        { name: 'Użytkownik', value: `${target.user.tag} (${target.id})`, inline: true },
        { name: 'Moderator', value: interaction.user.tag, inline: true },
        { name: 'Powód', value: reason }
      )
      .setTimestamp();

    return interaction.editReply({ embeds: [embed] });

  } catch (error) {
    console.error('Ban failed:', error);
    return interaction.editReply('❌ Wystąpił błąd podczas banowania.');
  }
}

Auto-Moderation System

Zaawansowany system moderacji wykrywający spam, flood i zakazane treści:

// src/events/messageCreate.ts - Auto-Mod Engine
import { Message } from 'discord.js';
import { cache } from '../utils/cache'; // Redis wrapper

const SPAM_THRESHOLD = 5; // wiadomości
const SPAM_WINDOW = 5000; // w 5 sekundach

export async function handleMessage(message: Message) {
  if (message.author.bot || !message.guild) return;

  // 1. Spam detection z sliding window
  const key = `spam:${message.guild.id}:${message.author.id}`;
  const count = await cache.incr(key);
  if (count === 1) await cache.expire(key, 5); // 5s window

  if (count >= SPAM_THRESHOLD) {
    await message.delete().catch(() => {});
    
    const member = message.member;
    if (member) {
      await member.timeout(60000, 'Auto-Mod: Spam detection');
      await message.channel.send(
        `⚠️ ${message.author} - timeout 1 minuta za spam.`
      ).then(msg => setTimeout(() => msg.delete(), 5000));
    }
    return;
  }

  // 2. Badwords filter (z regex)
  const BADWORDS_REGEX = /\b(spam|offensive_word)\b/gi; // customize!
  if (BADWORDS_REGEX.test(message.content)) {
    await message.delete();
    await message.author.send('⚠️ Twoja wiadomość została usunięta - naruszyła regulamin serwera.');
    return;
  }

  // 3. Link filter dla nieweryfikowanych użytkowników
  const hasLink = /https?:\/\/[^\s]+/.test(message.content);
  const isVerified = message.member?.roles.cache.some(r => r.name === 'Verified');
  
  if (hasLink && !isVerified) {
    await message.delete();
    await message.reply('❌ Musisz być zweryfikowany aby wysyłać linki.').then(
      msg => setTimeout(() => msg.delete(), 5000)
    );
  }
}

4. Telegram Bot Development - potęga inline i webhooks

Telegram vs Discord: Kluczowe różnice dla developerów

Discord:
  ✓ Guild (server) structure - hierarchia, kanały, role
  ✓ Rich Embeds - piękne wiadomości
  ✓ Voice channels - audio/video
  ✗ Mniejsza baza użytkowników poza gaming

Telegram:
  ✓ 900M+ użytkowników
  ✓ Inline bots - działają w dowolnym chacie
  ✓ Bot payments API wbudowany
  ✓ WebApp support (mini-apps!)
  ✓ Kanały + grupy + bot jednocześnie
  ✓ Ogromna adopcja w crypto, biznes, e-commerce

Telegraf v4 - Node.js framework

import { Telegraf, Markup, session } from 'telegraf';
import { message } from 'telegraf/filters';
import { MongoClient } from 'mongodb';

interface SessionData {
  step?: string;
  orderData?: Partial<Order>;
}

const bot = new Telegraf<Context>(process.env.TELEGRAM_TOKEN!);

// Session middleware (persisted w MongoDB)
bot.use(session({
  defaultSession: (): SessionData => ({})
}));

// Inline keyboard z callback buttons
bot.command('start', async (ctx) => {
  const keyboard = Markup.inlineKeyboard([
    [
      Markup.button.callback('🛒 Sklep', 'shop'),
      Markup.button.callback('📦 Zamówienia', 'orders')
    ],
    [
      Markup.button.callback('💬 Support', 'support'),
      Markup.button.webApp('🌐 Panel', 'https://yourapp.com/panel')
    ]
  ]);

  await ctx.reply(
    `Witaj w **${process.env.BOT_NAME}** 👋\n\nCo mogę dla Ciebie zrobić?`,
    { parse_mode: 'Markdown', ...keyboard }
  );
});

// Conversation flow - multi-step form
bot.action('shop', async (ctx) => {
  ctx.session.step = 'choosing_product';
  
  const products = await db.collection('products').find({ active: true }).toArray();
  
  const keyboard = Markup.inlineKeyboard(
    products.map(p => [
      Markup.button.callback(`${p.name} - $${p.price}`, `buy_${p._id}`)
    ])
  );

  await ctx.editMessageText('🛍️ Wybierz produkt:', keyboard);
});

// Payment integration (Telegram Payments API)
bot.action(/^buy_(.+)$/, async (ctx) => {
  const productId = ctx.match[1];
  const product = await db.collection('products').findOne({ _id: new ObjectId(productId) });
  
  if (!product) return ctx.answerCbQuery('Produkt niedostępny');

  await ctx.replyWithInvoice({
    title: product.name,
    description: product.description,
    payload: JSON.stringify({ productId, userId: ctx.from.id }),
    provider_token: process.env.STRIPE_PROVIDER_TOKEN!,
    currency: 'USD',
    prices: [{ label: product.name, amount: product.price * 100 }],
    photo_url: product.imageUrl,
    need_name: false,
    need_email: true
  });
});

// Pre-checkout answer (wymagane przez Telegram!)
bot.on('pre_checkout_query', (ctx) => ctx.answerPreCheckoutQuery(true));

// Successful payment handler
bot.on(message('successful_payment'), async (ctx) => {
  const payload = JSON.parse(ctx.message.successful_payment.invoice_payload);
  
  // Zapisz zakup w bazie
  await db.collection('orders').insertOne({
    userId: ctx.from.id,
    productId: payload.productId,
    amount: ctx.message.successful_payment.total_amount / 100,
    currency: ctx.message.successful_payment.currency,
    telegramPaymentId: ctx.message.successful_payment.telegram_payment_charge_id,
    timestamp: new Date()
  });

  await ctx.reply(
    '✅ **Płatność przyjęta!**\n\nDziękujemy za zakup. Twój dostęp zostanie przyznany w ciągu kilku minut.',
    { parse_mode: 'Markdown' }
  );
});

// Webhook zamiast polling (production!)
bot.launch({
  webhook: {
    domain: process.env.WEBHOOK_DOMAIN!,
    port: 3001
  }
});

Telegram Mini Apps (Web Apps)

Najnowszy feature Telegrama - mini aplikacje działające bezpośrednio w chacie:

// Frontend (React/Next.js) - Telegram Web App SDK
import WebApp from '@twa-dev/sdk';

export function ShopApp() {
  const user = WebApp.initDataUnsafe.user;
  
  // Dostęp do danych Telegram user
  console.log(user?.id, user?.username, user?.first_name);

  const handlePurchase = async (productId: string) => {
    // Zamknij web app i wyślij dane do bota
    WebApp.sendData(JSON.stringify({ action: 'purchase', productId }));
  };

  return (
    <div style={{ background: WebApp.backgroundColor }}>
      {/* Twoja React aplikacja działa w Telegramie! */}
      <button onClick={() => handlePurchase('product-123')}>
        Kup teraz
      </button>
    </div>
  );
}

5. Slack Bot Automation - enterprise-grade solutions

Slack API - trzy warstwy możliwości

Warstwa 1: Basic Bot
  → Respond to messages
  → Post notifications
  → Simple commands
  → Use case: Alerts, CI/CD notifications

Warstwa 2: Workflow Automation  
  → Modals (popup forms)
  → Block Kit UI (rich interactive messages)
  → App Home tab
  → Use case: Ticket systems, approval workflows

Warstwa 3: Platform Integration
  → Slack Connect (B2B)
  → External integrations (Jira, GitHub, Salesforce)
  → Custom dashboards in Slack
  → Use case: Enterprise CRM, HR systems

Bolt.js - oficjalny Slack framework

import { App, BlockAction, ViewSubmitAction } from '@slack/bolt';
import { WebClient } from '@slack/web-api';

const app = new App({
  token: process.env.SLACK_BOT_TOKEN!,
  signingSecret: process.env.SLACK_SIGNING_SECRET!,
  socketMode: true, // dev mode - bez publicznego URL
  appToken: process.env.SLACK_APP_TOKEN!
});

// Slash command z Modal (formularz popup)
app.command('/ticket', async ({ command, ack, client }) => {
  await ack();

  // Otwórz modal
  await client.views.open({
    trigger_id: command.trigger_id,
    view: {
      type: 'modal',
      callback_id: 'create_ticket',
      title: { type: 'plain_text', text: '🎫 Nowy Ticket' },
      submit: { type: 'plain_text', text: 'Utwórz' },
      blocks: [
        {
          type: 'input',
          block_id: 'title',
          element: {
            type: 'plain_text_input',
            action_id: 'value',
            placeholder: { type: 'plain_text', text: 'Opisz problem...' }
          },
          label: { type: 'plain_text', text: 'Tytuł' }
        },
        {
          type: 'input',
          block_id: 'priority',
          element: {
            type: 'static_select',
            action_id: 'value',
            options: [
              { text: { type: 'plain_text', text: '🔴 Krytyczny' }, value: 'critical' },
              { text: { type: 'plain_text', text: '🟡 Średni' }, value: 'medium' },
              { text: { type: 'plain_text', text: '🟢 Niski' }, value: 'low' }
            ]
          },
          label: { type: 'plain_text', text: 'Priorytet' }
        }
      ]
    }
  });
});

// Modal submission handler
app.view('create_ticket', async ({ ack, body, view, client }) => {
  await ack();

  const title = view.state.values.title.value.value!;
  const priority = view.state.values.priority.value.selected_option!.value;
  const userId = body.user.id;

  // Stwórz ticket w DB i wyślij do kanału support
  const ticket = await createTicketInDB({ title, priority, userId });

  await client.chat.postMessage({
    channel: process.env.SUPPORT_CHANNEL!,
    blocks: [
      {
        type: 'section',
        text: {
          type: 'mrkdwn',
          text: `🎫 *Nowy Ticket #${ticket.id}*\n*Tytuł:* ${title}\n*Priorytet:* ${priority}\n*Zgłosił:* <@${userId}>`
        }
      },
      {
        type: 'actions',
        elements: [
          {
            type: 'button',
            text: { type: 'plain_text', text: '✅ Przyjmij' },
            style: 'primary',
            action_id: 'accept_ticket',
            value: ticket.id
          },
          {
            type: 'button',
            text: { type: 'plain_text', text: '❌ Odrzuć' },
            style: 'danger',
            action_id: 'reject_ticket',
            value: ticket.id
          }
        ]
      }
    ]
  });
});

6. AI-Powered Bots - integracja z GPT-4 i Claude

Kontekstowy AI Asystent w Discord

To właśnie odróżnia dobrego bota od wyjątkowego - pamięć konwersacji i prawdziwa inteligencja:

import OpenAI from 'openai';
import { Collection } from 'discord.js';

const openai = new OpenAI({ apiKey: process.env.OPENAI_KEY });

// Przechowuj historię konwersacji per user (Redis)
const conversations = new Collection<string, OpenAI.ChatCompletionMessageParam[]>();

export async function aiChat(
  userId: string,
  userMessage: string,
  systemPrompt: string
): Promise<string> {
  // Pobierz historię lub zainicjuj nową
  const history = conversations.get(userId) ?? [];

  // System prompt definiuje "osobowość" bota
  const messages: OpenAI.ChatCompletionMessageParam[] = [
    {
      role: 'system',
      content: systemPrompt || `Jesteś pomocnym asystentem na serwerze Discord. 
        Odpowiadaj zwięźle (max 300 słów), używaj emoji gdzie stosowne.
        Jeśli pytanie wykracza poza zakres serwera, grzecznie przekieruj.`
    },
    ...history.slice(-10), // Ostatnie 10 wiadomości (context window)
    { role: 'user', content: userMessage }
  ];

  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages,
    max_tokens: 500,
    temperature: 0.7
  });

  const aiReply = response.choices[0].message.content ?? 'Nie udało się wygenerować odpowiedzi.';

  // Zapisz do historii
  history.push(
    { role: 'user', content: userMessage },
    { role: 'assistant', content: aiReply }
  );
  conversations.set(userId, history);

  // Wyczyść historię po 30 minutach nieaktywności
  setTimeout(() => conversations.delete(userId), 30 * 60 * 1000);

  return aiReply;
}

// Discord command
bot.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;
  if (interaction.commandName !== 'ask') return;

  await interaction.deferReply();

  const question = interaction.options.getString('question', true);
  const serverConfig = await getServerConfig(interaction.guildId!);

  const response = await aiChat(
    interaction.user.id,
    question,
    serverConfig.aiSystemPrompt
  );

  await interaction.editReply(response);
});

Image Generation Bot (DALL-E 3 + Discord)

import { AttachmentBuilder } from 'discord.js';

async function generateImage(prompt: string): Promise<Buffer> {
  const response = await openai.images.generate({
    model: 'dall-e-3',
    prompt,
    size: '1024x1024',
    quality: 'standard',
    n: 1
  });

  const imageUrl = response.data[0].url!;
  const imageResponse = await fetch(imageUrl);
  return Buffer.from(await imageResponse.arrayBuffer());
}

// Slash command
// /imagine prompt:futuristic city at night, neon lights, cyberpunk style
export async function execute(interaction: ChatInputCommandInteraction) {
  await interaction.deferReply();

  const prompt = interaction.options.getString('prompt', true);

  // Basic content filter
  if (prompt.length > 1000) {
    return interaction.editReply('❌ Prompt za długi (max 1000 znaków).');
  }

  const imageBuffer = await generateImage(prompt);
  const attachment = new AttachmentBuilder(imageBuffer, { name: 'generated.png' });

  await interaction.editReply({
    content: `🎨 Wygenerowano dla: **${prompt}**`,
    files: [attachment]
  });
}

7. Databases & Caching - MongoDB, Redis, PostgreSQL

Kiedy używać której bazy?

MongoDB:
  ✓ Flexible schema (różne konfiguracje per serwer)
  ✓ Nested documents (user inventory w jednym document)
  ✓ Easy horizontal scaling
  → Używaj dla: User data, server config, logs, inventory

Redis:
  ✓ In-memory = microsecond latency
  ✓ TTL (auto-expiry) dla cooldownów
  ✓ Pub/Sub dla multi-shard botów
  → Używaj dla: Cooldowns, rate limits, sessions, cache

PostgreSQL:
  ✓ ACID transactions (payments!)
  ✓ Complex queries z JOINs
  ✓ Strong consistency
  → Używaj dla: Financial transactions, audit logs

Economy System w MongoDB + Redis

// Pełny economy system: balance, daily, transfer

export class EconomyService {
  private db: Collection;
  private redis: Redis;

  constructor(db: Collection, redis: Redis) {
    this.db = db;
    this.redis = redis;
  }

  async getBalance(userId: string, guildId: string): Promise<number> {
    // Cache first (Redis)
    const cached = await this.redis.get(`balance:${guildId}:${userId}`);
    if (cached) return parseInt(cached);

    // Fallback to MongoDB
    const user = await this.db.findOne({ userId, guildId });
    const balance = user?.balance ?? 0;

    // Cache na 60 sekund
    await this.redis.setex(`balance:${guildId}:${userId}`, 60, balance.toString());
    return balance;
  }

  async claimDaily(userId: string, guildId: string): Promise<{ success: boolean; amount?: number; timeLeft?: number }> {
    const cooldownKey = `daily:${guildId}:${userId}`;
    const ttl = await this.redis.ttl(cooldownKey);

    if (ttl > 0) {
      return { success: false, timeLeft: ttl };
    }

    const DAILY_AMOUNT = 100;
    const COOLDOWN = 86400; // 24h w sekundach

    // Atomic update w MongoDB
    await this.db.updateOne(
      { userId, guildId },
      { 
        $inc: { balance: DAILY_AMOUNT, totalEarned: DAILY_AMOUNT },
        $setOnInsert: { createdAt: new Date() }
      },
      { upsert: true }
    );

    // Invalidate cache
    await this.redis.del(`balance:${guildId}:${userId}`);
    
    // Set cooldown
    await this.redis.setex(cooldownKey, COOLDOWN, '1');

    return { success: true, amount: DAILY_AMOUNT };
  }

  async transfer(
    fromUserId: string,
    toUserId: string,
    guildId: string,
    amount: number
  ): Promise<{ success: boolean; error?: string }> {
    const balance = await this.getBalance(fromUserId, guildId);

    if (balance < amount) {
      return { success: false, error: 'Niewystarczające środki' };
    }

    if (amount <= 0) {
      return { success: false, error: 'Kwota musi być większa niż 0' };
    }

    // Atomic transfer (MongoDB transactions)
    const session = this.db.client.startSession();
    
    try {
      await session.withTransaction(async () => {
        await this.db.updateOne(
          { userId: fromUserId, guildId },
          { $inc: { balance: -amount } },
          { session }
        );
        await this.db.updateOne(
          { userId: toUserId, guildId },
          { $inc: { balance: amount }, $setOnInsert: { createdAt: new Date() } },
          { upsert: true, session }
        );
      });

      // Invalidate caches
      await Promise.all([
        this.redis.del(`balance:${guildId}:${fromUserId}`),
        this.redis.del(`balance:${guildId}:${toUserId}`)
      ]);

      return { success: true };
    } finally {
      await session.endSession();
    }
  }
}

8. Payment Integration - Stripe w botach Discord/Telegram

Premium Bot Subscriptions z Stripe

Jeden z najpopularniejszych modeli monetyzacji botów - subscription za premium features:

import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-04-10'
});

// Tworzy checkout session dla premium subscription
export async function createPremiumCheckout(
  discordUserId: string,
  guildId: string,
  tier: 'basic' | 'pro' | 'enterprise'
): Promise<string> {
  const PRICE_IDS = {
    basic: 'price_BASIC_ID',
    pro: 'price_PRO_ID',
    enterprise: 'price_ENTERPRISE_ID'
  };

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    line_items: [{ price: PRICE_IDS[tier], quantity: 1 }],
    success_url: `${process.env.SITE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.SITE_URL}/cancel`,
    metadata: {
      discordUserId,
      guildId,
      tier
    },
    subscription_data: {
      metadata: { discordUserId, guildId }
    }
  });

  return session.url!;
}

// Webhook handler - aktywuje premium po zapłacie
export async function handleStripeWebhook(
  rawBody: Buffer,
  signature: string
): Promise<void> {
  const event = stripe.webhooks.constructEvent(
    rawBody,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET!
  );

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      const { discordUserId, guildId, tier } = session.metadata!;

      await activatePremium(discordUserId, guildId, tier);
      await notifyUserInDiscord(discordUserId, tier);
      break;
    }

    case 'customer.subscription.deleted': {
      const subscription = event.data.object as Stripe.Subscription;
      const { discordUserId, guildId } = subscription.metadata;

      await deactivatePremium(discordUserId, guildId);
      break;
    }
  }
}

9. Skalowanie i hosting production botów

Gdzie hostować bota?

Small Bot (1-100 serwerów):
  → Railway.app: $5/miesiąc, auto-deploy z GitHub, zero config
  → Fly.io: Free tier dostępny, great dla małych botów
  → Render: Free tier (z sleep po 15 min nieaktywności)

Medium Bot (100-1000 serwerów):
  → Railway Pro: $20/miesiąc, persistent storage
  → DigitalOcean Droplet: $6-12/miesiąc, pełna kontrola
  → Hetzner VPS: €3.29/miesiąc, najlepszy stosunek ceny do jakości w EU

Large Bot (1000+ serwerów):
  → Discord Sharding (wymagane powyżej 2500 serwerów)
  → Kubernetes (k8s): Auto-scaling, zero downtime deploys
  → Redis Cluster: Distributed state dla wielu shardów

Sharding - skalowanie Discord bota

// src/shard-manager.ts
import { ShardingManager } from 'discord.js';
import path from 'path';

const manager = new ShardingManager(
  path.join(__dirname, 'bot.js'),
  {
    token: process.env.DISCORD_TOKEN!,
    totalShards: 'auto', // Discord oblicza optymalną liczbę
    respawn: true // Auto-restart crashed shards
  }
);

manager.on('shardCreate', (shard) => {
  console.log(`🔷 Shard #${shard.id} uruchomiony`);

  shard.on('ready', () =>
    console.log(`✅ Shard #${shard.id} gotowy`)
  );

  shard.on('disconnect', () =>
    console.warn(`⚠️ Shard #${shard.id} rozłączony - próba reconnect...`)
  );
});

manager.spawn();

PM2 Configuration (production process manager)

// ecosystem.config.json
{
  "apps": [
    {
      "name": "discord-bot",
      "script": "dist/index.js",
      "instances": 1,
      "autorestart": true,
      "watch": false,
      "max_memory_restart": "512M",
      "env": {
        "NODE_ENV": "production"
      },
      "log_date_format": "YYYY-MM-DD HH:mm:ss Z",
      "error_file": "logs/error.log",
      "out_file": "logs/out.log",
      "exp_backoff_restart_delay": 100
    }
  ]
}

10. Case Studies - prawdziwe projekty

Case Study #1: Gaming Community Bot (Discord)

Klient: Community gamingowe, 15,000 memberów

Problem:

  • Moderacja przez 3 osoby pracujące w różnych strefach czasowych
  • Brak automatycznego systemu levelowania i nagród
  • Wysoki churn - nowi użytkownicy nie widzieli powodu do pozostania

Rozwiązanie (stack: Discord.js, MongoDB, Redis):

System moderacji:
  → Auto-ban za spam (5+ wiadomości / 5 sekund)
  → Auto-timeout za badwords (3 strikes system)
  → Raid protection (flood nowych joinów = lockdown)
  → Mod logs w dedykowanym kanale

Economy & Gamification:
  → XP za aktywność (wiadomości, voice time)
  → Role rewards: Newbie → Regular → VIP → Legend
  → Daily rewards (100-500 coins)
  → Shop: custom roles, kanały, emotki

Onboarding:
  → Welcome DM z tutorialem
  → Verify system (role po przeczytaniu regulaminu)
  → First-message reward (bonus coins)

Wyniki po 30 dniach:

Metryki przed:              Metryki po:
Czas odpowiedzi mod: 45 min → 0.2 sekundy (auto-mod)
Daily active users: 234     → 891 (+281%)
Churn rate: 68%             → 31% (-54%)
Mod team hours: 12h/dzień   → 2h/dzień (-83%)

Case Study #2: E-commerce Customer Support (Telegram)

Klient: Sklep online, 2,000 zamówień/miesiąc

Problem:

  • Klienci pytają o status zamówienia przez email (odpowiedź: 24-48h)
  • Customer service overwhelmed przed Black Friday
  • Brak automatycznych powiadomień o statusie

Rozwiązanie (stack: Telegraf, PostgreSQL, Stripe webhooks):

// Order tracking bot
bot.command('status', async (ctx) => {
  const orderNumber = ctx.message.text.split(' ')[1];
  
  if (!orderNumber) {
    return ctx.reply('Podaj numer zamówienia: /status ORD-123456');
  }

  const order = await db.query(
    'SELECT * FROM orders WHERE order_number = $1 AND telegram_user_id = $2',
    [orderNumber, ctx.from.id.toString()]
  );

  if (!order.rows[0]) {
    return ctx.reply('❌ Nie znaleziono zamówienia lub nie masz do niego dostępu.');
  }

  const o = order.rows[0];
  const statusEmoji = {
    pending: '⏳',
    processing: '🔄',
    shipped: '📦',
    delivered: '✅',
    cancelled: '❌'
  }[o.status] ?? '❓';

  await ctx.reply(
    `${statusEmoji} *Zamówienie ${o.order_number}*\n\n` +
    `Status: ${o.status}\n` +
    `Produkt: ${o.product_name}\n` +
    `Data zamówienia: ${o.created_at.toLocaleDateString('pl-PL')}\n` +
    (o.tracking_number ? `Śledzenie: \`${o.tracking_number}\`` : ''),
    { parse_mode: 'Markdown' }
  );
});

Wyniki:

Tickety email:     1,240/miesiąc → 89/miesiąc (-93%)
Czas odpowiedzi:  24-48h        → instant
Customer satisfaction: 3.2/5   → 4.7/5
Support team cost: $2,400/mies  → $600/mies (-75%)

Case Study #3: HR Bot (Slack)

Klient: Firma tech, 80 pracowników

Problem:

  • Urlopy zgłaszane przez email do HR (chaos)
  • Brak visibility kto jest dostępny
  • Onboarding nowych pracowników: papierologia, manuale

Rozwiązanie (stack: Bolt.js, PostgreSQL, Google Calendar API):

Leave Management:
  /urlop start:2026-06-01 end:2026-06-07 type:wypoczynek
  → Modal do potwierdzenia
  → Auto-notification do managera (button: Akceptuj/Odrzuć)
  → Google Calendar event po akceptacji
  → Aktualizacja channel topic: "Jan (urlop 1-7 cze)"

Team Availability Dashboard:
  /kto-jest - rich embed z listą kto jest/nie ma dziś
  /zespol-week - plan tygodnia z dostępnością

New Employee Onboarding:
  /onboarding @newjoiner
  → Automatyczne zaproszenia do channelów
  → DM z linkami do dokumentów
  → Lista checklisty (confirm each step)
  → Przypomnienia po 1, 7, 30 dniach

Wyniki:

HR admin time: 12h/tydzień → 2h/tydzień (-83%)
Urlopy przez email: 0 (100% przez Slack)
Onboarding time: 3 dni → 4 godziny (-94%)
Manager satisfaction: "Nareszcie porządek"

11. Pełny ekosystem: Multi-Platform Bot Architecture

Dlaczego warto myśleć multi-platform od początku?

Dobrze zaprojektowany bot to platforma, nie tylko kod na jedną usługę. Oto jak buduję architekturę, która pozwala na łatwe dodawanie nowych platform:

// Core Bot Service (platform-agnostic)
interface BotMessage {
  userId: string;
  platformUserId: string;
  platform: 'discord' | 'telegram' | 'slack' | 'whatsapp';
  content: string;
  metadata?: Record<string, unknown>;
}

interface BotResponse {
  text: string;
  attachments?: Attachment[];
  buttons?: Button[];
  metadata?: Record<string, unknown>;
}

// Business logic jest NIEZALEŻNA od platformy
class CommandRouter {
  async route(message: BotMessage): Promise<BotResponse> {
    if (message.content.startsWith('/help')) {
      return this.handleHelp(message);
    }
    if (message.content.startsWith('/order')) {
      return this.handleOrder(message);
    }
    return this.handleAI(message);
  }
}

// Platform adapters tłumaczą na specyficzne API
class DiscordAdapter {
  async sendResponse(channelId: string, response: BotResponse) {
    const embed = new EmbedBuilder().setDescription(response.text);
    await channel.send({ embeds: [embed] });
  }
}

class TelegramAdapter {
  async sendResponse(chatId: number, response: BotResponse) {
    await this.bot.telegram.sendMessage(chatId, response.text, {
      parse_mode: 'Markdown'
    });
  }
}

// Dodanie nowej platformy = nowy adapter. Business logic bez zmian.
class WhatsAppAdapter { /* ... */ }
class TeamsAdapter { /* ... */ }

Roadmapa: Od pierwszego bota do platformy

Faza 1 (Tydzień 1-2): MVP Bot
  → Jeden Discord bot, podstawowe komendy
  → MongoDB dla user data
  → Deploy na Railway

Faza 2 (Tydzień 3-4): Feature Rich
  → Economy system
  → AI integration (GPT-4)
  → Auto-moderation
  → Premium subscriptions (Stripe)

Faza 3 (Miesiąc 2): Multi-Platform
  → Telegram bot (ten sam core, nowy adapter)
  → Slack bot
  → Shared database, shared business logic

Faza 4 (Miesiąc 3+): Platform & Scale
  → Sharding (jeśli 1000+ Discord servers)
  → Dashboard admin (Next.js)
  → Analytics (ile komend dziennie, revenue, etc.)
  → API dla external integrations

Podsumowanie - Bot Development to nie tylko Discord

Przez ostatnie lata boty stały się prawdziwą infrastrukturą biznesową. Nie chodzi już tylko o "bota, który wita nowych memberów". Chodzi o:

  • 🔧 Automatyzacje oszczędzające dziesiątki godzin pracy tygodniowo
  • 💰 Systemy payments przetwarzające tysiące dolarów dziennie
  • 🤖 AI asystentów zastępujących działy customer support
  • 📊 Analytics platformy dające wgląd w community behavior
  • 🌐 Multi-platform ecosystemy działające jednocześnie na Discord, Telegram, Slack

Każdy projekt jest inny. Czasem potrzebujesz prostego moderation bota w 2 godziny. Czasem zaawansowanej platformy z AI, payments i multi-platform support budowanej przez tygodnie.

Kluczowe lekcje z moich projektów:

  1. Zawsze zacznij od architektury - trudno przepisać bota gdy ma 10,000 użytkowników
  2. Redis jest obowiązkowy - baza danych nie wytrzyma rate limitów bez cachingu
  3. Webhooks > Polling - dla production zawsze webhooks (mniejsze latency, mniej zasobów)
  4. Graceful shutdown - bot musi umieć się zamknąć bez utraty danych
  5. Monitoring i alerty - wiedz o problemach zanim użytkownicy zgłoszą

Szukasz custom bota?

Jeśli masz projekt, który wymaga automatyzacji - czy to Discord community, sklep online na Telegramie, czy workflow w Slacku - chętnie porozmawiam.

Tworzę boty od podstaw, z pełnym customizacją, production-ready architekturą i wsparciem post-launch.

Kontakt / Wycena projektu


Artykuł napisany na podstawie doświadczeń z dziesiątek projektów bot development. Stack użyty w projektach: Discord.js v14, Telegraf v4, Bolt.js, Node.js, TypeScript, MongoDB, Redis, PostgreSQL, Stripe, OpenAI GPT-4.

Bot Development & Automation 2026: Discord, Telegram, Slack i nie tylko - kompletny przewodnik - NextGenCode Blog | NextGenCode House of Technology - Full-Stack Ecosystem Architect