tom_chattools
A platform-agnostic chat abstraction for sending and receiving messages, with a unified message model and a Telegram implementation behind a single `ChatAPI` interface.
Overview
`tom_chattools` gives Tom one interface for talking to messaging platforms. The abstract `ChatAPI` and unified `ChatMessage`, `ChatSender`, and `ChatResponse` types let calling code send and receive messages without binding to a specific service. Concrete platforms are selected through `ChatAPI.connect()`, with Telegram supported today via the Bot API and real-time updates delivered through an `onMessage` stream. The factory pattern leaves room for additional platforms behind the same contract.
What it enables
Enables Platform-agnostic messaging, Telegram bot integration, Streaming message updates.
Relationships
Standalone — no declared relationships.
Tom Chattools
A platform-agnostic chat API library for Dart that provides a unified interface for sending and receiving messages across different chat platforms.
Features
- **Abstract ChatAPI** - Platform-independent interface for chat operations
- **Telegram Support** - Full Telegram Bot API integration via televerse
- **Message Abstraction** - Unified `ChatMessage`, `ChatSender`, and `ChatResponse` classes
- **Streaming Updates** - Real-time message notifications via `onMessage` stream
- **Factory Pattern** - Create appropriate implementation via `ChatAPI.connect()`
Getting Started
Prerequisites
- Dart SDK 3.0 or higher
- A Telegram bot token (for Telegram integration)
Installation
Add `tom_chattools` to your `pubspec.yaml`:
dependencies:
tom_chattools:
path: ../path/to/tom_chattools # Or use git reference
Telegram Setup
To connect to Telegram, you need a bot token from [@BotFather](https://t.me/BotFather).
Step 1: Create a Bot
1. Open Telegram and search for **@BotFather** (the official Telegram bot) 2. Start a conversation and send `/newbot` 3. Follow the prompts: - Choose a display name (e.g., "My Assistant") - Choose a username (must end in `bot`, e.g., `my_assistant_bot`) 4. BotFather will give you an API token like:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz
5. **Save this token securely** - it grants full access to your bot
Step 2: Get Your Chat ID
To send/receive messages from a specific chat, you need the chat ID:
**For personal chats:** 1. Message your bot first (search for its username in Telegram) 2. Run your bot with polling enabled (see example below) 3. Send a message to your bot 4. Check the `sender.id` in the received message - that's your chat ID
**Using a helper bot:** 1. Forward any message to [@userinfobot](https://t.me/userinfobot) 2. It will reply with your user ID (same as chat ID for 1:1 chats)
**For groups:** 1. Add your bot to the group 2. The group chat ID will appear in incoming messages (usually a negative number)
Step 3: Connect and Use
import 'package:tom_chattools/tom_chattools.dart';
void main() async {
// Create configuration (just authentication)
final config = TelegramChatConfig(
token: 'YOUR_BOT_TOKEN',
usePolling: true, // Use long polling for updates
);
// Connect to Telegram
final chat = await ChatAPI.connect(config);
// Define who to communicate with
final receiver = ChatReceiver.id('YOUR_CHAT_ID');
// Send a message
await chat.sendMessage(receiver, 'Hello from Dart!');
// Listen for incoming messages
chat.onMessage.listen((message) {
print('Received: ${message.text} from ${message.sender.name}');
// Echo back to the sender
final sender = ChatReceiver.id(message.sender.id);
chat.sendMessage(sender, 'You said: ${message.text}');
});
}
Environment Variables (Recommended)
Store your token and chat ID securely using environment variables:
import 'dart:io';
final token = Platform.environment['TELEGRAM_BOT_TOKEN']!;
final chatId = Platform.environment['TELEGRAM_CHAT_ID']!;
final config = TelegramChatConfig(token: token, usePolling: true);
final receiver = ChatReceiver.id(chatId);
Set them in your shell:
export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
export TELEGRAM_CHAT_ID="987654321"
Usage Examples
Basic Send/Receive
final chat = await ChatAPI.connect(TelegramChatConfig(
token: token,
usePolling: true,
));
// Define the receiver
final receiver = ChatReceiver.id(chatId);
// Send a message to the receiver
await chat.sendMessage(receiver, 'Hello!');
// Get messages from that receiver
final response = await chat.getMessages(
receiver,
maxWait: Duration(seconds: 10),
);
for (final msg in response.messages) {
print('${msg.sender.name}: ${msg.text}');
}
Message Types
chat.onMessage.listen((msg) {
switch (msg.type) {
case ChatMessageType.text:
print('Text: ${msg.text}');
case ChatMessageType.image:
print('Received an image');
case ChatMessageType.document:
print('Received a document');
default:
print('Other: ${msg.type}');
}
});
Send to Different Chats
// Send to a user by ID
await chat.sendMessage(ChatReceiver.id('123456789'), 'Hello user!');
// Send to a user by username
await chat.sendMessage(ChatReceiver.username('johndoe'), 'Hi John!');
// Send to a group
await chat.sendMessage(ChatReceiver.group('-100123456789'), 'Hello group!');
API Overview
Core Classes
| Class | Description |
|---|---|
| `ChatAPI` | Abstract interface for chat operations |
| `ChatConfig` | Base configuration class |
| `ChatMessage` | Represents a chat message |
| `ChatSender` | Information about message sender |
| `ChatResponse` | Response from getMessages() |
| `ChatReceiver` | Target for sending messages |
Telegram Classes
| Class | Description |
|---|---|
| `TelegramChatConfig` | Telegram-specific configuration |
| `TelegramChat` | Telegram implementation of ChatAPI |
Troubleshooting
"Conflict: terminated by other getUpdates request"
Only one polling connection can be active. Make sure: - You don't have another instance running - You stopped previous bot instances properly
Bot not receiving messages
1. Make sure you've messaged the bot first (bots can't initiate chats) 2. Check if polling is enabled: `usePolling: true` 3. Verify your token is correct
Getting chat/user IDs
Print incoming message details:
chat.onMessage.listen((msg) {
print('Chat ID: ${msg.sender.id}');
print('Message ID: ${msg.platformMessageId}');
});
Additional Information
- [Telegram Bot API Documentation](https://core.telegram.org/bots/api)
- [Televerse Package](https://pub.dev/packages/televerse) - underlying Telegram library
- [BotFather Commands](https://core.telegram.org/bots#6-botfather)
Bot Privacy Settings
By default, bots in groups only see messages that: - Start with `/` (commands) - Are replies to the bot - Mention the bot
To see all messages, disable privacy mode: 1. Go to @BotFather 2. Send `/setprivacy` 3. Choose your bot 4. Select "Disable"
License
BSD 3-Clause License Copyright (c) 2024-2026, Peter Nicolai Alexis Kyaw Find me on LinkedIn under Alexis Kyaw All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.