Skip to main content

Multi-platform AI chatbot with Bring Your Own Key support — Ollama, OpenAI, Anthropic, Gemini, Groq, OpenRouter

Project description

BotServer

A multi-platform AI chatbot that connects Discord, Telegram, and Signal to locally-running Ollama LLMs.

Zero cloud AI dependencies — all inference runs on your own hardware through a local Ollama server. Your conversations stay private, your data stays local.

Discord ─┐
Telegram ─┤──▶ BotServer ──▶ Ollama (local) ──▶ LLM on your GPU
Signal  ──┘

Table of Contents


Features

Feature Discord Telegram Signal
Streaming responses (live-edit) Yes (0.6s) Yes (1.0s) Buffered
Conversation history (10 msgs) Yes Yes Yes
Context-aware prompts Yes Yes Yes
AI mode switching Yes Yes Yes
Custom model per user Yes Yes Yes
Web search + AI summary Yes Yes Yes
Deep thinking (DeepSeek-R1) Spoiler tags Spoiler tags Separate msg
Music playback Yes (voice) YouTube links
News feeds (RSS) Yes Yes
Access control Open Location-based Phone-based
Typing indicators Yes
Group support Yes Yes Yes (commands only)
Output guardrails (PII/secrets) Yes Yes Yes
Input guardrails (injection) Yes Yes Yes

Architecture

User Message
     │
     ▼
┌─────────────────────────────────────────────┐
│  Platform Bot                                │
│  (discord_bot / telegram_bot / signal_bot)   │
└─────────────┬───────────────────────────────┘
              │
              ▼
┌─────────────────────────┐
│  Guardrails (Input)     │ ── Prompt injection detection
│  guardrails.py          │ ── Content safety checks
│                         │ ── Rate limiting
└─────────────┬───────────┘
              │
              ▼
┌─────────────────────────┐
│  Context Analyzer        │ ── Topic detection (8 categories)
│  context_analyzer.py     │ ── Intent classification
│                          │ ── Entity extraction
│                          │ ── Pronoun referent resolution
└─────────────┬────────────┘
              │
              ▼
┌─────────────────────────┐
│  Ollama Handler          │ ── Sync & async streaming
│  ollama_handler.py       │ ── /api/generate & /api/chat
│                          │ ── Model keep-alive (VRAM)
└─────────────┬────────────┘
              │
              ▼
┌─────────────────────────┐
│  Think Parser            │ ── DeepSeek-R1 <think> tag parsing
│  think_parser.py         │ ── Streaming state machine
└─────────────┬────────────┘
              │
              ▼
┌─────────────────────────┐
│  Guardrails (Output)     │ ── PII redaction
│  guardrails.py           │ ── API key/token scrubbing
│                          │ ── Infrastructure URL filtering
└─────────────┬────────────┘
              │
              ▼
     Platform Response
     (formatted, split, streamed)

Module Breakdown

Module Lines Purpose
discord_bot.py ~1070 Discord bot with streaming, music, news
telegram_bot.py ~1270 Telegram bot with location-based access control
signal_bot.py ~1070 Signal bot via signal-cli JSON-RPC (fully async)
ollama_handler.py ~230 Ollama API wrapper (sync + async streaming)
context_analyzer.py ~390 Keyword-based conversation analysis (zero ML overhead)
think_parser.py ~120 Streaming <think> tag state machine parser
web_search.py ~85 DuckDuckGo search with retry logic
guardrails.py ~590 5-layer input/output security system
access_store.py ~160 Thread-safe persistent user approval store

Prerequisites

  • Python 3.10+
  • Ollama installed and running locally
  • At least one LLM pulled (e.g., ollama pull llama3.1:8b)
  • For Discord: A Discord bot token (Discord Developer Portal)
  • For Telegram: A bot token from @BotFather
  • For Signal: signal-cli installed and linked to a phone number
  • For Discord music: FFmpeg installed and in PATH

Installation

  1. Clone the repository:

    git clone https://github.com/your-username/BotServer.git
    cd BotServer
    
  2. Install Python dependencies:

    pip install discord.py pyTelegramBotAPI aiohttp requests feedparser yt-dlp qrcode duckduckgo-search python-dotenv
    
  3. Pull Ollama models:

    ollama pull llama3.1:8b        # General mode
    ollama pull deepseek-r1:8b     # Reasoning mode
    ollama pull qwen3-coder        # Coding mode (adjust tag as needed)
    
  4. Create your .env file (see Configuration below).

  5. Start Ollama (if not already running):

    ollama serve
    

