Added
This commit is contained in:
344
scheduler_bots/telegram_scheduler_v3.py
Normal file
344
scheduler_bots/telegram_scheduler_v3.py
Normal file
@@ -0,0 +1,344 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Enhanced Scheduler Bot with SQLite database support
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import datetime
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
|
||||
|
||||
# 🔑 REPLACE THIS with your bot token from @BotFather
|
||||
BOT_TOKEN = "8248686383:AAGN5UJ73H9i7LQzIBR3TjuJgUGNTFyRHk8"
|
||||
|
||||
# Database setup
|
||||
DATABASE_NAME = "schedule.db"
|
||||
|
||||
def init_db():
|
||||
"""Initialize the SQLite database and create tables if they don't exist."""
|
||||
conn = sqlite3.connect(DATABASE_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Create table for schedule entries
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS schedule (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
day TEXT NOT NULL,
|
||||
period INTEGER NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
class_name TEXT NOT NULL,
|
||||
room TEXT NOT NULL,
|
||||
UNIQUE(day, period)
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def add_schedule_entry(day, period, subject, class_name, room):
|
||||
"""Add a new schedule entry to the database."""
|
||||
conn = sqlite3.connect(DATABASE_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
cursor.execute('''
|
||||
INSERT OR REPLACE INTO schedule (day, period, subject, class_name, room)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
''', (day, period, subject, class_name, room))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return True
|
||||
except sqlite3.Error as e:
|
||||
print(f"Database error: {e}")
|
||||
conn.close()
|
||||
return False
|
||||
|
||||
def load_schedule_from_db():
|
||||
"""Load schedule from the SQLite database."""
|
||||
conn = sqlite3.connect(DATABASE_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT day, period, subject, class_name, room FROM schedule ORDER BY day, period")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
conn.close()
|
||||
|
||||
# Group by day
|
||||
schedule = {}
|
||||
for day, period, subject, class_name, room in rows:
|
||||
if day not in schedule:
|
||||
schedule[day] = []
|
||||
|
||||
class_info = f"Subject: {subject} Class: {class_name} Room: {room}"
|
||||
schedule[day].append((str(period), class_info))
|
||||
|
||||
return schedule
|
||||
|
||||
# Initialize the database
|
||||
init_db()
|
||||
|
||||
# Map period numbers to times - Updated as requested
|
||||
period_times = {
|
||||
'1': ('09:00', '09:40'),
|
||||
'2': ('10:00', '10:40'),
|
||||
'3': ('11:00', '11:40'),
|
||||
'4': ('11:50', '12:30'),
|
||||
'5': ('12:40', '13:20'),
|
||||
'6': ('13:30', '14:10'),
|
||||
'7': ('14:20', '15:00'),
|
||||
'8': ('15:20', '16:00'),
|
||||
'9': ('16:15', '16:55'),
|
||||
'10': ('17:05', '17:45'),
|
||||
'11': ('17:55', '18:35'),
|
||||
'12': ('18:45', '19:20'),
|
||||
'13': ('19:20', '20:00')
|
||||
}
|
||||
|
||||
# User states for tracking conversations
|
||||
user_states = {} # Stores user conversation state
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Send welcome message when command /start is issued."""
|
||||
await update.message.reply_text(
|
||||
"🤖 Hello! I'm your enhanced class scheduler bot with database support!\n"
|
||||
"Use /whereami to find your current class\n"
|
||||
"Use /schedule to see today's full schedule\n"
|
||||
"Use /tomorrow to see tomorrow's schedule\n"
|
||||
"Use /add to add a new class to the schedule\n"
|
||||
"Use /help for all commands"
|
||||
)
|
||||
|
||||
|
||||
async def where_am_i(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Tell user where they should be right now."""
|
||||
# Reload schedule from DB to ensure latest data
|
||||
schedule = load_schedule_from_db()
|
||||
|
||||
if not schedule:
|
||||
await update.message.reply_text("❌ Schedule not loaded from database.")
|
||||
return
|
||||
|
||||
now = datetime.datetime.now()
|
||||
current_time = now.strftime("%H:%M")
|
||||
current_day = now.strftime("%A")
|
||||
|
||||
await update.message.reply_text(f"📅 Today is {current_day}")
|
||||
await update.message.reply_text(f"⏰ Current time: {current_time}")
|
||||
|
||||
# Check if we have schedule for today
|
||||
if current_day not in schedule:
|
||||
await update.message.reply_text("😊 No classes scheduled for today!")
|
||||
return
|
||||
|
||||
# Find current class
|
||||
found_class = False
|
||||
for period_num, class_info in schedule[current_day]:
|
||||
start_time, end_time = period_times[period_num]
|
||||
|
||||
if start_time <= current_time <= end_time:
|
||||
await update.message.reply_text(f"🎯 You should be in: {class_info}")
|
||||
found_class = True
|
||||
break
|
||||
|
||||
if not found_class:
|
||||
await update.message.reply_text("😊 No class right now! Free period.")
|
||||
|
||||
|
||||
async def schedule(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Show the complete weekly schedule."""
|
||||
# Reload schedule from DB to ensure latest data
|
||||
schedule = load_schedule_from_db()
|
||||
|
||||
if not schedule:
|
||||
await update.message.reply_text("❌ Schedule not loaded from database.")
|
||||
return
|
||||
|
||||
schedule_text = "📚 Weekly Schedule:\n\n"
|
||||
|
||||
# Define the standard order of days in a week
|
||||
days_of_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
||||
|
||||
for day in days_of_week:
|
||||
if day in schedule and schedule[day]: # Check if the day exists in the schedule and has classes
|
||||
schedule_text += f"*{day}'s Schedule:*\n"
|
||||
for period_num, class_info in schedule[day]:
|
||||
start, end = period_times[period_num]
|
||||
schedule_text += f" ⏰ {start}-{end}: {class_info}\n"
|
||||
schedule_text += "\n"
|
||||
else:
|
||||
schedule_text += f"{day}: No classes scheduled\n\n"
|
||||
|
||||
await update.message.reply_text(schedule_text)
|
||||
|
||||
|
||||
async def tomorrow(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Show tomorrow's schedule."""
|
||||
# Reload schedule from DB to ensure latest data
|
||||
schedule = load_schedule_from_db()
|
||||
|
||||
if not schedule:
|
||||
await update.message.reply_text("❌ Schedule not loaded from database.")
|
||||
return
|
||||
|
||||
tomorrow_date = datetime.datetime.now() + datetime.timedelta(days=1)
|
||||
tomorrow_day = tomorrow_date.strftime("%A")
|
||||
|
||||
if tomorrow_day not in schedule or not schedule[tomorrow_day]:
|
||||
await update.message.reply_text(f"😊 No classes scheduled for {tomorrow_day}!")
|
||||
return
|
||||
|
||||
schedule_text = f"📚 {tomorrow_day}'s Schedule:\n\n"
|
||||
for period_num, class_info in schedule[tomorrow_day]:
|
||||
start, end = period_times[period_num]
|
||||
schedule_text += f"⏰ {start}-{end}: {class_info}\n"
|
||||
|
||||
await update.message.reply_text(schedule_text)
|
||||
|
||||
|
||||
async def add(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Start the process of adding a new schedule entry."""
|
||||
user_id = update.effective_user.id
|
||||
user_states[user_id] = {"step": "waiting_day"}
|
||||
|
||||
await update.message.reply_text(
|
||||
"📅 Adding a new class to the schedule.\n"
|
||||
"Please enter the day of the week (e.g., Monday, Tuesday, etc.):"
|
||||
)
|
||||
|
||||
|
||||
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Handle user messages during the add process."""
|
||||
user_id = update.effective_user.id
|
||||
|
||||
if user_id not in user_states:
|
||||
# Not in a conversation, ignore
|
||||
return
|
||||
|
||||
state_info = user_states[user_id]
|
||||
message_text = update.message.text.strip()
|
||||
|
||||
if state_info["step"] == "waiting_day":
|
||||
# Validate day input
|
||||
valid_days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
|
||||
if message_text.lower() not in valid_days:
|
||||
await update.message.reply_text(
|
||||
f"'{message_text}' is not a valid day of the week.\n"
|
||||
"Please enter a valid day (e.g., Monday, Tuesday, etc.):"
|
||||
)
|
||||
return
|
||||
|
||||
state_info["day"] = message_text.capitalize()
|
||||
state_info["step"] = "waiting_period"
|
||||
|
||||
await update.message.reply_text(
|
||||
f"Got it! Day: {state_info['day']}\n"
|
||||
"Now please enter the period number (1-13):"
|
||||
)
|
||||
|
||||
elif state_info["step"] == "waiting_period":
|
||||
try:
|
||||
period = int(message_text)
|
||||
if period < 1 or period > 13:
|
||||
raise ValueError("Period must be between 1 and 13")
|
||||
|
||||
state_info["period"] = period
|
||||
state_info["step"] = "waiting_subject"
|
||||
|
||||
await update.message.reply_text(
|
||||
f"Got it! Period: {period}\n"
|
||||
"Now please enter the subject name:"
|
||||
)
|
||||
except ValueError:
|
||||
await update.message.reply_text(
|
||||
f"'{message_text}' is not a valid period number.\n"
|
||||
"Please enter a number between 1 and 13:"
|
||||
)
|
||||
|
||||
elif state_info["step"] == "waiting_subject":
|
||||
state_info["subject"] = message_text
|
||||
state_info["step"] = "waiting_class"
|
||||
|
||||
await update.message.reply_text(
|
||||
f"Got it! Subject: {message_text}\n"
|
||||
"Now please enter the class name (e.g., 10ABC, 6A/6B, etc.):"
|
||||
)
|
||||
|
||||
elif state_info["step"] == "waiting_class":
|
||||
state_info["class_name"] = message_text
|
||||
state_info["step"] = "waiting_room"
|
||||
|
||||
await update.message.reply_text(
|
||||
f"Got it! Class: {message_text}\n"
|
||||
"Finally, please enter the room number:"
|
||||
)
|
||||
|
||||
elif state_info["step"] == "waiting_room":
|
||||
state_info["room"] = message_text
|
||||
|
||||
# Add to database
|
||||
success = add_schedule_entry(
|
||||
state_info["day"],
|
||||
state_info["period"],
|
||||
state_info["subject"],
|
||||
state_info["class_name"],
|
||||
message_text
|
||||
)
|
||||
|
||||
if success:
|
||||
await update.message.reply_text(
|
||||
f"✅ Successfully added to schedule!\n\n"
|
||||
f"Day: {state_info['day']}\n"
|
||||
f"Period: {state_info['period']}\n"
|
||||
f"Subject: {state_info['subject']}\n"
|
||||
f"Class: {state_info['class_name']}\n"
|
||||
f"Room: {state_info['room']}"
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text(
|
||||
f"❌ Failed to add to schedule. Please try again."
|
||||
)
|
||||
|
||||
# Clean up user state
|
||||
del user_states[user_id]
|
||||
|
||||
|
||||
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Send help message with all commands."""
|
||||
await update.message.reply_text(
|
||||
"Available commands:\n"
|
||||
"/start - Start the bot\n"
|
||||
"/whereami - Find your current class\n"
|
||||
"/schedule - Show today's full schedule\n"
|
||||
"/tomorrow - Show tomorrow's schedule\n"
|
||||
"/add - Add a new class to the schedule\n"
|
||||
"/help - Show this help message"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
"""Start the bot."""
|
||||
# Create the Application
|
||||
application = Application.builder().token(BOT_TOKEN).build()
|
||||
|
||||
# Add command handlers
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
application.add_handler(CommandHandler("whereami", where_am_i))
|
||||
application.add_handler(CommandHandler("schedule", schedule))
|
||||
application.add_handler(CommandHandler("tomorrow", tomorrow))
|
||||
application.add_handler(CommandHandler("add", add))
|
||||
application.add_handler(CommandHandler("help", help_command))
|
||||
|
||||
# Add message handler for conversation flow
|
||||
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
|
||||
|
||||
# Start the Bot
|
||||
print("🤖 Enhanced scheduler bot with database support is running...")
|
||||
print("📊 Database initialized successfully!")
|
||||
print("Press Ctrl+C to stop the bot")
|
||||
|
||||
application.run_polling()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user