diff --git a/bot.py b/bot.py
index 7bc0f9b..ea50357 100644
--- a/bot.py
+++ b/bot.py
@@ -1,10 +1,12 @@
import os
import logging
-from database.models import testModel
-from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
+from database.models import Students
+from telebot import types
+from datetime import datetime
logger = logging.getLogger(__name__)
+authenticated_users = {2032936226}
_bot = None
def get_bot():
@@ -16,33 +18,125 @@ def get_bot():
@_bot.message_handler(commands=["start"])
def start(message):
- _bot.reply_to(message, "Welcome! Use /getdata to fetch from database.")
+ if message.from_user.id in authenticated_users:
+ _bot.reply_to(message, "authorized user! Welcome. Use /getstudents to fetch from database.")
+ return
+ _bot.reply_to(message, "Welcome! Use /getstudents to fetch from database.")
- @_bot.message_handler(commands=["getdata"])
+ @_bot.message_handler(commands=["getstudents"])
def get_data(message):
try:
- data = testModel.getAllUsers()
+ data = Students.getAllStudents()
if data:
- _bot.reply_to(message, f"Data: {data}")
- response = "";
- for i in range(3):
- response += "\n";
- response += f"""
- 📚 {data[i][0]}
- نویسنده: {data[i][1]}
- موجودی: {data[i][3]}/{data[i][8]}
- کد: {data[i][1]}
- """
- _bot.reply_to(message, response, parse_mode='HTML')
+ markup = types.InlineKeyboardMarkup(row_width=2)
+ for row in data:
+ btn = types.InlineKeyboardButton(f"{row[0]}: @{row[1]}", 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 or database error.")
+ _bot.reply_to(message, "No data found.")
+ return
except Exception as e:
logger.error(f"Error in getdata handler: {e}")
_bot.reply_to(message, "Sorry, an error occurred.")
- @_bot.message_handler(func=lambda message: True)
- def echo_all(message):
- _bot.reply_to(message, f"You said: {message.text}")
+ # Single handler for all student selections
+ @_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()
+ markup.add(types.InlineKeyboardButton("🔙 Back", callback_data="back_to_students"))
+ _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.")
+
+ def format_student_info(student):
+ """
+ Format student data into a nice message
+ student is a tuple: (id, username, created_at, email, phone_number, last_seen, is_verified, birthday)
+ """
+ print(student);
+ id, username, 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"""
+ 👤 Student Profile
+
+ Username: {username}
+ Email: {email}
+ Phone: {phone_number}
+ Birthday: {birthday} (Age: {age})
+ Account Status: {verified_status}
+
+ 📅 Account Info
+ Joined: {created_date}
+ Last Seen: {last_seen_date}
+ ID: {id}
+ """
+ return details.strip()
+
+ 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"
+
+ @_bot.message_handler(commands=["test"])
+ def test_handler(message):
+ markup = types.ReplyKeyboardMarkup(row_width=2, one_time_keyboard=True)
+ btn1 = types.KeyboardButton("Option 1")
+ btn2 = types.KeyboardButton("Option 2")
+ markup.add(btn1, btn2)
+ _bot.reply_to(message, "Test command received!", reply_markup=markup)
+
+ @_bot.message_handler(func=lambda message: message.text in ["Option 1", "Option 2"])
+ def handle_test_options(message):
+ option = message.text
+ _bot.send_message(message.chat.id, f"You selected: {option}")
+
+ @_bot.message_handler(func=lambda message: True)
+ def handle_student_selection(message):
+ chat_id = message.chat.id
+ selected_text = message.text
+
+ _bot.reply_to(message, f"You said: {message.text}")
+
return _bot
\ No newline at end of file
diff --git a/database/connection.py b/database/connection.py
index 4a0fbdf..7e66c4e 100644
--- a/database/connection.py
+++ b/database/connection.py
@@ -9,15 +9,18 @@ logger = logging.getLogger(__name__)
_connection_pool = None
def get_connection_pool():
+ """Create a connection pool"""
global _connection_pool
if _connection_pool is None:
try:
- DATABASE_URL = os.environ.get("DATABASE_URL")
- _connection_pool = psycopg2.pool.SimpleConnectionPool(
- 1, # minimum connections
- 5, # maximum connections
- DATABASE_URL
- )
+ # --- Production settings
+ # DATABASE_URL = os.environ.get("DATABASE_URL")
+ # _connection_pool = psycopg2.pool.SimpleConnectionPool(1, 5, DATABASE_URL);
+
+ # --- Development settings
+ dev_url = "postgresql://postgres:123@localhost:5432/OLP"
+ _connection_pool = psycopg2.pool.SimpleConnectionPool(1, 5, dev_url);
+
logger.info("Database connection pool created")
except Exception as e:
logger.error(f"Failed to create connection pool: {e}")
diff --git a/database/models.py b/database/models.py
index d67b314..21be51d 100644
--- a/database/models.py
+++ b/database/models.py
@@ -4,8 +4,8 @@ import database.connection as connection
logger = logging.getLogger(__name__)
-class testModel:
- def getAllUsers():
+class Students:
+ def getAllStudents():
conn = None
try:
conn = connection.get_db_connection()
@@ -13,13 +13,33 @@ class testModel:
return None
cursor = conn.cursor()
- cursor.execute("SELECT * FROM students");
+ cursor.execute("SELECT id,name FROM students");
result = cursor.fetchall()
cursor.close()
return result if result else None
except Exception as e:
- logger.error(f"Database query error: {e}")
+ logger.error(f"Database query error in getAllStudents: {e}")
+ return None
+ finally:
+ if conn:
+ connection.release_db_connection(conn)
+
+ def getStudentById(student_id):
+ conn = None
+ try:
+ conn = connection.get_db_connection()
+ if not conn:
+ return None
+
+ cursor = conn.cursor()
+ cursor.execute("SELECT id,username, created_at, email, phone_number, last_seen, is_verfied, birthday FROM students WHERE id = %s", (student_id,))
+ result = cursor.fetchall()
+ cursor.close()
+
+ return result[0] if result else None
+ except Exception as e:
+ logger.error(f"Database query error in getStudentById: {e}")
return None
finally:
if conn:
diff --git a/dev.py b/dev.py
index 0695b8a..ff0e83a 100644
--- a/dev.py
+++ b/dev.py
@@ -22,6 +22,6 @@ def ensure_no_webhook():
if __name__ == "__main__":
if ensure_no_webhook():
- bot = get_bot()
- print("🤖 Bot is polling locally...")
- bot.polling(non_stop=True)
\ No newline at end of file
+ bot = get_bot()
+ print("🤖 Bot is polling locally...")
+ bot.polling(non_stop=True)
\ No newline at end of file