Configuration

Create a .env file in the project root with the following variables:

# ── Discord ──────────────────────────────────
DISCORD_BOT_TOKEN=your_discord_bot_token_here

# ── Telegram ─────────────────────────────────
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
TELEGRAM_ADMIN_ID=your_numeric_telegram_user_id

# ── Signal ───────────────────────────────────
SIGNAL_PHONE_NUMBER=+1234567890          # Bot's linked phone number
SIGNAL_CLI_HOST=localhost                # signal-cli daemon host
SIGNAL_CLI_PORT=7583                     # signal-cli daemon port
SIGNAL_ADMIN_NUMBER=+1234567890          # Admin's phone number

# ── Ollama ───────────────────────────────────
OLLAMA_BASE_URL=http://localhost:11434   # Ollama server URL
OLLAMA_DEFAULT_MODEL=llama3.1:8b         # Default model for general mode

Note: Only configure the platforms you plan to use. Each bot loads only its own variables.


Running the Bots

Run individually

python discord_bot.py      # Starts Discord bot
python telegram_bot.py     # Starts Telegram bot
python signal_bot.py       # Starts Signal bot (requires signal-cli daemon)

Run all at once

Windows (batch):

botserver.bat

This launches each bot in its own terminal window, including the signal-cli daemon.

Windows (PowerShell):

.\start_all.ps1

Monitors all processes and reports exits. Ctrl+C stops everything cleanly.

Linux/macOS:

./start_all.sh

Runs all bots in background, traps SIGINT/SIGTERM for clean shutdown.

Signal-specific setup

Signal requires a running signal-cli daemon:

signal-cli -a +YOUR_NUMBER daemon --tcp 7583

To link a new device, use the included helper:

python signal_link.py    # Generates QR code for Signal linking

Each bot binds a singleton port (Discord: 47001, Telegram: 47002, Signal: 47003) to prevent duplicate instances.


Commands Reference

Chat & Modes

Command Discord Telegram Signal Description
Switch to General !chat /chat /chat llama3.1:8b — general assistant
Switch to Coding !coder /coder /coder qwen3-coder — code-focused
Switch to Reasoning !think /think /think deepseek-r1:8b — step-by-step
Toggle thinking display !deepthink /deepthink /deepthink Show/hide <think> reasoning
Reset history !reset /reset /reset Clear conversation memory

Questions & Search

Command Discord Telegram Signal Description
One-shot question !ask <q> /ask <q> /ask <q> No history, direct answer
Problem solver !solve <q> /solve <q> /solve <q> Uses deepseek-r1
Web search !search <q> /search <q> /search <q> DuckDuckGo + AI summary

Model Management

Command Discord Telegram Signal Description
Show current model !model /model /model Displays active mode & model
Set custom model !setmodel <name> /setmodel <name> /setmodel <name> Override with any Ollama model
List available models !models /models /models Fetches live list from Ollama

!setmodel also accepts a number (e.g., !setmodel 3) to pick from the models list.

Music (Discord only)

Command Description
!play <song> Search YouTube and play in voice channel
!skip Skip current track
!pause / !resume Pause or resume playback
!stop Stop and disconnect from voice
!queue Show upcoming tracks
!volume <0-100> Set playback volume

Music (Signal)

Command Description
/music <song> Returns YouTube search results
/recommend <mood/genre> AI-generated music suggestions

News Feeds

Command Platform Description
!news [category] [count] Discord Google News RSS headlines
/news [category] [count] Signal Google News RSS headlines

Categories: top, tech, science, world, business

Admin Commands (Telegram & Signal)

Command Description
/approve [id] Approve a pending user
/deny [id] Deny a pending user
/revoke <id> Revoke an approved user
/pending List pending access requests
/users List all approved users

Default behavior

  • Discord: @mention the bot or type in its channel for a streaming conversation
  • Telegram: Any message from an approved user gets a streaming AI response
  • Signal DMs: Plain text messages get streaming AI responses
  • Signal Groups: Only /commands are processed (no free-text chat)

AI Modes

BotServer offers three switchable AI personalities per user:

