added authentication to the bot. added bot commnads. added create button for when the db is empty or no data is available to show.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from telebot import types, TeleBot
|
from telebot import types, TeleBot
|
||||||
from database.models import Categories
|
from database.models import Categories, Admins
|
||||||
from bot.handlers.start import startMarkup
|
from bot.handlers.start import startMarkup
|
||||||
from bot.utils.crud_helpers import create_entity_markup
|
from bot.utils.crud_helpers import create_entity_markup
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ def register(bot: TeleBot):
|
|||||||
<b>Description:</b> \n{category[2]}
|
<b>Description:</b> \n{category[2]}
|
||||||
"""
|
"""
|
||||||
details.strip()
|
details.strip()
|
||||||
markup = create_entity_markup("category", category_id)
|
markup = create_entity_markup("category", category_id, True)
|
||||||
|
|
||||||
bot.send_message(call.message.chat.id, details,
|
bot.send_message(call.message.chat.id, details,
|
||||||
reply_markup=markup, parse_mode="HTML")
|
reply_markup=markup, parse_mode="HTML")
|
||||||
@@ -91,9 +91,13 @@ def register(bot: TeleBot):
|
|||||||
message.chat.id, "❌ Failed to create category.", reply_markup=startMarkup())
|
message.chat.id, "❌ Failed to create category.", reply_markup=startMarkup())
|
||||||
|
|
||||||
# Editing a Category Flow
|
# Editing a Category Flow
|
||||||
|
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_category_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_category_'))
|
||||||
def start_category_editing(call):
|
def start_category_editing(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
category_id = call.data.split('_')[2]
|
category_id = call.data.split('_')[2]
|
||||||
category = Categories.getCategorieById(category_id)
|
category = Categories.getCategorieById(category_id)
|
||||||
|
|
||||||
@@ -150,6 +154,11 @@ def register(bot: TeleBot):
|
|||||||
# Deleting a Category
|
# Deleting a Category
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_category_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_category_'))
|
||||||
def delete_category(call):
|
def delete_category(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
category_id = call.data.split('_')[2]
|
category_id = call.data.split('_')[2]
|
||||||
if (Categories.deleteCategory(category_id)):
|
if (Categories.deleteCategory(category_id)):
|
||||||
bot.send_message(call.message.chat.id, "✅ Category deleted.",
|
bot.send_message(call.message.chat.id, "✅ Category deleted.",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from telebot import TeleBot, types
|
from telebot import TeleBot, types
|
||||||
from database.models import Courses
|
from database.models import Courses, Admins
|
||||||
from bot.utils.crud_helpers import create_entity_markup
|
from bot.utils.crud_helpers import create_entity_markup
|
||||||
from bot.utils.formatters import format_course_info
|
from bot.utils.formatters import format_course_info
|
||||||
from bot.handlers.start import startMarkup
|
from bot.handlers.start import startMarkup
|
||||||
@@ -38,7 +38,7 @@ def register(bot: TeleBot):
|
|||||||
return
|
return
|
||||||
|
|
||||||
details = format_course_info(course)
|
details = format_course_info(course)
|
||||||
markup = create_entity_markup("course", course_id)
|
markup = create_entity_markup("course", course_id, True)
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
f"👨🏫 Teacher's Info", callback_data=f"teacher_{course[3]}"))
|
f"👨🏫 Teacher's Info", callback_data=f"teacher_{course[3]}"))
|
||||||
|
|
||||||
@@ -93,6 +93,11 @@ def register(bot: TeleBot):
|
|||||||
# Editing a Course Flow
|
# Editing a Course Flow
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_course_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_course_'))
|
||||||
def start_course_editing(call):
|
def start_course_editing(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
course_id = call.data.split('_')[2]
|
course_id = call.data.split('_')[2]
|
||||||
course = Courses.getCourseById(course_id)
|
course = Courses.getCourseById(course_id)
|
||||||
|
|
||||||
@@ -149,6 +154,11 @@ def register(bot: TeleBot):
|
|||||||
# Deleting a Teacher
|
# Deleting a Teacher
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_course_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_course_'))
|
||||||
def delete_course(call):
|
def delete_course(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
course_id = call.data.split('_')[2]
|
course_id = call.data.split('_')[2]
|
||||||
if (Courses.deleteCourse(course_id)):
|
if (Courses.deleteCourse(course_id)):
|
||||||
bot.send_message(call.message.chat.id, "✅ Course deleted.",
|
bot.send_message(call.message.chat.id, "✅ Course deleted.",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from telebot import types, TeleBot
|
from telebot import types, TeleBot
|
||||||
from database.models import Students
|
from database.models import Students, Admins
|
||||||
from bot.utils.formatters import format_student_info
|
from bot.utils.formatters import format_student_info
|
||||||
from bot.utils.crud_helpers import create_entity_markup
|
from bot.utils.crud_helpers import create_entity_markup
|
||||||
from bot.handlers.start import startMarkup
|
from bot.handlers.start import startMarkup
|
||||||
@@ -30,12 +30,17 @@ def register(bot: TeleBot):
|
|||||||
# Showing details of a Student
|
# Showing details of a Student
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('student_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('student_'))
|
||||||
def show_student_details(call):
|
def show_student_details(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
student_id = call.data.split('_')[1]
|
student_id = call.data.split('_')[1]
|
||||||
student = Students.getStudentById(student_id)
|
student = Students.getStudentById(student_id)
|
||||||
|
|
||||||
if student:
|
if student:
|
||||||
details = format_student_info(student)
|
details = format_student_info(student)
|
||||||
markup = create_entity_markup("student", student_id)
|
markup = create_entity_markup("student", student_id, True)
|
||||||
|
|
||||||
bot.send_message(call.message.chat.id, details,
|
bot.send_message(call.message.chat.id, details,
|
||||||
reply_markup=markup, parse_mode="HTML")
|
reply_markup=markup, parse_mode="HTML")
|
||||||
@@ -47,6 +52,11 @@ def register(bot: TeleBot):
|
|||||||
# Creating a Student Flow
|
# Creating a Student Flow
|
||||||
@bot.callback_query_handler(func=lambda call: call.data == 'create_student')
|
@bot.callback_query_handler(func=lambda call: call.data == 'create_student')
|
||||||
def create_student(call):
|
def create_student(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
msg = bot.send_message(call.message.chat.id,
|
msg = bot.send_message(call.message.chat.id,
|
||||||
"Please enter following data: (enter any key to start)",
|
"Please enter following data: (enter any key to start)",
|
||||||
reply_markup=cancelMarkup)
|
reply_markup=cancelMarkup)
|
||||||
@@ -90,6 +100,11 @@ def register(bot: TeleBot):
|
|||||||
# Editing a Student Flow
|
# Editing a Student Flow
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_student_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_student_'))
|
||||||
def start_student_editing(call):
|
def start_student_editing(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
student_id = call.data.split('_')[2]
|
student_id = call.data.split('_')[2]
|
||||||
student = Students.getStudentById(student_id)
|
student = Students.getStudentById(student_id)
|
||||||
|
|
||||||
@@ -146,6 +161,11 @@ def register(bot: TeleBot):
|
|||||||
# Deleting a Teacher
|
# Deleting a Teacher
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_student_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_student_'))
|
||||||
def delete_student(call):
|
def delete_student(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
student_id = call.data.split('_')[2]
|
student_id = call.data.split('_')[2]
|
||||||
if (Students.deleteStudent(student_id)):
|
if (Students.deleteStudent(student_id)):
|
||||||
bot.send_message(call.message.chat.id, "✅ Student deleted.",
|
bot.send_message(call.message.chat.id, "✅ Student deleted.",
|
||||||
|
|||||||
+12
-3
@@ -1,5 +1,5 @@
|
|||||||
from telebot import types, TeleBot
|
from telebot import types, TeleBot
|
||||||
from database.models import Tags
|
from database.models import Tags, Admins
|
||||||
from bot.handlers.start import startMarkup
|
from bot.handlers.start import startMarkup
|
||||||
from bot.utils.crud_helpers import create_entity_markup
|
from bot.utils.crud_helpers import create_entity_markup
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ def register(bot: TeleBot):
|
|||||||
<b>slug:</b> {tag[2]}
|
<b>slug:</b> {tag[2]}
|
||||||
"""
|
"""
|
||||||
details.strip()
|
details.strip()
|
||||||
markup = create_entity_markup("tag", tag_id)
|
markup = create_entity_markup("tag", tag_id, True)
|
||||||
|
|
||||||
bot.send_message(call.message.chat.id, details,
|
bot.send_message(call.message.chat.id, details,
|
||||||
reply_markup=markup, parse_mode="HTML")
|
reply_markup=markup, parse_mode="HTML")
|
||||||
@@ -87,9 +87,13 @@ def register(bot: TeleBot):
|
|||||||
message.chat.id, "❌ Failed to create tag.", reply_markup=startMarkup())
|
message.chat.id, "❌ Failed to create tag.", reply_markup=startMarkup())
|
||||||
|
|
||||||
# Editing a Tag Flow
|
# Editing a Tag Flow
|
||||||
|
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_tag_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_tag_'))
|
||||||
def start_tag_editing(call):
|
def start_tag_editing(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
tag_id = call.data.split('_')[2]
|
tag_id = call.data.split('_')[2]
|
||||||
tag = Tags.getTagById(tag_id)
|
tag = Tags.getTagById(tag_id)
|
||||||
|
|
||||||
@@ -146,6 +150,11 @@ def register(bot: TeleBot):
|
|||||||
# Deleting a Tag
|
# Deleting a Tag
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_tag_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_tag_'))
|
||||||
def delete_tag(call):
|
def delete_tag(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
tag_id = call.data.split('_')[2]
|
tag_id = call.data.split('_')[2]
|
||||||
if (Tags.deleteTag(tag_id)):
|
if (Tags.deleteTag(tag_id)):
|
||||||
bot.send_message(call.message.chat.id, "✅ Tag deleted.",
|
bot.send_message(call.message.chat.id, "✅ Tag deleted.",
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
from telebot import types, TeleBot
|
from telebot import types, TeleBot
|
||||||
from database.models import Teachers
|
from database.models import Teachers, Admins
|
||||||
from bot.utils.formatters import format_teacher_info
|
from bot.utils.formatters import format_teacher_info
|
||||||
from bot.handlers.start import startMarkup
|
from bot.handlers.start import startMarkup
|
||||||
from bot.utils.crud_helpers import create_entity_markup
|
from bot.utils.crud_helpers import create_entity_markup
|
||||||
|
|
||||||
# TODO: Add Buttons for skipping Optional Fields (Add to all entities).
|
# TODO: Add Buttons for skipping Optional Fields (Add to all entities).
|
||||||
# TODO: Add Option for handling all updates at once.
|
# TODO: Add Option for handling all updates at once.\
|
||||||
# TODO: Add Authentication for sensitive actions and info.
|
|
||||||
|
|
||||||
# TODO: Add Option for seeing courses taught by a teacher in Teacher Details.
|
# TODO: Add Option for seeing courses taught by a teacher in Teacher Details.
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ def register(bot: TeleBot):
|
|||||||
|
|
||||||
if teacher:
|
if teacher:
|
||||||
details = format_teacher_info(teacher)
|
details = format_teacher_info(teacher)
|
||||||
markup = create_entity_markup("teacher", teacher_id)
|
markup = create_entity_markup("teacher", teacher_id, True)
|
||||||
|
|
||||||
bot.send_message(call.message.chat.id, details,
|
bot.send_message(call.message.chat.id, details,
|
||||||
reply_markup=markup, parse_mode="HTML")
|
reply_markup=markup, parse_mode="HTML")
|
||||||
@@ -57,6 +56,11 @@ def register(bot: TeleBot):
|
|||||||
# Creating a Teacher Flow
|
# Creating a Teacher Flow
|
||||||
@bot.callback_query_handler(func=lambda call: call.data == 'create_teacher')
|
@bot.callback_query_handler(func=lambda call: call.data == 'create_teacher')
|
||||||
def start_teacher_creation(call):
|
def start_teacher_creation(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
msg = bot.send_message(call.message.chat.id,
|
msg = bot.send_message(call.message.chat.id,
|
||||||
"Please enter following data: (enter any key to start)",
|
"Please enter following data: (enter any key to start)",
|
||||||
reply_markup=cancelMarkup)
|
reply_markup=cancelMarkup)
|
||||||
@@ -100,6 +104,11 @@ def register(bot: TeleBot):
|
|||||||
# Editing a Teacher Flow
|
# Editing a Teacher Flow
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_teacher_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('edit_teacher_'))
|
||||||
def start_teacher_editing(call):
|
def start_teacher_editing(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
teacher_id = call.data.split('_')[2]
|
teacher_id = call.data.split('_')[2]
|
||||||
teacher = Teachers.getTeacherById(teacher_id)
|
teacher = Teachers.getTeacherById(teacher_id)
|
||||||
|
|
||||||
@@ -156,6 +165,11 @@ def register(bot: TeleBot):
|
|||||||
# Deleting a Teacher
|
# Deleting a Teacher
|
||||||
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_teacher_'))
|
@bot.callback_query_handler(func=lambda call: call.data.startswith('delete_teacher_'))
|
||||||
def delete_teacher(call):
|
def delete_teacher(call):
|
||||||
|
if not Admins.is_authenticated(call.from_user.id):
|
||||||
|
bot.answer_callback_query(call.id, "⛔ Unauthorized access!")
|
||||||
|
bot.send_message(call.message.chat.id, "Please /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
teacher_id = call.data.split('_')[2]
|
teacher_id = call.data.split('_')[2]
|
||||||
if (Teachers.deleteTeacher(teacher_id)):
|
if (Teachers.deleteTeacher(teacher_id)):
|
||||||
bot.send_message(call.message.chat.id, "✅ Teacher deleted.",
|
bot.send_message(call.message.chat.id, "✅ Teacher deleted.",
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ def register(bot):
|
|||||||
bot.send_message(
|
bot.send_message(
|
||||||
message.chat.id, "Here is the data:", reply_markup=markup)
|
message.chat.id, "Here is the data:", reply_markup=markup)
|
||||||
else:
|
else:
|
||||||
bot.reply_to(message, "No data found.")
|
markup = types.InlineKeyboardMarkup(row_width=1)
|
||||||
|
markup.add(types.InlineKeyboardButton(
|
||||||
|
"➕ Create New Category", callback_data="create_category"))
|
||||||
|
|
||||||
|
bot.reply_to(message, "No data found.", reply_markup=markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in 'Show Categories' handler: {e}")
|
logger.error(f"Error in 'Show Categories' handler: {e}")
|
||||||
bot.reply_to(message, "Sorry, an error occurred.")
|
bot.reply_to(message, "Sorry, an error occurred.")
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
from telebot import types
|
||||||
|
from bot.handlers.start import startMessage
|
||||||
|
|
||||||
|
|
||||||
def register(bot):
|
def register(bot):
|
||||||
@bot.message_handler(func=lambda message: True)
|
@bot.message_handler(func=lambda message: True)
|
||||||
def handle_unknown(message):
|
def handle_unknown(message):
|
||||||
bot.reply_to(message, f"You said: {message.text}")
|
bot.reply_to(
|
||||||
|
message, f"You said: {message.text}. send /start to get started.")
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ def register(bot):
|
|||||||
bot.send_message(
|
bot.send_message(
|
||||||
message.chat.id, "Here is the data:", reply_markup=markup)
|
message.chat.id, "Here is the data:", reply_markup=markup)
|
||||||
else:
|
else:
|
||||||
bot.reply_to(message, "No data found.")
|
markup = types.InlineKeyboardMarkup(row_width=1)
|
||||||
|
markup.add(types.InlineKeyboardButton(
|
||||||
|
"➕ Create New Course", callback_data="create_course"))
|
||||||
|
bot.reply_to(message, "No data found.", reply_markup=markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in (Show Courses) handler: {e}")
|
logger.error(f"Error in (Show Courses) handler: {e}")
|
||||||
bot.reply_to(message, "Sorry, an error occurred.")
|
bot.reply_to(message, "Sorry, an error occurred.")
|
||||||
|
|||||||
+15
-1
@@ -1,11 +1,25 @@
|
|||||||
from . import start, students, teachers, courses, tags, categories, common
|
from . import start, students, teachers, courses, tags, categories, common, login
|
||||||
from bot.callbacks.init import register_all_callbacks
|
from bot.callbacks.init import register_all_callbacks
|
||||||
|
from telebot import types
|
||||||
|
|
||||||
|
|
||||||
def register_all_handlers(bot):
|
def register_all_handlers(bot):
|
||||||
"""Register all handlers and callbacks"""
|
"""Register all handlers and callbacks"""
|
||||||
|
# Set bot commands
|
||||||
|
commands = [
|
||||||
|
types.BotCommand(command="start", description="Start the bot"),
|
||||||
|
types.BotCommand(command="login", description="Login to your account"),
|
||||||
|
types.BotCommand(command="logout",
|
||||||
|
description="Logout of your account"),
|
||||||
|
types.BotCommand(command="session",
|
||||||
|
description="Info about your session"),
|
||||||
|
]
|
||||||
|
|
||||||
|
bot.set_my_commands(commands)
|
||||||
|
|
||||||
# Message handlers
|
# Message handlers
|
||||||
start.register(bot)
|
start.register(bot)
|
||||||
|
login.register(bot)
|
||||||
students.register(bot)
|
students.register(bot)
|
||||||
teachers.register(bot)
|
teachers.register(bot)
|
||||||
courses.register(bot)
|
courses.register(bot)
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
from telebot import types, TeleBot
|
||||||
|
from database.models import Admins
|
||||||
|
from bot.handlers.start import startMarkup
|
||||||
|
|
||||||
|
|
||||||
|
def register(bot: TeleBot):
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['login'])
|
||||||
|
def start_login(message):
|
||||||
|
# Check if already authenticated
|
||||||
|
if Admins.is_authenticated(message.from_user.id):
|
||||||
|
session_info = Admins.get_session_info(message.from_user.id)
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"✅ You are already logged in!\n\n"
|
||||||
|
f"Session expires in: {session_info['time_remaining']}"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
msg = bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"🔐 Please enter your username:"
|
||||||
|
)
|
||||||
|
bot.register_next_step_handler(msg, get_password)
|
||||||
|
|
||||||
|
def get_password(message):
|
||||||
|
"""Get username and ask for password"""
|
||||||
|
username = message.text.strip()
|
||||||
|
|
||||||
|
try:
|
||||||
|
bot.delete_message(message.chat.id, message.message_id)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
msg = bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"Username: {username}\n\n🔑 Now enter your password:"
|
||||||
|
)
|
||||||
|
bot.register_next_step_handler(msg, verify_and_login, username)
|
||||||
|
|
||||||
|
def verify_and_login(message, username):
|
||||||
|
"""Verify credentials and create session"""
|
||||||
|
password = message.text.strip()
|
||||||
|
telegram_id = message.from_user.id
|
||||||
|
|
||||||
|
try:
|
||||||
|
bot.delete_message(message.chat.id, message.message_id)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Attempt login (this creates the session)
|
||||||
|
if Admins.login(username, password, telegram_id):
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"✅ Login successful!\n\n"
|
||||||
|
f"Welcome back, {username}!\n"
|
||||||
|
f"Session valid for: {Admins.SESSION_TIMEOUT_HOURS} hours\n"
|
||||||
|
f"Use /session for info about your session, or /logout to logout.",
|
||||||
|
reply_markup=startMarkup()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"❌ Invalid credentials or unauthorized Telegram account.\n\n"
|
||||||
|
"Please check your username and password.\nContact @HoseinA05 for support."
|
||||||
|
)
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['logout'])
|
||||||
|
def logout(message):
|
||||||
|
"""Logout user manually"""
|
||||||
|
|
||||||
|
if not Admins.is_authenticated(message.from_user.id):
|
||||||
|
bot.send_message(message.chat.id, "You are not logged in.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if Admins.logout(message.from_user.id):
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
"✅ You have been logged out successfully.\n\n"
|
||||||
|
"Use /login to access admin features again."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id, "❌ Logout failed. Please try again later.")
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['session'])
|
||||||
|
def check_session(message):
|
||||||
|
"""Check current session status"""
|
||||||
|
session_info = Admins.get_session_info(message.from_user.id)
|
||||||
|
|
||||||
|
if not session_info:
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id, "❌ You don't have an admin account.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if session_info['is_active']:
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"✅ Active Session\n\n"
|
||||||
|
f"Username: {session_info['username']}\n"
|
||||||
|
f"Last Login: {session_info['last_login']}\n"
|
||||||
|
f"Time Remaining: {session_info['time_remaining']}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
f"⏱️ Session Expired\n\n"
|
||||||
|
f"Username: {session_info['username']}\n"
|
||||||
|
f"Please use /login to continue."
|
||||||
|
)
|
||||||
+10
-10
@@ -1,5 +1,4 @@
|
|||||||
from telebot import types
|
from telebot import types
|
||||||
from bot.utils.auth import is_authenticated
|
|
||||||
|
|
||||||
# TODO: Add Pagincation to Showing rows of entities (To all entities)
|
# TODO: Add Pagincation to Showing rows of entities (To all entities)
|
||||||
|
|
||||||
@@ -7,16 +6,17 @@ from bot.utils.auth import is_authenticated
|
|||||||
def register(bot):
|
def register(bot):
|
||||||
@bot.message_handler(commands=["start"])
|
@bot.message_handler(commands=["start"])
|
||||||
def start_handler(message):
|
def start_handler(message):
|
||||||
if is_authenticated(message.from_user.id):
|
startMessage(bot, message=message)
|
||||||
bot.send_message(
|
|
||||||
message.chat.id, "authorized user! Welcome.")
|
|
||||||
else:
|
|
||||||
bot.send_message(
|
|
||||||
message.chat.id, "Welcome! Use buttons to fetch from database.")
|
|
||||||
|
|
||||||
markup = startMarkup()
|
|
||||||
bot.reply_to(message, "Use buttons to fetch from database.",
|
def startMessage(bot, message):
|
||||||
reply_markup=markup)
|
# if is_authenticated(message.from_user.id):
|
||||||
|
# bot.send_message(
|
||||||
|
# message.chat.id, "authorized user! Welcome.")
|
||||||
|
|
||||||
|
markup = startMarkup()
|
||||||
|
bot.reply_to(message, "Use buttons to fetch from database.",
|
||||||
|
reply_markup=markup)
|
||||||
|
|
||||||
|
|
||||||
def startMarkup():
|
def startMarkup():
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import logging
|
import logging
|
||||||
from telebot import types
|
from telebot import types, TeleBot
|
||||||
from database.models import Students
|
from database.models import Students, Admins
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def register(bot):
|
def register(bot: TeleBot):
|
||||||
@bot.message_handler(func=lambda message: message.text == "Show Students")
|
@bot.message_handler(func=lambda message: message.text == "Show Students")
|
||||||
def get_students(message):
|
def get_students(message):
|
||||||
|
if not Admins.is_authenticated(message.from_user.id):
|
||||||
|
bot.send_message(
|
||||||
|
message.chat.id, "⛔ Unauthorized access!\nPlease /login first.")
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = Students.getAllStudents()
|
data = Students.getAllStudents()
|
||||||
if data:
|
if data:
|
||||||
@@ -20,12 +25,15 @@ def register(bot):
|
|||||||
|
|
||||||
# add button for creating a new student
|
# add button for creating a new student
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
"➕ Create New Student", callback_data="create_student"))
|
"➕ Create New Student 🔒", callback_data="create_student"))
|
||||||
|
|
||||||
bot.send_message(
|
bot.send_message(
|
||||||
message.chat.id, "Here is the data:", reply_markup=markup)
|
message.chat.id, "Here is the data:", reply_markup=markup)
|
||||||
else:
|
else:
|
||||||
bot.reply_to(message, "No data found.")
|
markup = types.InlineKeyboardMarkup(row_width=1)
|
||||||
|
markup.add(types.InlineKeyboardButton(
|
||||||
|
"➕ Create New Student 🔒", callback_data="create_student"))
|
||||||
|
bot.reply_to(message, "No data found.", reply_markup=markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in get_students handler: {e}")
|
logger.error(f"Error in get_students handler: {e}")
|
||||||
bot.reply_to(message, "Sorry, an error occurred.")
|
bot.reply_to(message, "Sorry, an error occurred.")
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ def register(bot: TeleBot):
|
|||||||
bot.send_message(
|
bot.send_message(
|
||||||
message.chat.id, "Here is the data:", reply_markup=markup)
|
message.chat.id, "Here is the data:", reply_markup=markup)
|
||||||
else:
|
else:
|
||||||
markup = types.InlineKeyboardMarkup(row_width=2)
|
markup = types.InlineKeyboardMarkup(row_width=1)
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
"➕ Create New Tag", callback_data="create_tag"))
|
"➕ Create New Tag", callback_data="create_tag"))
|
||||||
|
|
||||||
bot.reply_to(message, "No data found.", markup=markup)
|
bot.reply_to(message, "No data found.", reply_markup=markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in 'Show Tags' handler: {e}")
|
logger.error(f"Error in 'Show Tags' handler: {e}")
|
||||||
bot.reply_to(message, "Sorry, an error occurred.")
|
bot.reply_to(message, "Sorry, an error occurred.")
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ def register(bot):
|
|||||||
markup.add(btn)
|
markup.add(btn)
|
||||||
# add button for creating a new teacher
|
# add button for creating a new teacher
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
"➕ Create New Teacher", callback_data="create_teacher"))
|
"➕ Create New Teacher 🔒", callback_data="create_teacher"))
|
||||||
|
|
||||||
bot.send_message(
|
bot.send_message(
|
||||||
message.chat.id, "Here is the data:", reply_markup=markup)
|
message.chat.id, "Here is the data:", reply_markup=markup)
|
||||||
else:
|
else:
|
||||||
bot.reply_to(message, "No data found.")
|
markup = types.InlineKeyboardMarkup(row_width=1)
|
||||||
|
markup.add(types.InlineKeyboardButton(
|
||||||
|
"➕ Create New Teacher 🔒", callback_data="create_teacher"))
|
||||||
|
bot.reply_to(message, "No data found.", reply_markup=markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in get_teachers handler: {e}")
|
logger.error(f"Error in get_teachers handler: {e}")
|
||||||
bot.reply_to(message, "Sorry, an error occurred.")
|
bot.reply_to(message, "Sorry, an error occurred.")
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
authenticated_users = {2032936226}
|
|
||||||
|
|
||||||
def is_authenticated(user_id):
|
|
||||||
return user_id in authenticated_users
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
from telebot import types
|
from telebot import types
|
||||||
|
|
||||||
|
|
||||||
def create_entity_markup(entity_name, enitity_id):
|
def create_entity_markup(entity_name, enitity_id, is_auth_needed=False):
|
||||||
markup = types.InlineKeyboardMarkup()
|
markup = types.InlineKeyboardMarkup()
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
f"✏️ Edit {entity_name}", callback_data=f"edit_{entity_name}_{enitity_id}"))
|
f"✏️ Edit {entity_name} " + ("🔒" if is_auth_needed else ""), callback_data=f"edit_{entity_name}_{enitity_id}"))
|
||||||
markup.add(types.InlineKeyboardButton(
|
markup.add(types.InlineKeyboardButton(
|
||||||
f"🗑️ Delete {entity_name}", callback_data=f"delete_{entity_name}_{enitity_id}"))
|
f"🗑️ Delete {entity_name}" + ("🔒" if is_auth_needed else ""), callback_data=f"delete_{entity_name}_{enitity_id}"))
|
||||||
|
|
||||||
return markup
|
return markup
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import database.connection as connection
|
import database.connection as connection
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -55,6 +58,119 @@ class BaseRepository:
|
|||||||
connection.release_db_connection(conn)
|
connection.release_db_connection(conn)
|
||||||
|
|
||||||
|
|
||||||
|
class Admins(BaseRepository):
|
||||||
|
|
||||||
|
SESSION_TIMEOUT_HOURS = 1
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def hash_password(password: str) -> str:
|
||||||
|
"""Hash password using SHA256"""
|
||||||
|
return hashlib.sha256(password.encode()).hexdigest()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def login(username: str, password: str, telegram_id: int) -> bool:
|
||||||
|
"""
|
||||||
|
Verify credentials and create a session.
|
||||||
|
Returns True if login successful, False otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def query(cursor):
|
||||||
|
password_hash = Admins.hash_password(password)
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT id FROM admins WHERE username = %s AND password_hash = %s AND telegram_id = %s",
|
||||||
|
(username, password_hash, telegram_id)
|
||||||
|
)
|
||||||
|
result = cursor.fetchone()
|
||||||
|
return result is not None
|
||||||
|
|
||||||
|
result = Admins._execute_query(query, "login")
|
||||||
|
|
||||||
|
if result:
|
||||||
|
# Create session by updating last_login and session_expires_at
|
||||||
|
def mutation(cursor, conn):
|
||||||
|
expires_at = datetime.now() + timedelta(hours=Admins.SESSION_TIMEOUT_HOURS)
|
||||||
|
cursor.execute(
|
||||||
|
"""UPDATE admins
|
||||||
|
SET last_login = CURRENT_TIMESTAMP,
|
||||||
|
session_expires_at = %s
|
||||||
|
WHERE telegram_id = %s""",
|
||||||
|
(expires_at, telegram_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Admins._execute_mutation(mutation, "login")
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_authenticated(telegram_id: int) -> bool:
|
||||||
|
"""Check if user has a valid active session"""
|
||||||
|
def query(cursor):
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT session_expires_at FROM admins WHERE telegram_id = %s",
|
||||||
|
(telegram_id,)
|
||||||
|
)
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
|
if not result or result[0] is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if session has expired
|
||||||
|
expires_at = result[0]
|
||||||
|
|
||||||
|
if isinstance(expires_at, str):
|
||||||
|
expires_at = datetime.fromisoformat(expires_at)
|
||||||
|
|
||||||
|
return datetime.now() < expires_at
|
||||||
|
|
||||||
|
result = Admins._execute_query(query, "is_authenticated")
|
||||||
|
return result if result is not None else False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def logout(telegram_id: int) -> bool:
|
||||||
|
"""Logout admin by clearing session"""
|
||||||
|
def mutation(cursor, conn):
|
||||||
|
cursor.execute(
|
||||||
|
"UPDATE admins SET session_expires_at = NULL WHERE telegram_id = %s",
|
||||||
|
(telegram_id,)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Admins._execute_mutation(mutation, "logout")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_session_info(telegram_id: int) -> dict:
|
||||||
|
"""Get session info for the admin"""
|
||||||
|
def query(cursor):
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT username, last_login, session_expires_at FROM admins WHERE telegram_id = %s",
|
||||||
|
(telegram_id,)
|
||||||
|
)
|
||||||
|
result = cursor.fetchone()
|
||||||
|
return result
|
||||||
|
|
||||||
|
result = Admins._execute_query(query, "get_session_info")
|
||||||
|
if not result:
|
||||||
|
return None
|
||||||
|
|
||||||
|
session_info = {
|
||||||
|
'username': result[0],
|
||||||
|
'last_login': result[1],
|
||||||
|
'expires_at': result[2],
|
||||||
|
'is_active': False
|
||||||
|
}
|
||||||
|
|
||||||
|
if result[2]:
|
||||||
|
expires_at = result[2]
|
||||||
|
|
||||||
|
if isinstance(expires_at, str):
|
||||||
|
expires_at = datetime.fromisoformat(expires_at)
|
||||||
|
|
||||||
|
session_info['is_active'] = datetime.now() < expires_at
|
||||||
|
session_info['time_remaining'] = str(
|
||||||
|
expires_at - datetime.now()).split('.')[0]
|
||||||
|
|
||||||
|
return session_info
|
||||||
|
|
||||||
|
|
||||||
class Students(BaseRepository):
|
class Students(BaseRepository):
|
||||||
table_name = "students"
|
table_name = "students"
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ load_dotenv()
|
|||||||
|
|
||||||
BOT_TOKEN = os.environ.get("BOT_TOKEN")
|
BOT_TOKEN = os.environ.get("BOT_TOKEN")
|
||||||
|
|
||||||
|
|
||||||
def ensure_no_webhook():
|
def ensure_no_webhook():
|
||||||
"""Remove webhook before starting polling"""
|
"""Remove webhook before starting polling"""
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
|
|||||||
Reference in New Issue
Block a user