Spaces:
Sleeping
Sleeping
File size: 7,838 Bytes
f2c1750 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
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()
|