General Mode (default)

  • Model: llama3.1:8b
  • Best for: Everyday questions, conversation, general knowledge
  • System prompt: Helpful, friendly assistant with conversation context awareness

Coding Mode

  • Model: qwen3-coder:480b-cloud
  • Best for: Code generation, debugging, technical explanations
  • System prompt: Expert programmer focused on clean, efficient code

Reasoning Mode

  • Model: deepseek-r1:8b
  • Best for: Complex problems, math, logic, step-by-step analysis
  • System prompt: Deep analytical thinker showing reasoning process
  • Special: Produces <think>...</think> blocks showing internal reasoning

Users can also override their model with !setmodel / /setmodel to use any model available on their Ollama server.


How Streaming Works

All bots stream responses token-by-token from Ollama, but display them differently:

Discord edits the reply message every 0.6 seconds with accumulated tokens. If a response exceeds 2000 characters, it splits into multiple messages. While generating, the bot shows rotating "thinking" status phrases (81 unique phrases).

Telegram edits the reply message every 1.0 seconds (longer interval to respect Telegram rate limits). Responses are capped at 4000 characters per message.

Signal buffers the entire response since Signal doesn't support message editing. It sends typing indicators while generating. Long responses are split at 4000-character boundaries.

After every response, performance stats are appended:

⏱ 3.2s  |  ⚙ llama3.1:8b  |  ↑ 142 tokens  |  ↓ 256 tokens  |  42.1 tok/s

Context Awareness

BotServer enriches every prompt with conversation intelligence — without making extra LLM calls:

  1. Topic Detection — Scans the last 6 messages for keywords across 8 categories (programming, math, science, writing, business, health, gaming, music) and tells the model what the conversation is about.

  2. Intent Classification — Determines if the user is asking a question, debugging, brainstorming, learning, or just chatting. The model adjusts its response style accordingly.

  3. Entity Extraction — Identifies repeated nouns and key terms, helping the model maintain focus on what matters.

  4. Referent Resolution — When a user says "fix it" or "explain that," the analyzer determines what "it" or "that" refers to from conversation history.

  5. Conversation Type — Labels the chat as debugging, Q&A, learning, brainstorming, or casual — giving the model meta-awareness of the interaction style.

  6. Geolocation (Telegram only) — If the user shared their location, it's included in the system prompt for location-aware responses.

All analysis is keyword/pattern-based (regex + word frequency), adding negligible latency.


Security & Guardrails

BotServer implements a 5-layer security system via guardrails.py:

Layer 1: Input Filtering

  • Prompt injection detection — Catches "forget previous instructions," "act as DAN," "bypass rules," and other common jailbreak patterns
  • Encoded evasion detection — Flags Base64, hex escapes, and HTML entity attempts
  • Educational context awareness — Avoids false positives on legitimate questions (e.g., "how to ignore errors in bash")
  • Rate limiting — 3 suspicious probes per user in 10 minutes triggers a 30-minute block

Layer 2: Content Safety

  • Blocks requests involving violence, self-harm, CSAM, illegal activity, and hate speech
  • Severity levels: critical, high, medium, low

Layer 3: Output Filtering

  • PII redaction — SSNs, credit card numbers
  • Secret scrubbing — API keys, JWT tokens, bot tokens, environment variables
  • Infrastructure hiding — Localhost URLs, file paths, internal endpoints
  • Smart context — Preserves code blocks and avoids redacting model self-references

Layer 4: Prompt-Level Safety

  • A SAFETY_GUARDRAIL string is appended to every prompt sent to Ollama, instructing the model to refuse harmful requests

Layer 5: Operational Security

  • Log sanitization (redacts emails, tokens, phone numbers, URLs)
  • Message length enforcement (4000 chars message, 200 chars search query, 500 chars command arg)

Access Control

Discord

Open to all server members — no approval needed. Security is handled at the Discord server level.

Telegram

New users go through a location-based approval flow:

  1. User sends /start — bot asks them to share their location
  2. User shares location via keyboard button
  3. Request goes to pending with name, username, and coordinates
  4. Admin receives notification and reviews with /pending
  5. Admin runs /approve or /deny
  6. Approved users can chat freely; denied users are removed

Signal

Phone-number-based approval:

  1. New user sends a message — bot notifies admin
  2. Admin approves with /approve +phone_number
  3. Approved users can chat in DMs and use commands in groups

