From 67a76250ab276505e10e2fff7dca946512f32a2e Mon Sep 17 00:00:00 2001 From: Hosein Date: Sun, 28 Dec 2025 10:49:50 +0330 Subject: [PATCH] testing tg bot library and set the db connection for dev and production --- bot.py | 134 +++++++++++++++++++++++++++++++++++------ database/connection.py | 15 +++-- database/models.py | 28 +++++++-- dev.py | 6 +- 4 files changed, 150 insertions(+), 33 deletions(-) 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