Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ TWITTER_ACCESS_TOKEN=""
TWITTER_ACCESS_TOKEN_SECRET=""

# DISCORD
DISCORD_TOKEN=""
DISCORD_TOKEN=""

# TELEGRAM
TELEGRAM_BOT_TOKEN=""
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ propcache==0.2.1
pydantic==2.10.5
pydantic_core==2.27.2
python-dotenv==1.0.1
python-telegram-bot==22.5
PyYAML==6.0.2
requests==2.32.3
requests-oauthlib==2.0.0
Expand Down
3 changes: 2 additions & 1 deletion src/agent/agent_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class AgentConfig:
def __init__(self):
self.TWITTER_ENABLED = True
self.DISCORD_ENABLED = True
self.DISCORD_ENABLED = True
self.TELEGRAM_ENABLED = False
65 changes: 65 additions & 0 deletions src/agent/agent_tools/telegram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Telegram Tool

This tool enables the agent to interact with Telegram via a bot. The bot can respond to messages in private chats and group conversations.

## Setup

### 1. Create a Telegram Bot

1. Open Telegram and search for [@BotFather](https://t.me/botfather)
2. Start a conversation and send `/newbot`
3. Follow the prompts to create your bot
4. Save the bot token provided by BotFather

### 2. Add Bot Token to Environment

Add your bot token to the `.env` file:
```
TELEGRAM_BOT_TOKEN=your_bot_token_here
```

### 3. Enable Telegram Tool

In `src/agent/agent_config.py`, set:
```python
self.TELEGRAM_ENABLED = True
```

## Configuration

You can customize the bot's behavior in `telegram_config.py`:

- `RESPONSE_PROMPT`: The prompt given to the model to generate responses

## Testing

To test the Telegram bot separately from the main agent:
```bash
python3 -m src.agent.agent_tools.telegram
```

Expected output:
```
INFO: [TELEGRAM] Initializing Telegram client...
INFO: [TELEGRAM] Starting Telegram client...
```

## Usage

### Private Chats
The bot will respond to all messages sent in private chats.

### Group Chats
In group chats, the bot will only respond when mentioned with @. Add the bot to a group and mention it to get responses.

## Troubleshooting

**Bot not responding:**
- Check that `TELEGRAM_BOT_TOKEN` is correctly set in `.env`
- Verify that `TELEGRAM_ENABLED = True` in `agent_config.py`
- Check the logs for any error messages

**Group mentions not working:**
- Make sure the bot has permission to read messages in the group
- The bot must be a member of the group
- Try mentioning the bot with @ followed by its username
1 change: 1 addition & 0 deletions src/agent/agent_tools/telegram/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Telegram bot module
21 changes: 21 additions & 0 deletions src/agent/agent_tools/telegram/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import os
from dotenv import load_dotenv
from .telegram import Telegram
from ..model.model import Model

if __name__ == "__main__":
load_dotenv()

bot_token = os.getenv("TELEGRAM_BOT_TOKEN")
if not bot_token:
print("Error: TELEGRAM_BOT_TOKEN not found in environment variables")
exit(1)

model_api_key = os.getenv("MODEL_API_KEY")
if not model_api_key:
print("Error: MODEL_API_KEY not found in environment variables")
exit(1)

model = Model(api_key=model_api_key)
telegram = Telegram(bot_token=bot_token, model=model)
telegram.run()
115 changes: 115 additions & 0 deletions src/agent/agent_tools/telegram/telegram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import logging
from telegram import Update
from telegram.ext import Application, MessageHandler, filters, ContextTypes
from .telegram_config import TelegramConfig

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logging.basicConfig(format="%(levelname)s: %(message)s")

class Telegram:
"""A class for interfacing with the Telegram Bot API.

Attributes:
application (telegram.ext.Application): The Telegram bot application instance.
model: The language model used for generating responses.
config (TelegramConfig): Configuration settings for the Telegram bot.

Methods:
run(): Starts the Telegram bot and begins polling for messages.
"""

def __init__(self, bot_token, model):
"""
Initializes the Telegram class with the necessary parameters.

Args:
bot_token (str): The bot token from @BotFather.
model: The language model instance for generating responses.

Sets up the Telegram bot application and registers message handlers.
"""
logger.info("[TELEGRAM] Initializing Telegram client...")
self.bot_token = bot_token
self.model = model
self.config = TelegramConfig()

self.application = Application.builder().token(self.bot_token).build()

# Register message handlers
self.application.add_handler(
MessageHandler(
filters.TEXT & ~filters.COMMAND,
self._handle_message
)
)


def run(self):
"""Starts the Telegram bot and begins polling for messages."""
logger.info("[TELEGRAM] Starting Telegram client...")

# Run the bot using run_polling which blocks
self.application.run_polling(allowed_updates=Update.ALL_TYPES)


async def _handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""
Handles incoming messages and generates responses.

Args:
update (telegram.Update): The incoming update containing message info.
context (telegram.ext.ContextTypes.DEFAULT_TYPE): Context for the handler.
"""
message = update.message

if not message or not message.text:
return

logger.info(f"[TELEGRAM] Message received from {message.from_user.username}: {message.text}")

# Check if bot should respond to this message
if not self._should_respond(message):
return

try:
# Generate response using model
prompt = f"{self.config.RESPONSE_PROMPT} {message.text}"
response = self.model.query(prompt)
logger.info(f"[TELEGRAM] Response: {response}")

# Send response
logger.info("[TELEGRAM] Sending response...")
await message.reply_text(response)

except Exception as e:
logger.exception(f"[TELEGRAM] Error responding to message {message.message_id}. {e}")


def _should_respond(self, message) -> bool:
"""
Determines if the bot should respond to a message.

Args:
message: The Telegram message object.

Returns:
bool: True if the bot should respond, False otherwise.
"""
# In private chats, respond to everything
if message.chat.type == "private":
return True

# In group chats, only respond if bot is mentioned
if message.chat.type in ["group", "supergroup"]:
# Check if bot is mentioned
if message.entities:
for entity in message.entities:
if entity.type == "mention":
# Get the mentioned username
mentioned = message.text[entity.offset:entity.offset + entity.length]
# This would need the bot's username to compare properly
# For now, respond if ANY mention is present
return True

return False
5 changes: 5 additions & 0 deletions src/agent/agent_tools/telegram/telegram_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class TelegramConfig:
def __init__(self):
# Prompt that is provided to model, along with telegram message, to
# generate a response
self.RESPONSE_PROMPT = "Respond to this telegram message."