فصل ۱۳: ارسال پیام زمان‌بندی‌شده با Job Queue

""

۱. مقدمه

فرض کنید می‌خواهید رباتتان به صورت خودکار:

  • هر روز صبح پیام هواشناسی بفرستد.
  • هر ساعت نرخ ارز را ارسال کند.
  • یا فقط در یک تاریخ و ساعت خاص به کاربر یادآوری بدهد.

برای این کار نیاز به Job Queue داریم.

📌 تعریف:
Job Queue در کتابخانه python-telegram-bot یک سیستم داخلی برای زمان‌بندی وظایف (Task Scheduling) است.
یعنی شما به آن می‌گویید “این تابع را در فلان زمان یا هر چند ثانیه یک بار اجرا کن” و خودش مدیریت می‌کند.


۲. چرا از Job Queue استفاده کنیم؟

روشمزایامعایب
Job Queue (داخلی)ساده، بدون نیاز به نصب Cron، همه چیز داخل کدوابسته به اجرای ربات؛ اگر خاموش شود، کارها متوقف می‌شوند
Cronjob (خارجی)اجرا حتی اگر ربات خاموش باشدنیاز به تنظیم در سرور و مدیریت جداگانه
Thread/while(True)کنترل کامل در کدخطر مصرف زیاد CPU یا RAM، مدیریت سخت‌تر

📌 نتیجه:
برای اکثر ربات‌های تلگرامی، Job Queue کافی و ایده‌آل است مگر این که بخواهید مستقل از اجرای ربات کار کند.


۳. روش‌های زمان‌بندی در Job Queue

Job Queue چند روش اصلی دارد:

متدتوضیحاستفاده
run_once(func, when)اجرای یک بار در زمان مشخصیادآوری یک قرار مهم
run_repeating(func, interval, first=None)اجرای تکراری با فاصله زمانی ثابتارسال نرخ ارز هر ۱۰ دقیقه
run_daily(func, time, days=(0,1,...))اجرای هر روز در ساعت مشخصگزارش هواشناسی هر صبح

۴. اولین مثال – ارسال پیام یک بار بعد از مدت مشخص

from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes

TOKEN = "توکن_ربات"

async def send_once(context: ContextTypes.DEFAULT_TYPE):
    await context.bot.send_message(context.job.chat_id, "⏰ این پیام بعد از ۱۰ ثانیه ارسال شد!")

async def start_timer(update, context):
    context.job_queue.run_once(send_once, when=10, chat_id=update.message.chat_id)
    await update.message.reply_text("✅ تایمر ۱۰ ثانیه‌ای فعال شد.")

app = ApplicationBuilder().token(TOKEN).build()
app.add_handler(CommandHandler("starttimer", start_timer))
app.run_polling()

📌 کاربرد:
برای مثال، وقتی کاربر درخواست “یادآوری ۱ ساعته” دارد.


۵. مثال دوم – اجرای تکراری هر چند دقیقه

async def send_repeated(context: ContextTypes.DEFAULT_TYPE):
    await context.bot.send_message(context.job.chat_id, "🔄 این پیام هر ۵ دقیقه ارسال می‌شود.")

async def repeat_timer(update, context):
    context.job_queue.run_repeating(
        send_repeated,
        interval=300,  # هر ۵ دقیقه
        first=0,       # بلافاصله بعد از دستور
        chat_id=update.message.chat_id
    )
    await update.message.reply_text("✅ تایمر ۵ دقیقه‌ای فعال شد.")

app.add_handler(CommandHandler("repeat", repeat_timer))

📌 کاربرد:
برای اعلان‌های دوره‌ای مثل قیمت ارز یا هشدار وضعیت.


۶. مثال سوم – اجرای روزانه سر ساعت

import datetime

async def send_daily_weather(context: ContextTypes.DEFAULT_TYPE):
    await context.bot.send_message(context.job.chat_id, "☀ هواشناسی امروز: آفتابی!")

async def daily_weather(update, context):
    context.job_queue.run_daily(
        send_daily_weather,
        time=datetime.time(hour=8, minute=0),
        days=(0,1,2,3,4,5,6),  # همه روزها
        chat_id=update.message.chat_id
    )
    await update.message.reply_text("📅 ارسال روزانه هواشناسی فعال شد!")

app.add_handler(CommandHandler("daily", daily_weather))

📌 کاربرد:
ارسال گزارش روزانه، پیام انگیزشی یا اخبار.


۷. ثبت کاربران برای ارسال پیام گروهی زمان‌بندی‌شده

ذخیره User ID در دیتابیس یا فایل:

users = set()

async def register(update, context):
    users.add(update.message.chat_id)
    await update.message.reply_text("✅ شما در لیست ارسال پیام قرار گرفتید.")

async def send_to_all(context):
    for uid in users:
        await context.bot.send_message(uid, "📢 پیام روزانه!")

async def set_broadcast(update, context):
    context.job_queue.run_daily(
        send_to_all,
        time=datetime.time(hour=9, minute=0)
    )
    await update.message.reply_text("📢 ارسال پیام به همه کاربران هر روز ساعت ۹ فعال شد.")

app.add_handler(CommandHandler("register", register))
app.add_handler(CommandHandler("broadcast", set_broadcast))

۸. نکات مهم عملی

  • ذخیره کاربران را حتماً در دیتابیس بگذارید، چون با ریستارت ربات لیست پاک می‌شود.
  • اگر از APIها استفاده می‌کنید، به محدودیت آن‌ها (Rate Limit) دقت کنید.
  • پیام‌های تکراری زیاد ممکن است باعث مزاحمت کاربر و بلاک شدن ربات شود.

۹. سوالات متداول

س: اگر کاربر بخواهد تایمر خود را لغو کند چطور؟
ج: باید Job را هنگام ایجاد ذخیره کنید و با job.schedule_removal() آن را حذف کنید.

س: اگر اینترنت یا ربات قطع شود چه می‌شود؟
ج: Job Queue متوقف می‌شود. بهتر است ربات را روی یک سرور یا سرویس پایدار (مثل VPS یا Railway) اجرا کنید.

س: آیا می‌توان زمان را بر اساس ساعت محلی کاربر تنظیم کرد؟
ج: بله، ولی باید ساعت محلی کاربر را بگیرید و تایم UTC را محاسبه کنید.


۱۰. اشتباهات رایج

اشتباهتوضیح
اجرای Job بدون پاک کردن قبلیباعث چندبار ارسال پیام یکسان می‌شود
تعیین interval کوتاهفشار به سرور و API زیاد می‌شود
ذخیره لیست کاربران در حافظهبا ریستارت پاک می‌شود

۱۱. نکات حرفه‌ای

  • ارسال داده‌های هوش مصنوعی به صورت روزانه (ترکیب فصل ۱۲ و ۱۳)
  • استفاده از Inline Button برای فعال/غیرفعال کردن Job
  • ثبت زمان Job در دیتابیس برای مدیریت بهتر
  • استفاده ترکیبی از Job Queue و Thread برای پردازش‌های طولانی
محمد وب‌سایت

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *