Example-example / app.py
AkshayHuggingFace's picture
Rename echobot.py to app.py
936f555 verified
import logging
import asyncio
from dotenv import load_dotenv
import os
from telegram import Update, ForceReply
from telegram.ext import (
Application, CommandHandler, MessageHandler, ContextTypes, filters, ConversationHandler
)
from tools import add_task, list_tasks, edit_task, delete_task
from runner import create_session_async, run_agent
from db_utils import save_message, load_chat_history, init_db
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
load_dotenv()
session = None
NEW_TASK, EDIT_TASK_NAME, EDIT_TASK_NEW_NAME, DELETE_TASK_NAME, DELETE_TASK_CONFIRM = range(5)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
menu = (
"Welcome to Task Manager Bot!\n"
"Choose a method:\n"
"/newtask - Add a new task\n"
"/listtask - View all tasks\n"
"/edittask - Edit an existing task\n"
"/deletetask - Delete a task\n"
"/history - Show last 5 chats"
)
await update.message.reply_text(menu, reply_markup=ForceReply(selective=True))
async def newtask_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Enter task name:")
return NEW_TASK
async def newtask_save(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = str(update.effective_user.id)
task_name = update.message.text.strip()
if task_name:
result = add_task(user_id, task_name)
await update.message.reply_text(result)
else:
await update.message.reply_text("Task name cannot be empty. Please try again.")
return NEW_TASK
return ConversationHandler.END
async def listtask(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = str(update.effective_user.id)
result = list_tasks(user_id)
await update.message.reply_text(result)
async def edittask_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Enter the task name you want to edit:")
return EDIT_TASK_NAME
async def edittask_get_new_name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = str(update.effective_user.id)
old_name = update.message.text.strip()
context.user_data['edit_task_old_name'] = old_name
tasks_list = list_tasks(user_id)
if old_name not in tasks_list:
await update.message.reply_text("Task not found. Please enter a valid task name:")
return EDIT_TASK_NAME
await update.message.reply_text("Enter the new task name:")
return EDIT_TASK_NEW_NAME
async def edittask_save(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = str(update.effective_user.id)
new_name = update.message.text.strip()
old_name = context.user_data.get('edit_task_old_name')
result = edit_task( user_id, old_name, new_name)
await update.message.reply_text(result)
return ConversationHandler.END
async def deletetask_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Enter the task name you want to delete:")
return DELETE_TASK_NAME
async def deletetask_confirm(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = str(update.effective_user.id)
task_name = update.message.text.strip()
context.user_data['delete_task_name'] = task_name
tasks_list = list_tasks(user_id)
if task_name not in tasks_list:
await update.message.reply_text("Task not found. Please enter a valid task name:")
return DELETE_TASK_NAME
await update.message.reply_text(f'Are you sure you want to delete "{task_name}"? If yes, type "yes" else type /cancel')
return DELETE_TASK_CONFIRM
async def deletetask_finish(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = str(update.effective_user.id)
response = update.message.text.strip().lower()
task_name = context.user_data.get('delete_task_name')
if response == "yes":
result = delete_task(user_id, task_name)
await update.message.reply_text(result)
else:
await update.message.reply_text("Delete cancelled ❌")
return ConversationHandler.END
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Cancelled ❌")
return ConversationHandler.END
async def history(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = str(update.effective_user.id)
messages = load_chat_history(user_id, limit=5)
if not messages:
await update.message.reply_text("No history yet.")
return
history_text = "\n".join([f"[{m.role}] {m.message}" for m in messages])
await update.message.reply_text("🕑 Your recent chats:\n\n" + history_text)
async def handle_free_text(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = int(update.effective_user.id)
user_message = update.message.text.strip()
save_message(user_id, "user", user_message)
await update.message.reply_text(f"🤖 Thinking... {user_id}")
try:
response = await run_agent(user_id, session.id, user_message)
if not response:
response_text = "⚠️ I didn't get any response."
elif isinstance(response, dict):
response_text = response.get("text") or response.get("message") or str(response)
else:
response_text = str(response).strip()
# if not response_text:
# response_text = "⚠️ Sorry, I got an empty reply."
save_message(user_id, "bot", response_text)
await update.message.reply_text(response_text)
except Exception as e:
await update.message.reply_text(f"❌ Error: {str(e)}")
def main():
global session
init_db()
loop = asyncio.get_event_loop()
session = loop.run_until_complete(create_session_async())
telegram_token = os.getenv("TELEGRAM_BOT_TOKEN")
application = Application.builder().token(telegram_token).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("listtask", listtask))
application.add_handler(CommandHandler("history", history))
newtask_conv = ConversationHandler(
entry_points=[CommandHandler("newtask", newtask_start)],
states={NEW_TASK: [MessageHandler(filters.TEXT & ~filters.COMMAND, newtask_save)]},
fallbacks=[]
)
application.add_handler(newtask_conv)
edittask_conv = ConversationHandler(
entry_points=[CommandHandler("edittask", edittask_start)],
states={
EDIT_TASK_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, edittask_get_new_name)],
EDIT_TASK_NEW_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, edittask_save)]
},
fallbacks=[]
)
application.add_handler(edittask_conv)
deletetask_conv = ConversationHandler(
entry_points=[CommandHandler("deletetask", deletetask_start)],
states={
DELETE_TASK_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, deletetask_confirm)],
DELETE_TASK_CONFIRM: [MessageHandler(filters.TEXT & ~filters.COMMAND, deletetask_finish)]
},
fallbacks=[CommandHandler("cancel", cancel)]
)
application.add_handler(deletetask_conv)
application.add_handler(CommandHandler("cancel", cancel))
application.add_handler(
MessageHandler(filters.TEXT & ~filters.COMMAND, handle_free_text)
)
application.run_polling()
if __name__ == "__main__":
main()