All approval data persists in approved_users.json (thread-safe, auto-saving).


Music Playback (Discord)

Discord bot includes a full music player with queue management:

  • Searches YouTube via yt-dlp and streams audio into voice channels
  • Queue system — add multiple songs, skip, view upcoming tracks
  • Volume control — adjustable 0–100%
  • Auto-detection — finds FFmpeg from PATH or common Windows install locations
  • Requires the bot to be in a voice channel (auto-joins when you use !play)

News Feeds

Discord and Signal bots can fetch headlines from Google News RSS:

!news tech 5       # 5 latest tech headlines (Discord)
/news science 3    # 3 latest science headlines (Signal)

Available categories: top (default), tech, science, world, business


Project Structure

BotServer/
├── discord_bot.py        # Discord bot (streaming, music, news)
├── telegram_bot.py       # Telegram bot (location-based access)
├── signal_bot.py         # Signal bot (async JSON-RPC)
├── ollama_handler.py     # Ollama API wrapper
├── context_analyzer.py   # Conversation intelligence
├── think_parser.py       # DeepSeek-R1 <think> tag parser
├── web_search.py         # DuckDuckGo search integration
├── guardrails.py         # 5-layer security system
├── access_store.py       # Persistent user approval store
├── gen_qr.py             # QR code generator utility
├── signal_link.py        # Signal device linking helper
├── approved_users.json   # User approval data (auto-generated)
├── .env                  # Configuration (create manually)
├── botserver.bat         # Windows launcher (batch)
├── start_all.ps1         # Windows launcher (PowerShell)
├── start_all.sh          # Linux/macOS launcher
└── CLAUDE.md             # AI coding assistant instructions

Troubleshooting

Bot won't start — "Address already in use" Each bot uses a singleton port (47001/47002/47003). Another instance is already running. Kill the existing process or restart.

Ollama connection refused Make sure Ollama is running (ollama serve) and the OLLAMA_BASE_URL in .env matches your setup.

Slow first response The first request after startup loads the model into VRAM. BotServer pre-loads models with keep_alive() to minimize this. Subsequent responses are fast.

Signal bot can't connect Ensure signal-cli is running as a daemon: signal-cli -a +YOUR_NUMBER daemon --tcp 7583. The bot auto-reconnects with exponential backoff if the connection drops.

Discord music not working FFmpeg must be installed and accessible. On Windows, the bot also checks C:\ffmpeg\bin\ and C:\Program Files\ffmpeg\bin\. Verify with ffmpeg -version.

Telegram bot not responding to messages The user may not be approved. Check /pending as admin, or verify the user completed the location-sharing step.

"Model not found" errors Run ollama list to see available models. Pull missing ones with ollama pull <model_name>.


State Management

All per-user state is stored in memory (module-level dictionaries) and is not persisted across restarts:

  • user_modes[user_id] — Current AI mode (general / coding / reasoning)
  • user_custom_models[user_id] — Custom model override
  • deep_thinking_enabled[user_id] — Whether to show <think> blocks
  • conversation_history[key] — Last 10 messages per user

The only persisted state is approved_users.json for access control.


License

This project is provided as-is for personal and educational use.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rotbot-1.0.0.tar.gz (254.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rotbot-1.0.0-py3-none-any.whl (118.8 kB view details)

Uploaded Python 3

File details

Details for the file rotbot-1.0.0.tar.gz.

File metadata

  • Download URL: rotbot-1.0.0.tar.gz
  • Upload date:
  • Size: 254.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for rotbot-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3bbcf80f84bec07040b951c00736e4245327f882d0c16105d2bab298a75d6b3d
MD5 bd58982976ffe4905231bc933d9f477e
BLAKE2b-256 9077b4f01c3947f19460ae06598d63a529c503ea106e8b879a3208543b8a8415

See more details on using hashes here.

File details

Details for the file rotbot-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: rotbot-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 118.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for rotbot-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f3aa9f0525c73f126bc239d3bc751fc4c09a53117c042e9a3562c3710cf3ca4c
MD5 82bd0967d39d012601dbbcb4bb0a1e8c
BLAKE2b-256 f78158c4a03b15f865452fbf1bea009b81d9220aacfee1c410e925847cab2f47

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page