turns-00079.parquet:36147
861c8763ecfac9a41ffd8b6fdegenerate_repetitionAbsentFinal dense release
Select one behavior. Every returned turn has one binary label: Present or Absent. Source: final dense boolean release.
861c8763ecfac9a41ffd8b6fمن قطوتي؟
هل تقصد كلمة "قطوتي" باللهجة المحلية؟ عادةً، كلمة "قطوتي" تُستخدم كلقب دلع لكلمة "قطة" أو "قط"، وتعني شخصاً محبوباً أو لطيفاً كالقطة. هل ترغب في معرفة معنى محدد أو استخدام معين للكلمة؟ أم هل تقصد شيئاً آخر؟ يرجى توضيح السؤال أكثر لأتمكن من مساعدتك بشكل أفضل.
717634e3d6165b0133032a04Describe the significance, strengths, weaknesses, and hurdles of the Indian name 'Srijan', strictly keep it under 350 characters. add emojis if you can to make it more attractive.
'Srijan' (creation) symbolizes creativity & innovation 🌟. Strengths: unique, meaningful, and culturally rich 🇮🇳. Weaknesses: often mispronounced globally 🌍. Hurdles: spelling variations can cause confusion ✍️. Overall, it’s a powerful, inspiring name with deep roots and modern appeal! 💡✨
947e21cb79f8684641ac46dfكت
مرحبًا! كيف يمكنني مساعدتك اليوم؟
fbb5a8c11d7bdbe97aa89f46طرد
مرحبًا! هل يمكنك توضيح ماذا تقصد بكلمة "طرد"؟ هل تقصد طرد شيء ما، أم طرد شخص من مكان، أم شيء آخر؟ سأكون سعيدًا بمساعدتك إذا زودتني بمزيد من التفاصيل.
3ebef15e94a879726622de32Your task is to summarize the user's message in one short sentence that captures the emotional state and key concern. User message: I accidentally touched blood and now I feel anxious and can't stop thinking about getting infected.
The user feels anxious and worried about potential infection after accidentally touching blood.
0b80d97285a929f737aa5216بدي بوتات لل فيدوهات
أكيد! هل تقصد بوتات تساعدك في إنشاء فيديوهات أو تحريرها، أو بوتات تعمل على منصات معينة مثل تيك توك أو يوتيوب؟ وهل تفضل أن تكون هذه البوتات جاهزة للاستخدام أم تود إنشاء بوت خاص بك؟ لو تشرح لي أكثر عن احتياجك مثل نوع الفيديوهات، المنصة، والهدف، أقدر أساعدك بشكل أدق.
b1934481c8ccf05f70c284b4You are a cognitive behavioral therapist. Based on the following summary of the user's problem, generate a list of 5 CBT-based tasks. Each task must have a title and a short description. Respond in the following markdown format: 1. **Title** Description... 2. **Title** Description... 3. **Title** Description... 4. **Title** Description... 5. **Title** Description... Summary:
Could you please provide the summary of your problem? This will help me generate appropriate CBT-based tasks for you.
63650dd97169c16fe03e45d1User: hi, how are you? User: hi, how are you? Assistant:
Hello! I'm doing well, thank you. How can I assist you today?
182d3127a747a5cb97c32193اريد الكود الكامل لهذا
# 🌟 استيراد المكتبات اللازمة
from bs4 import BeautifulSoup
import requests
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
ApplicationBuilder,
CommandHandler,
MessageHandler,
ContextTypes,
filters,
CallbackQueryHandler,
ConversationHandler,
JobQueue
)
import logging
import nest_asyncio
import asyncio
from datetime import datetime, timedelta
import pytz
from tabulate import tabulate
import json
import os
# 🔄 تفعيل nest_asyncio للسماح بتشغيل event loop داخل بيئات Jupyter/Colab
nest_asyncio.apply()
# 🔑 توكن البوت (يجب أن يكون سرياً في التطبيقات الحقيقية)
TOKEN = "7563226990:AAFg2E5-f6EcVEjBK7ph5w8Q064P4daZlj0"
# 📝 إعداد تسجيل الأخطاء (Logging)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
# 🗃️ حالات المحادثة
ADD_NUMBER, DELETE_NUMBER, SCHEDULE_HOUR, SCHEDULE_AMPM = range(4)
# 📂 ملف تخزين الأرقام المحفوظة
SAVED_NUMBERS_FILE = "saved_numbers.json"
# 📂 ملف تخزين الأوقات المجدولة
SCHEDULED_TIMES_FILE = "scheduled_times.json"
# ⏰ تحديد المنطقة الزمنية لليمن
YEMEN_TZ = pytz.timezone('Asia/Aden')
# 💾 تحميل الأرقام المحفوظة من ملف JSON
def load_saved_numbers():
if os.path.exists(SAVED_NUMBERS_FILE):
try:
with open(SAVED_NUMBERS_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"خطأ في تحميل الأرقام المحفوظة: {e}")
return {}
return {}
# 💾 تحميل الأوقات المجدولة من ملف JSON
def load_scheduled_times():
if os.path.exists(SCHEDULED_TIMES_FILE):
try:
with open(SCHEDULED_TIMES_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"خطأ في تحميل الأوقات المجدولة: {e}")
return {}
return {}
# 💾 حفظ الأرقام المحفوظة في ملف JSON
def save_numbers_to_file(numbers):
try:
with open(SAVED_NUMBERS_FILE, 'w', encoding='utf-8') as f:
json.dump(numbers, f, ensure_ascii=False, indent=4)
except Exception as e:
logger.error(f"خطأ في حفظ الأرقام المحفوظة: {e}")
# 💾 حفظ الأوقات المجدولة في ملف JSON
def save_scheduled_times(times):
try:
with open(SCHEDULED_TIMES_FILE, 'w', encoding='utf-8') as f:
json.dump(times, f, ensure_ascii=False, indent=4)
except Exception as e:
logger.error(f"خطأ في حفظ الأوقات المجدولة: {e}")
# 💾 تهيئة تخزين الأرقام المحفوظة والأوقات المجدولة
saved_numbers = load_saved_numbers()
scheduled_times = load_scheduled_times()
scheduled_jobs = {}
# 🔍 دالة جديدة لجلب معلومات الرصيد باستخدام requests و BeautifulSoup
def get_adsl_info(phone_number):
try:
# رابط الصفحة
url = "http://adsl-yemen.com/adsl4.php"
# بيانات POST المطلوبة
data = {
'mobile': phone_number,
'action': 'query' # قد تحتاج إلى تعديل هذا حسب الموقع الفعلي
}
# إرسال الطلب مع محاولة محاكاة متصفح
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'http://adsl-yemen.com/adsl4.php',
'Origin': 'http://adsl-yemen.com'
}
response = requests.post(url, data=data, headers=headers)
response.raise_for_status() # التحقق من عدم وجود أخطاء في الطلب
# تحليل محتوى HTML
soup = BeautifulSoup(response.text, 'html.parser')
# استخراج البيانات - هذه انتقاءات افتراضية، يجب تعديلها حسب الهيكل الفعلي للصفحة
current_balance_div = soup.find("div", string="الرصيد الحالي")
package_value_div = soup.find("div", string="قيمة الباقة")
expiry_date_div = soup.find("div", string="تاريخ الانتهاء")
# الحصول على القيم
current_balance = current_balance_div.find_next_sibling("div").text.strip() if current_balance_div else "غير متوفر"
package_value = package_value_div.find_next_sibling("div").text.strip() if package_value_div else "غير متوفر"
expiry_date = expiry_date_div.find_next_sibling("div").text.strip() if expiry_date_div else "غير متوفر"
return {
'current_balance': current_balance,
'package_value': package_value,
'expiry_date': expiry_date,
'timestamp': datetime.now(YEMEN_TZ).strftime("%Y-%m-%d %H:%M:%S")
}
except requests.exceptions.RequestException as e:
logger.error(f"خطأ في الاتصال بالموقع: {e}")
return None
except Exception as e:
logger.error(f"حدث خطأ أثناء استعلام الرصيد: {e}")
return None
# 📨 دالة لإرسال نتائج الاستعلام (تبقى كما هي)
async def send_balance_info(update, phone_number, info):
if info:
response = (
f"📊 *نتائج استعلام رصيد ADSL*\n"
f"══════════════════════════\n"
f"📱 *الرقم:* `{phone_number}`\n"
f"⏰ *وقت الاستعلام:* {info['timestamp']}\n\n"
f"💵 *الرصيد الحالي:* `{info['current_balance']}`\n"
f"💰 *قيمة الباقة:* `{info['package_value']}`\n"
f"📅 *تاريخ الانتهاء:* `{info['expiry_date']}`\n\n"
f"✨ يمكنك إضافة هذا الرقم إلى المحفوظات للاستعلام عنه لاحقاً"
)
else:
response = (
"⚠️ *عذراً، تعذر الحصول على معلومات الرصيد*\n"
"══════════════════════════\n"
"🛑 *الأسباب المحتملة:*\n"
"• الرقم غير مسجل في خدمة ADSL\n"
"• وجود مشكلة تقنية مؤقتة\n"
"• خطأ في الاتصال بالخادم\n\n"
"🔍 يرجى التأكد من الرقم والمحاولة لاحقاً"
)
if isinstance(update, Update):
await update.message.reply_text(response, parse_mode='Markdown')
else:
await update.reply_text(response, parse_mode='Markdown')
# ... (بقية الدوال تبقى كما هي بدون تغيير)
# 🎉 أمر /start (يتبقى كما هو)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""إرسال رسالة ترحيبية احترافية مع قائمة الأزرار"""
user = update.effective_user
# 🌈 رسالة ترحيبية شاملة
welcome_message = (
f"✨ *مرحباً بك {user.first_name} في بوت استعلام رصيد ADSL اليمن* ✨\n\n"
"🚀 *خدمات البوت المتكاملة:*\n"
"▫️ استعلام فوري عن رصيد أي خط ADSL\n"
"▫️ إدارة الأرقام المحفوظة بسهولة\n"
"▫️ جدولة استعلامات تلقائية يومية\n"
"▫️ عرض التقارير المفصلة\n\n"
"📌 *كيفية الاستخدام:*\n"
"▪️ أرسل رقم الهاتف مباشرة للاستعلام الفوري\n"
"▪️ أو استخدم القائمة أدناه للوصول إلى جميع الميزات\n\n"
"🔘 *الرجاء اختيار أحد الخيارات التالية:*"
)
keyboard = [
[InlineKeyboardButton("➕ إضافة رقم جديد", callback_data='add_number'),
InlineKeyboardButton("🗂️ عرض الأرقام", callback_data='show_numbers')],
[InlineKeyboardButton("🔍 استعلام الأرقام", callback_data='query_numbers'),
InlineKeyboardButton("🗑️ إدارة الأرقام", callback_data='manage_numbers')],
[InlineKeyboardButton("⏰ جدولة تلقائية", callback_data='schedule_query'),
InlineKeyboardButton("ℹ️ المساعدة", callback_data='help')],
[InlineKeyboardButton("🔄 تحديث البوت", callback_data='refresh')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
if update.message:
await update.message.reply_text(welcome_message, reply_markup=reply_markup, parse_mode='Markdown')
else:
await update.callback_query.edit_message_text(welcome_message, reply_markup=reply_markup, parse_mode='Markdown')
# ... (بقية الدوال تبقى كما هي بدون تغيير)
# 🚀 تشغيل البوت (يتبقى كما هو)
async def run_bot():
# إنشاء Application مع JobQueue
application = ApplicationBuilder().token(TOKEN).build()
# إضافة مهمة دورية للتحقق من الأوقات المجدولة كل دقيقة
job_queue = application.job_queue
if job_queue:
job_queue.run_repeating(
check_scheduled_times,
interval=60.0, # كل دقيقة
first=10.0 # البدء بعد 10 ثواني
)
# إعداد معالج المحادثة مع per_message=True
conv_handler = ConversationHandler(
entry_points=[CallbackQueryHandler(button_handler)],
states={
ADD_NUMBER: [MessageHandler(filters.TEXT & ~filters.COMMAND, add_number)],
DELETE_NUMBER: [CallbackQueryHandler(delete_number)],
SCHEDULE_HOUR: [CallbackQueryHandler(schedule_hour)],
SCHEDULE_AMPM: [CallbackQueryHandler(schedule_ampm)]
},
fallbacks=[CommandHandler("start", start)],
per_message=True # هذا يحل التحذير الأول
)
# 🛠️ تسجيل المعالجات
application.add_handler(CommandHandler("start", start))
application.add_handler(conv_handler)
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
application.add_error_handler(error_handler)
logger.info("🤖 البوت يعمل...")
await application.run_polling()
# التشغيل الرئيسي (يتبقى كما هو)
if __name__ == '__main__':
try:
asyncio.run(run_bot())
except KeyboardInterrupt:
logger.info("⏹️ إيقاف البوت بواسطة المستخدم")
except Exception as e:
logger.error(f"❌ فشل تشغيل البوت: {e}")بالطبع! إليك الكود الكامل لكود البوت الذي طلبته مع جميع التعريفات اللازمة ليعمل بوت تلغرام متكامل للاستعلام عن رصيد ADSL مع إدارة الأرقام وجهات الجدولة. تأكد من استبدال توكن بوتك في المتغير `TOKEN`.
```python
# 🌟 استيراد المكتبات اللازمة
from bs4 import BeautifulSoup
import requests
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
ApplicationBuilder,
CommandHandler,
MessageHandler,
ContextTypes,
filters,
CallbackQueryHandler,
ConversationHandler,
JobQueue
)
import logging
import nest_asyncio
import asyncio
from datetime import datetime, timedelta
import pytz
from tabulate import tabulate
import json
import os
# 🔄 تفعيل nest_asyncio للسماح بتشغيل event loop داخل بيئات Jupyter/Colab
nest_asyncio.apply()
# 🔑 توكن البوت (يجب تغييره إلى توكن بوتك الخاص)
TOKEN = "7563226990:AAFg2E5-f6EcVEjBK7ph5w8Q064P4daZlj0"
# 📝 إعداد تسجيل الأخطاء (Logging)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
# 🗃️ حالات المحادثة للـ ConversationHandler
ADD_NUMBER, DELETE_NUMBER, SCHEDULE_HOUR, SCHEDULE_AMPM = range(4)
# 📂 ملفات تخزين الأرقام المجدولة والوقت
SAVED_NUMBERS_FILE = "saved_numbers.json"
SCHEDULED_TIMES_FILE = "scheduled_times.json"
# ⏰ المنطقة الزمنية لليمن
YEMEN_TZ = pytz.timezone('Asia/Aden')
# 💾 تحميل الأرقام المحفوظة من ملف JSON
def load_saved_numbers():
if os.path.exists(SAVED_NUMBERS_FILE):
try:
with open(SAVED_NUMBERS_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"خطأ في تحميل الأرقام المحفوظة: {e}")
return {}
return {}
# 💾 تحميل الأوقات المجدولة من ملف JSON
def load_scheduled_times():
if os.path.exists(SCHEDULED_TIMES_FILE):
try:
with open(SCHEDULED_TIMES_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"خطأ في تحميل الأوقات المجدولة: {e}")
return {}
return {}
# 💾 حفظ الأرقام المحفوظة في ملف JSON
def save_numbers_to_file(numbers):
try:
with open(SAVED_NUMBERS_FILE, 'w', encoding='utf-8') as f:
json.dump(numbers, f, ensure_ascii=False, indent=4)
except Exception as e:
logger.error(f"خطأ في حفظ الأرقام المحفوظة: {e}")
# 💾 حفظ الأوقات المجدولة في ملف JSON
def save_scheduled_times(times):
try:
with open(SCHEDULED_TIMES_FILE, 'w', encoding='utf-8') as f:
json.dump(times, f, ensure_ascii=False, indent=4)
except Exception as e:
logger.error(f"خطأ في حفظ الأوقات المجدولة: {e}")
# 💾 البيانات المحفوظة بالأرقام والأوقات
saved_numbers = load_saved_numbers() # شكل: {user_id: [numbers]}
scheduled_times = load_scheduled_times() # شكل: {user_id: {"hour": int, "ampm": "AM"/"PM"}}
scheduled_jobs = {} # لتخزين الـ jobs التي ستُلغى أو تُحدث
# 🔍 دالة لجلب معلومات الرصيد من موقع ADSL اليمن
def get_adsl_info(phone_number: str):
try:
url = "http://adsl-yemen.com/adsl4.php"
data = {
'mobile': phone_number,
'action': 'query'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'Referer': url,
'Origin': 'http://adsl-yemen.com'
}
response = requests.post(url, data=data, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# پيش فرض: استخراج على شكل div يحمل عناوين ثم قيم بجانبه
def get_field_value(field_name):
label = soup.find("div", string=field_name)
if label:
sib = label.find_next_sibling("div")
if sib:
return sib.text.strip()
return "غير متوفر"
current_balance = get_field_value("الرصيد الحالي")
package_value = get_field_value("قيمة الباقة")
expiry_date = get_field_value("تاريخ الانتهاء")
return {
'current_balance': current_balance,
'package_value': package_value,
'expiry_date': expiry_date,
'timestamp': datetime.now(YEMEN_TZ).strftime("%Y-%m-%d %H:%M:%S")
}
except requests.exceptions.RequestException as e:
logger.error(f"خطأ في الاتصال بالموقع: {e}")
return None
except Exception as e:
logger.error(f"حدث خطأ أثناء استعلام الرصيد: {e}")
return None
# 📨 دالة لإرسال نتائج الاستعلام للمستخدم
async def send_balance_info(update_or_context, phone_number, info):
if info:
response = (
f"📊 *نتائج استعلام رصيد ADSL*\n"
f"══════════════════════════\n"
f"📱 *الرقم:* `{phone_number}`\n"
f"⏰ *وقت الاستعلام:* {info['timestamp']}\n\n"
f"💵 *الرصيد الحالي:* `{info['current_balance']}`\n"
f"💰 *قيمة الباقة:* `{info['package_value']}`\n"
f"📅 *تاريخ الانتهاء:* `{info['expiry_date']}`\n\n"
f"✨ يمكنك إضافة هذا الرقم إلى المحفوظات للاستعلام عنه لاحقاً"
)
else:
response = (
"⚠️ *عذراً، تعذر الحصول على معلومات الرصيد*\n"
"══════════════════════════\n"
"🛑 *الأسباب المحتملة:*\n"
"• الرقم غير مسجل في خدمة ADSL\n"
"• وجود مشكلة تقنية مؤقتة\n"
"• خطأ في الاتصال بالخادم\n\n"
"🔍 يرجى التأكد من الرقم والمحاولة لاحقاً"
)
# update_or_context يمكن أن يكون من نوع Update أو ContextTypes.DEFAULT_TYPE
if hasattr(update_or_context, "message") and update_or_context.message:
await update_or_context.message.reply_text(response, parse_mode='Markdown')
elif hasattr(update_or_context, "reply_text"):
await update_or_context.reply_text(response, parse_mode='Markdown')
else:
logger.warning("تعذر إرسال رسالة الاستعلام، لم يتم تحديد update أو context مناسب")
# 🧩 إدارة أزرار القائمة الرئيسية
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
user_id = str(update.effective_user.id)
if query.data == 'add_number':
await query.edit_message_text("📥 الرجاء إرسال رقم الهاتف لإضافته (مثال: 777123456):")
return ADD_NUMBER
elif query.data == 'show_numbers':
numbers = saved_numbers.get(user_id, [])
if not numbers:
text = "⚠️ لا توجد أرقام محفوظة لديك الآن."
else:
text = "📋 *الأرقام المحفوظة لديك:*\n\n" + "\n".join(f"▫️ {num}" for num in numbers)
await query.edit_message_text(text, parse_mode='Markdown')
return ConversationHandler.END
elif query.data == 'query_numbers':
numbers = saved_numbers.get(user_id, [])
if not numbers:
await query.edit_message_text("⚠️ لا توجد أرقام محفوظة للاستعلام عنها. أضف أولاً رقم باستخدام القائمة.")
return ConversationHandler.END
keyboard = [[InlineKeyboardButton(num, callback_data=f"query_{num}")] for num in numbers]
keyboard.append([InlineKeyboardButton("🔙 العودة", callback_data='back_to_menu')])
reply_markup = InlineKeyboardMarkup(keyboard)
await query.edit_message_text("🔍 اختر رقم للاستعلام عن رصيده:", reply_markup=reply_markup)
return ConversationHandler.END
elif query.data.startswith('query_'):
phone_number = query.data.split('_', 1)[1]
await query.edit_message_text(f"⏳ جارٍ استعلام الرصيد للرقم: {phone_number} ...")
info = await asyncio.to_thread(get_adsl_info, phone_number)
await send_balance_info(update.callback_query, phone_number, info)
await query.edit_message_text("✅ تم الانتهاء من الاستعلام.\n\n↩️ استخدم /start للرجوع إلى القائمة الرئيسية.")
return ConversationHandler.END
elif query.data == 'manage_numbers':
numbers = saved_numbers.get(user_id, [])
if not numbers:
await query.edit_message_text("⚠️ لا توجد أرقام لإدارتها حالياً.")
return ConversationHandler.END
keyboard = [[InlineKeyboardButton(f"❌ حذف {num}", callback_data=f"delete_{num}")] for num in numbers]
keyboard.append([InlineKeyboardButton("🔙 العودة", callback_data='back_to_menu')])
reply_markup = InlineKeyboardMarkup(keyboard)
await query.edit_message_text("🗑️ اختر رقم للحذف:", reply_markup=reply_markup)
return DELETE_NUMBER
elif query.data.startswith('delete_'):
phone_number = query.data.split('_', 1)[1]
numbers = saved_numbers.get(user_id, [])
if phone_number in numbers:
numbers.remove(phone_number)
saved_numbers[user_id] = numbers
save_numbers_to_file(saved_numbers)
await query.edit_message_text(f"✅ تم حذف الرقم `{phone_number}` بنجاح.", parse_mode='Markdown')
else:
await query.edit_message_text("⚠️ الرقم غير موجود بالمحفوظات.")
return ConversationHandler.END
elif query.data == 'schedule_query':
await query.edit_message_text(
"⏰ قم باختيار الساعة التي تريد أن يتم الاستعلام التلقائي عندها:\n\n" +
"\n".join(
[f"{h} {'ص' if h < 12 else 'م'}" for h in range(1, 13)]
)
)
keyboard = []
for h in range(1, 13):
keyboard.append([InlineKeyboardButton(str(h), callback_data=f"hour_{h}")])
reply_markup = InlineKeyboardMarkup(keyboard)
await query.edit_message_text("⏰ اختر الساعة من 1 إلى 12:", reply_markup=reply_markup)
return SCHEDULE_HOUR
elif query.data.startswith('hour_'):
hour = int(query.data.split('_')[1])
context.user_data['schedule_hour'] = hour
keyboard = [
[InlineKeyboardButton("ص (AM)", callback_data="ampm_AM"),
InlineKeyboardButton("م (PM)", callback_data="ampm_PM")]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.edit_message_text(f"⏰ اختر الفترة (ص / م) للساعة {hour}:", reply_markup=reply_markup)
return SCHEDULE_AMPM
elif query.data.startswith('ampm_'):
ampm = query.data.split('_')[1]
user_id = str(update.effective_user.id)
hour = context.user_data.get('schedule_hour')
if hour is None:
await query.edit_message_text("❌ حدث خطأ: لم يتم اختيار الساعة.")
return ConversationHandler.END
# تحويل الساعة بص/م إلى 24 ساعة
if ampm == "AM":
hour_24 = hour % 12 # 12 صباحًا = 0 ساعة
else:
hour_24 = (hour % 12) + 12 # 12 مساءً = 12 ساعة أو غيرها
scheduled_times[user_id] = {"hour": hour_24}
save_scheduled_times(scheduled_times)
# إلغاء جدولة سابقة إن وجدت
if user_id in scheduled_jobs:
scheduled_jobs[user_id].schedule_removal()
del scheduled_jobs[user_id]
# إضافة مهمة مجدولة جديدة
app = context.application
job = app.job_queue.run_daily(
scheduled_query_callback,
time=datetime.now(YEMEN_TZ).replace(hour=hour_24, minute=0, second=0, microsecond=0).timetz(),
days=(0, 1, 2, 3, 4, 5, 6),
context=user_id,
name=user_id
)
scheduled_jobs[user_id] = job
await query.edit_message_text(f"✅ تم جدولة الاستعلام التلقائي يومياً في الساعة {hour} {ampm}")
return ConversationHandler.END
elif query.data == "help":
help_text = (
"ℹ️ *كيفية استخدام بوت استعلام رصيد ADSL:*\n\n"
"• أرسل رقم الهاتف مباشرة للاستعلام الفوري.\n"
"• استخدم القائمة لإضافة أرقام، عرضها، أو جدولتها.\n"
"• يمكنك جدولة استعلام يومي أو حذف أرقام من المحفوظات.\n"
"• البوت يدعم المنطقة الزمنية لليمن.\n\n"
"⚠️ *ملاحظة:* تأكد من إدخال رقم سليم ومن ضمن شبكة ADSL اليمن."
)
await query.edit_message_text(help_text, parse_mode='Markdown')
return ConversationHandler.END
elif query.data == 'refresh':
await start(update, context)
return ConversationHandler.END
elif query.data == 'back_to_menu':
await start(update, context)
return ConversationHandler.END
else:
await query.edit_message_text("❌ خيار غير معروف، الرجاء المحاولة مرة أخرى.")
return ConversationHandler.END
# 📨 إضافة رقم جديد
async def add_number(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_id = str(update.effective_user.id)
text = update.message.text.strip()
if not text.isdigit():
await update.message.reply_text("⚠️ الرقم غير صحيح، الرجاء إرسال رقم صحيح يتكون من أرقام فقط.")
return ADD_NUMBER
numbers = saved_numbers.get(user_id, [])
if text in numbers:
await update.message.reply_text("⚠️ هذا الرقم محفوظ لديك مسبقاً.")
return ConversationHandler.END
numbers.append(text)
saved_numbers[user_id] = numbers
save_numbers_to_file(saved_numbers)
await update.message.reply_text(f"✅ تم إضافة الرقم `{text}` إلى المحفوظات.", parse_mode='Markdown')
return ConversationHandler.END
# 🗑️ حذف رقم - المعالج هو CallbackQueryHandler لذلك أدرجناه في button_handler مباشرة
# ⏰ مهمة الاستعلام المجدول التي تعمل يومياً
async def scheduled_query_callback(context: ContextTypes.DEFAULT_TYPE):
user_id = context.job.context
user = await context.bot.get_chat(user_id)
user_numbers = saved_numbers.get(user_id, [])
if not user_numbers:
logger.info(f"المستخدم {user_id} لا يملك أرقام محفوظة للاستعلام المجدول.")
return
for number in user_numbers:
info = await asyncio.to_thread(get_adsl_info, number)
message = (
f"📅 *استعلام رصيد ADSL المجدول*\n"
f"⏰ {datetime.now(YEMEN_TZ).strftime('%Y-%m-%d %H:%M:%S')}\n"
f"📱 الرقم: `{number}`\n"
)
if info:
message += (
f"💵 الرصيد الحالي: `{info['current_balance']}`\n"
f"💰 قيمة الباقة: `{info['package_value']}`\n"
f"📅 تاريخ الانتهاء: `{info['expiry_date']}`"
)
else:
message += "⚠️ لم نتمكن من جلب بيانات الرصيد."
await context.bot.send_message(chat_id=user_id, text=message, parse_mode='Markdown')
# 📩 التعامل مع رسالة نصية عادية (أرسلت رقم للاستعلام السريع)
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
text = update.message.text.strip()
if text.isdigit():
# استعلام سريع عن الرصيد لرقم واحد
await update.message.reply_text(f"⏳ جارٍ استعلام رصيد الرقم {text} ...")
info = await asyncio.to_thread(get_adsl_info, text)
await send_balance_info(update, text, info)
else:
await update.message.reply_text("⚠️ يرجى إرسال رقم هاتف صالح للاستعلام أو استخدم /start لعرض القائمة.")
# 📛 معالج الأخطاء
async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
logger.error(msg="حدث خطأ غير متوقع:", exc_info=context.error)
if isinstance(update, Update) and update.message:
await update.message.reply_text("❌ حدث خطأ داخلي، الرجاء المحاولة لاحقاً أو التواصل مع الدعم.")
# ⏰ فحص الأوقات المجدولة تلقائياً خلال الـ JobQueue (يمكن استخدامه للتحقق من تغيرات أخرى إذا أردت)
async def check_scheduled_times(context: ContextTypes.DEFAULT_TYPE):
# لا حاجة لعمل أي شيء لأننا جدولنا run_daily لكل مستخدم سواء
pass
# 🎉 أمر /start - الترحيب مع عرض القائمة الرئيسية
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user = update.effective_user
welcome_message = (
f"✨ *مرحباً بك {user.first_name} في بوت استعلام رصيد ADSL اليمن* ✨\n\n"
"🚀 *خدمات البوت المتكاملة:*\n"
"▫️ استعلام فوري عن رصيد أي خط ADSL\n"
"▫️ إدارة الأرقام المحفوظة بسهولة\n"
"▫️ جدولة استعلامات تلقائية يومية\n"
"▫️ عرض التقارير المفصلة\n\n"
"📌 *كيفية الاستخدام:*\n"
"▪️ أرسل رقم الهاتف مباشرة للاستعلام الفوري\n"
"▪️ أو استخدم القائمة أدناه للوصول إلى جميع الميزات\n\n"
"🔘 *الرجاء اختيار أحد الخيارات التالية:*"
)
keyboard = [
[InlineKeyboardButton("➕ إضافة رقم جديد", callback_data='add_number'),
InlineKeyboardButton("🗂️ عرض الأرقام", callback_data='show_numbers')],
[InlineKeyboardButton("🔍 استعلام الأرقام", callback_data='query_numbers'),
InlineKeyboardButton("🗑️ إدارة الأرقام", callback_data='manage_numbers')],
[InlineKeyboardButton("⏰ جدولة تلقائية", callback_data='schedule_query'),
InlineKeyboardButton("ℹ️ المساعدة", callback_data='help')],
[InlineKeyboardButton("🔄 تحديث البوت", callback_data='refresh')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
if update.message:
await update.message.reply_text(welcome_message, reply_markup=reply_markup, parse_mode='Markdown')
elif update.callback_query:
await update.callback_query.edit_message_text(welcome_message, reply_markup=reply_markup, parse_mode='Markdown')
# 🚀 تشغيل البوت
async def run_bot():
application = ApplicationBuilder().token(TOKEN).build()
job_queue = application.job_queue
if job_queue:
job_queue.run_repeating(check_scheduled_times, interval=60.0, first=10.0)
conv_handler = ConversationHandler(
entry_points=[CallbackQueryHandler(button_handler)],
states={
ADD_NUMBER: [MessageHandler(filters.TEXT & ~filters.COMMAND, add_number)],
DELETE_NUMBER: [CallbackQueryHandler(button_handler)], # حذف رقم يتم من button_handler
SCHEDULE_HOUR: [CallbackQueryHandler(button_handler)],
SCHEDULE_AMPM: [CallbackQueryHandler(button_handler)]
},
fallbacks=[CommandHandler("start", start)],
per_message=True
)
application.add_handler(CommandHandler("start", start))
application.add_handler(conv_handler)
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
application.add_error_handler(error_handler)
logger.info("🤖 البوت يعمل...")
await application.run_polling()
if __name__ == '__main__':
try:
asyncio.run(run_bot())
except KeyboardInterrupt:
logger.info("⏹️ إيقاف البوت بواسطة المستخدم")
except Exception as e:
logger.error(f"❌ فشل تشغيل البوت: {e}")
```
---
## شرح سريع
- البوت يسمح:
- إضافة أرقام وإدارتها وحذفها.
- استعلام فوري بأي رقم.
- جدولة استعلام يومية حسب ساعة ص/م.
- البيانات تحفظ في ملفات JSON مستقلة (يمكن تعديلها حسب الحاجة).
- الجدولة تنفذ عبر `JobQueue` وتراعي المنطقة الزمنية لليمن.
- الكود متوافق مع `python-telegram-bot v20+` بطريقة asyncio الحديثة.
- يمكن تطوير الـ `get_adsl_info` حسب الصفحة الحقيقية لموقع adsl-yemen.com إذا تغيرت الهيكلة.
---
إذا احتجت مساعدات إضافية أو شرح لكيفية تشغيل البوت أو نشره، فقط أخبرني! 🌟0fa74606ca2be57773e787daظهر هذا الخطاء
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-23-cfcd08d64263> in <cell line: 0>()
2 from bs4 import BeautifulSoup
3 import requests
----> 4 from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
5 from telegram.ext import (
6 ApplicationBuilder,
ModuleNotFoundError: No module named 'telegram'
---------------------------------------------------------------------------
NOTE: If your import is failing due to a missing package, you can
manually install dependencies using either !pip or !apt.
To view examples of installing some common dependencies, click the
"Open Examples" button below.
---------------------------------------------------------------------------الخطأ الذي ظهر لك هو `ModuleNotFoundError: No module named 'telegram'`، وهذا يعني أن مكتبة `python-telegram-bot` غير مثبتة في بيئة العمل التي تستخدمها (على سبيل المثال: Jupyter Notebook أو Google Colab أو بيئة أخرى). لحل هذه المشكلة، يمكنك تثبيت المكتبة باستخدام أمر `pip` في الخلية الخاصة بالـ Jupyter أو من الطرفية (Terminal): ```python !pip install python-telegram-bot --upgrade ``` أو في حال كنت تستخدم بيئة عادية (Terminal / Command Prompt): ```bash pip install python-telegram-bot --upgrade ``` --- ### بعد التثبيت قم بإعادة تشغيل النواة (restart kernel) أو جلسة العمل، ثم أعد تشغيل الكود الخاص بالبوت. --- ### ملاحظة: - تأكد من أنك تستخدم إصدار Python 3.7 أو أحدث، لأن `python-telegram-bot v20` يحتاج لهذه الإصدارات. - إذا كنت تستخدم Google Colab، الأمر `!pip install` في خلية كود هو ما تحتاجه غالبًا. --- هل تحتاج مساعدة في تشغيل التثبيت، أو لديك استفسار آخر؟