refactored bot code

This commit is contained in:
Hosein
2025-12-30 18:57:48 +03:30
parent 67a76250ab
commit a52d62c0fc
15 changed files with 328 additions and 149 deletions
+18
View File
@@ -0,0 +1,18 @@
import os
import telebot
import logging
from bot.handlers.init import register_all_handlers
logger = logging.getLogger(__name__)
_bot = None
def get_bot():
global _bot
if _bot is None:
BOT_TOKEN = os.environ.get("BOT_TOKEN")
_bot = telebot.TeleBot(BOT_TOKEN, threaded=False)
register_all_handlers(_bot)
logger.info("Telegram bot initialized.")
return _bot
+7
View File
@@ -0,0 +1,7 @@
from . import students, teachers
def register_all_callbacks(bot):
"""Register all callback handlers"""
students.register(bot)
teachers.register(bot)
+20
View File
@@ -0,0 +1,20 @@
from telebot import types
from database.models import Students
from bot.utils.formatters import format_student_info
def register(bot):
@bot.callback_query_handler(func=lambda call: call.data.startswith('student_'))
def show_student_details(call):
student_id = call.data.split('_')[1]
student = Students.getStudentById(student_id)
if student:
details = format_student_info(student)
markup = types.InlineKeyboardMarkup()
bot.send_message(call.message.chat.id, details,
reply_markup=markup, parse_mode="HTML")
else:
bot.send_message(call.message.chat.id, "Student not found.")
bot.answer_callback_query(call.id)
+20
View File
@@ -0,0 +1,20 @@
from telebot import types
from database.models import Teachers
from bot.utils.formatters import format_teacher_info
def register(bot):
@bot.callback_query_handler(func=lambda call: call.data.startswith('teacher_'))
def show_teacher_details(call):
teacher_id = call.data.split('_')[1]
teacher = Teachers.getTeachertById(teacher_id)
if teacher:
details = format_teacher_info(teacher)
markup = types.InlineKeyboardMarkup()
bot.send_message(call.message.chat.id, details,
reply_markup=markup, parse_mode="HTML")
else:
bot.send_message(call.message.chat.id, "Teacher not found.")
bot.answer_callback_query(call.id)
+4
View File
@@ -0,0 +1,4 @@
def register(bot):
@bot.message_handler(func=lambda message: True)
def handle_unknown(message):
bot.reply_to(message, f"You said: {message.text}")
+14
View File
@@ -0,0 +1,14 @@
from . import start, students, teachers, common
from bot.callbacks.init import register_all_callbacks
def register_all_handlers(bot):
"""Register all handlers and callbacks"""
# Message handlers
start.register(bot)
students.register(bot)
teachers.register(bot)
common.register(bot) # Must be last (catch-all)
# Callback handlers
register_all_callbacks(bot)
+29
View File
@@ -0,0 +1,29 @@
from telebot import types
from bot.utils.auth import is_authenticated
def register(bot):
@bot.message_handler(commands=["start"])
def start_handler(message):
if is_authenticated(message.from_user.id):
bot.send_message(
message.chat.id, "authorized user! Welcome.")
else:
bot.send_message(
message.chat.id, "Welcome! Use buttons to fetch from database.")
markup = types.ReplyKeyboardMarkup(
row_width=2, one_time_keyboard=True, resize_keyboard=True)
btn1 = types.KeyboardButton("Show Students")
btn2 = types.KeyboardButton("Show Teachers")
btn3 = types.KeyboardButton("Show Courses")
btn4 = types.KeyboardButton("Show Tag")
btn5 = types.KeyboardButton("Show Categories")
markup.add(btn1, btn2, btn3, btn4, btn5)
bot.reply_to(message, "Use buttons to fetch from database.",
reply_markup=markup)
@bot.message_handler(func=lambda message: message.text in ["Show Courses", "Show Tag", "Show Categories"])
def handle_test_options(message):
option = message.text
bot.send_message(message.chat.id, f"You selected: {option}")
+26
View File
@@ -0,0 +1,26 @@
import logging
from telebot import types
from database.models import Students
logger = logging.getLogger(__name__)
def register(bot):
@bot.message_handler(func=lambda message: message.text == "Show Students")
def get_students(message):
try:
data = Students.getAllStudents()
if data:
markup = types.InlineKeyboardMarkup(row_width=2)
for row in data:
btn = types.InlineKeyboardButton(
f"@{row[1]} | id#{row[0]}", callback_data=f"student_{row[0]}")
markup.add(btn)
bot.send_message(
message.chat.id, "Here is the data:", reply_markup=markup)
else:
bot.reply_to(message, "No data found.")
except Exception as e:
logger.error(f"Error in get_students handler: {e}")
bot.reply_to(message, "Sorry, an error occurred.")
+26
View File
@@ -0,0 +1,26 @@
import logging
from telebot import types
from database.models import Teachers
logger = logging.getLogger(__name__)
def register(bot):
@bot.message_handler(func=lambda message: message.text == "Show Teachers")
def get_teachers(message):
try:
data = Teachers.getAllTeachers()
if data:
markup = types.InlineKeyboardMarkup(row_width=2)
for row in data:
btn = types.InlineKeyboardButton(
f"@{row[1]} | id#{row[0]}", callback_data=f"teacher_{row[0]}")
markup.add(btn)
bot.send_message(
message.chat.id, "Here is the data:", reply_markup=markup)
else:
bot.reply_to(message, "No data found.")
except Exception as e:
logger.error(f"Error in get_teachers handler: {e}")
bot.reply_to(message, "Sorry, an error occurred.")
+4
View File
@@ -0,0 +1,4 @@
authenticated_users = {2032936226}
def is_authenticated(user_id):
return user_id in authenticated_users
+109
View File
@@ -0,0 +1,109 @@
from datetime import datetime
def format_date(date_string):
"""Convert database date to readable format"""
if not date_string:
return "N/A"
try:
# If date_string is already a datetime object
if isinstance(date_string, datetime):
return date_string.strftime("%d %b %Y, %H:%M")
# If it's a string, parse it first
date_obj = datetime.strptime(str(date_string), "%Y-%m-%d %H:%M:%S")
return date_obj.strftime("%d %b %Y, %H:%M")
except:
return str(date_string)
def calculate_age(birthday_string):
"""Calculate age from birthday"""
if not birthday_string:
return "N/A"
try:
birth_date = datetime.strptime(str(birthday_string), "%Y-%m-%d").date()
today = datetime.now().date()
age = today.year - birth_date.year - \
((today.month, today.day) < (birth_date.month, birth_date.day))
return age
except:
return "N/A"
# Student Info Formatter
def format_student_info(student):
"""
Format student data into a nice message
student is a tuple: (id, username, name, created_at, email, phone_number, last_seen, is_verified, birthday)
"""
print(student)
id, username, name, created_at, email, phone_number, last_seen, is_verfied, birthday = student
verified_status = "✅ Verified" if is_verfied else "❌ Not Verified"
# Format dates nicely
created_date = format_date(created_at)
last_seen_date = format_date(last_seen)
# Calculate age from birthday
age = calculate_age(birthday)
details = f"""
<b>👤 Student Profile</b>
<b>Name:</b> {name}
<b>Username:</b> {username}
<b>Email:</b> {email}
<b>Phone:</b> {phone_number}
<b>Birthday:</b> {birthday} (Age: {age})
<b>Account Status:</b> {verified_status}
<b>📅 Account Info</b>
<b>Joined:</b> {created_date}
<b>Last Seen:</b> {last_seen_date}
<b>ID:</b> <code>{id}</code>
"""
return details.strip()
# Teacher Info Formatter
def format_teacher_info(teacher):
"""
Format student data into a nice message
student is a tuple: (id, username, created_at, email, phone_number, last_seen, is_verified, birthday)
"""
print(teacher)
id, username, name, created_at, email, phone_number, last_seen, is_verfied, birthday, about_me, job_title = teacher
verified_status = "✅ Verified" if is_verfied else "❌ Not Verified"
# Format dates nicely
created_date = format_date(created_at)
last_seen_date = format_date(last_seen)
# Calculate age from birthday
age = calculate_age(birthday)
details = f"""
<b>👤 Student Profile</b>
<b>Name:</b> {name}
<b>Username:</b> {username}
<b>Job Title:</b> {job_title}
<b>About Me:</b> {about_me}
<b>Email:</b> {email}
<b>Phone:</b> {phone_number}
<b>Birthday:</b> {birthday} (Age: {age})
<b>Account Status:</b> {verified_status}
<b>📅 Account Info</b>
<b>Joined:</b> {created_date}
<b>Last Seen:</b> {last_seen_date}
<b>ID:</b> <code>{id}</code>
"""
return details.strip()