اخرین اپدیت : Pyrogram version >= 2.0
خب سلام دوستان.
قرار یه اموزش پروژه محور ربات client(یوزر بات، ربات cli ....) رو با هم باشیم اول کار تو این قسمت راجب یه سری مفاهیم پایه ای حرفه میزنیم و یه info کلی میدیم و در قسمت های بعد میایم ربات مون رو کم کم مینویسیم و کاملش میکنیم، تو این سری قرار نیست بیایم تمام متود های موجود و.. رو توضیح بدیم صرفا مواردی که مربوط به پروژه هستن رو توضیح میدیم و میریم جلو.
در اخر هر پست لینک گیت هاب پروژه قرار داده شده که میتونید برید و کد هایی که نوشتیم رو ببینید.
در کل میخوایم یک ربات بنویسیم که این قابلیت ها رو داشته باشه :
نحوه استفاده کردن از هندلر ها، raw متود ها ، step گذاری، متود های عادی و هندل کردن ارور های احتمالی و .. رو در این دوره با هم یاد میگیریم.
نکته: داکیومنت این لایبرری خیلی ساده و مناسب هستش میتونید مواردی که نیاز دارید رو داخل داکیومنت سرچ کنید و بخونیدش، توضیحات کامله و مثال های واضحی هم قرار داده شده .
نکته: در قسمت های بعدی برای قسمت step گذاری و... از دیتابیس استفاده میشه ولی میتویند از لایبرری pyromod هم استفاده بکنید، که تو لینک زیر آموزش استفادش رو گذاشتم.
اولین کاری که برای ساخت ربات client یا api در پروتکل mtproto باید انجام بدیم گرفتن api-id و api-hash هستش(میتونید از یک api-id و api-hash برای هرچند تا اکانت که نیاز دارید استفاده کنید ولی اگر با اکانت زیاد کار میکنید پیشنهاد نمیشه چون ممکنه تلگرام تشخصی بده و...)
خب چنتا راه دارید برای گرفتنش:
اول وارد سایت telegram میشید، بعد شماره تلفن تون رو وارد میکنید next رو میزنید و کدی برای شما راسال میشه رو وارد میکنید و sing in رو میزنید، در مرحله بعد یه فرم میاره برای شما که باید کاملش کنید، بعد از کامل کردنش( همینجوری پرش کنید هم زیاد مهم نیست) در آخر به شما یه api_id و یه api_hash میده(اگه از سایت تلگرام میگیرید، این روزا درست نمیده و Error میده، پس کشور تون رو تغیر بدید تا بلکه بتونید بگیرید ازش!) .
خب چرا ما از api-id و api-hash استفاده بکنیم!! اصلا برای چی هستن؟؟
خب باید بگم ما داریم با لایبرری پایروگرام کار میکنیم که با استفاده از پروتکل Mtproto به تلگرام وصل میشه و در این پروتکل ما باید از api-id و api-hash استفاده کنیم و بدونه این نمیتونیم وصل بشیم به سرورای تلگرام.
به صورت کلی برای تایید هویت application خودمون باید از api-id و api-hash استفاده کنیم
HTTP -------- HTTP/MTProto --------MTProto
[You] <------------> [Bot API] <--------------> [Telegram]
MTProto --------------------------------MTProto
[Pyrogram] <-------------------------------------> [Telegram]
خب بریم مواردی که نیاز داریم رو نصب کنیم:
pip install pyrogram pip install tgcrypto
اگه از لینوکس استفاده میکنید pip3 رو بزنید که برای پایتون 3 نصب بشه (البته اگه اپدیت باشید دیفالت پایتون 3 هستش و همون pip خالی اوکیه)
این tgcrypto که بالاتر نصب کردیم برای این هستش که کارایی و سرعت pyrogram بیشتر بشه، البته اختیاری هستش اگه ست نکنید از PyAES استفاده میکنه که کند تر هستش به نسبت... اگه خواستید در مورد tgcrypto بیشتر بدونید به این لینک مراجعه کنید.
اگه رو ویندوز هستید ممکن مشکلاتی برای شما پیش بیاد چون این tgcrypto یه سری دیپندنسی داره که باید از قبل نصب شده باشه مثلا رو ویندوز باید
نصب باشه و رو لینوکس یه کامپایلر برای c مثل gcc و همچنین python-dev باید نصب باشه که در لینوکس به صورت پیش فرض اوکیه ، اگر هم نبود!! خب با پیکج منیجرتون نصبش کنید :)
خب دیگه پیش نیاز ها رو نصب کردیم و الان وقت کد زدن هستش... ( یه فیلتر شکن یا پروکسی socks5 هم نیاز دارید اگه تلگرام فیلتر یا تحریم هستش تو کشور شما)
نکته: اگر نتونستید وصل بشید و ارورUnable to connect due to network issues: timed out
رو دریافت کردید این مربوط به فیلتر شکن(یا نتورک شما ) شما هستش که نتونسته کانکت بشه به تلگرام، بعضی فیلتر شکن ها ممکنه کار نکنن، علیرغم اینکه شما میتونید به تلگرام رو سیستم تون وصل بشید و اوکی هستش شاید اینجا این ارور بالا رو بگیرید ونتونید وصل بشید پس اگر همچین اروری گرفتید میتونید فیلتر شکن دیگه ای رو تست کنید.
from pyrogram import Client bot = Client(.....)
در کد بالا Client رو ایمپورت کردیم، هر رباتی که بنویسید نیاز دارید که Client رو ایمپورت کنید برای اینکه به تلگرام وصل بشید و قسمت تعامل شما با تلگرام رو هندل کنه( مثل این هستش که تلگرام رو باز کرده باشید ) خب الان یه اینستنس از کلاس Client ساختیم به اسم bot و خب الان ما به جای .... باید چی بزاریم؟؟
کلاس کلاینت پارامتر های مختلفی رو میگیره، مهم ترین هاش که حالا بیشتر استفاده میکنیم رو میگم بقیش رو هم میتونید از داکیومنتش ببینید...
* name(str)
خب اولین مورد که مهم هستش اسم سشن تون هست سشن چیه؟ خب وقتی شما به تلگرام وصل میشید یه فایل سشن در سیستم شما ایجاد میشه که دفعات بعدی خواستید کانکت بشید دیگه از شما رمز و پسورد نخواد البته اطلاعات بیشتری از اکانتتون هم داخلش ذخیره میشه برای همین دفعات بعدی نیازی نیست لاگین کنید... اگه نمیخواید سشن روی هارد شما ذخیره بشه، میتونید داخل مموری هم این سشن رو ایجاد کنید ولی بعد از دیزکانکت شدن شما یعنی وقتی پروسس مربوط به اسکریپتتون kill یا break بشه دیگه اون سشن از مموری پاک میشه و بهش دست رسی ندارید، البته میتونید قبل از اینکه break یا kill بشه از دستور
bot.export_session_string()
استفاده کنید و سشن استرینگ فعلی رو بدست بیارید بعدا دیگه نیاز نیست هربار اکسپورت کنید همین چیزی که بهتون میده رو بعدا میتونید ست کنید و ازش استفاده کنید یه همچین چیزی باید بهتون نشون بده
BAB-zAc9wtZY1SFBY5S-6AiSMyeJ6aLbIQT7JNpf9QOQwQ0W8GP0Fse..............
پس شد دو حالت یا داخل فایل ذخیره میشه که باید سشن نیم یه رشته استرینگ به عنوان اسم فایل بدیم بهش مثلا x یا y(بیشتر میایم اسم سشن رو برابر شماره تلفنی که وارد کردیم قرار میدیم که دیتکتش راحت تر باشه) یا اینکه بیایم اینجوری داخل مموری ذخیرش کنیم که باید بیایم از پارامتر in_memory استفاده کنیم .( این حالت دوم که داخل مموری ذخیره میشه رو هم بهش میگن سشن استرینگ)
* in_memory(bool)
برای اینکه از سشن استرینگ استفاده بکنیم باید این پارامتر رو هم قرار بدیم اگر true باشه از سشن استرینگ استفاده میکنه دیفالت False هستش.
* session_string(str)
برای اینکه از سشن استرینگ استفاده بکنیم باید سشن استرینگ مون رو با این پارامتر بدیم بهش البته name رو هم باید یه یچزی بزاریم(خالی هم باشه اوکیه)!
* api_id(int) , api_hash(str)
مورد بعدی هم که بالاتر توضیح دادیم باید این دو مورد رو هم ست کنید ، در ورژن v2.0 پایروگرام برای سشن هایی که از قبل ایجاد شدن لازم نیست ست بشه و بدونه این دو مورد هم کار میکنه.
* proxy(dict) --> dict(scheme="socks5", hostname=”127.0.0.0.1", port=9050, username="user", password="pass")
خب پایروگرام بهتون اجازه میده که از پروکسی socks5 و httpو socks4 به شکل بالا استفاده کنید.( tor برای این مورد خیلی خوبه:)) ) اگر پروکسیی که دارید username و پسورد نداره مثل tor اون قسمت رو ننویسید همون hostaname و port و scheme رو مشخص کنید کافیه.
* bot_token(str)
این مورد برای زمانی هستش که شما نمیخواید ربات client بنوییسد و صرفا میخواید ربات api بنویسید کافیه توکن رباتی که با بات فادر ساختید رو ست کنید .
force_sms(bool)
درمواردی که میخواید حتما تلگرام به شما code رو sms کنه با این اپشن میگید حتما sms کنه براتون.
workers(int)
با استفاده از این اپشن میتونید تعداد ترد های همزمانی که میخواید رو ست کنید، برای هندل کردن اپدیت هاتون که به صورت پیشفرض مقدار
min(32, os.cpu_count() + 4)
در نظر گرفته شده که اگه نیاز داشتید میتونید تغیرش بدید.
no_updates(bool)
این مورد بعضی جاها خیلی بدرد میخوره مثلا مثلا شما یه اکانت دارید که 5000 تا کانال و گروه.. عضو هستش و شما میخواید الان از همه اونا لفت بدید اگه این رو ست نکنید خب کل اپدیت های 5000 گروه رو دریافت میکنه و واقعا حجم زیادی داره ، هندل نمیشه و مشکلتون زیاد میشه ولی اگه ست کنید این رو دیگه اپدیتی دریافت نمیشه و خیلی راحت و سریع میتونید کاری که میخواید رو انجام بدید (البته که اپدیت رو نمیتونید بگیرید ولی بقی مواردی که نیازی به اپدیت ندارن و حجم اپدیت شما خیلی زیاد هستش این اپشن خیلی مفید هستش)( یه نکته دیگه اینکه اپدیت رو درسته نمیتونید بگیرید ولی get_history,... رو میتونید بگیرید که بعدا مثال هایی خواهیم زد)
from pyrogram import Client, filters bot = Client( name="new-client-bot", apit_id=your_api_id, api_hash="your_api_hash") @bot.on_message(filters.command("start")) async def test_bot(client, message): print(message) bot.run()
اول ما متود filters و Client رو ایمپورت کردیم، متود کلاینت برای کانکت شدن به تلگرام و.. استفاده میکنیم و از متود فیلتر برای فیلتر گذاشتن روی اپدیت ها استفاده میکینم ؛ همه اتفاق هایی که داخل اکانت رخ میده اپدیت هستش مثلا وقتی که شما وارد تلگرام میشید یه سری پیام ممکن برای شما بیاد حالا از گروه ها یا pv و کانال ها... همه این پیام ها اپدیت هستن یا یه فرد پیامی رو تو گروه pin میکنه یا جوین میده و... حالا میتونه تکست باشه یا فیلم باشه عکس،اهنگ،وویس و... همه این ها رو ما میتونیم داخل اپدیت دریافت کنیم. خب الان فک کنم واضع تر شده باشه که update دقیقا چی هستش .
ما میتونیم از filters استفاده کنیم تا برای یک سری اپدیت خاص یه عملی رو انجام بده مثلا میگیم اگر کامند بود بیا به کاربر پیام "سلام" بده ( کامند با / ( اسلش) شروع میشه) یا بیا پیام خوشآمدگویی رو به بده و یا یه info راجب ربات به کاربر بده و...( فیلتر ها رو ما میتونیم به شکل های مختلفی بنویسیم ) میتونید با زدن tab بقیه فیلتر ها رو هم ببینید داخل ادیتورتون(مثلا vsc)
@bot.on_message(filters.
در اینجا tab بزنید بهتون نشون میده(البته اگه ادیتورتون autocomplete برای پایتون داشته باشه) بعد داخل داکیومنت پایرو هم میتونید فیلتر مورد نظر رو سرچ کنید و اطلاعات بیشتری راجبش بدست بیارید(حتی میتونید از regex استفاده بکنید و قدرت مانور بیشتری داشته باشید و...)
اینجا اگه دقت کنید نوشتیم on_message به این میگن هندلر، ما هندلر های مختلفی رو داریم اینجا هندلر مون روی message هستش میتونه روی چیز های مختلفی باشه مثلا on_chat_join_request که وقتی کاربری تازه میخواد وارد گروه بشه و... در ادامه بیشتر میگیم..
ما میتونیم به 2 شکل هندل رو تعریف کنیم یا بیایم از متود add_handler استفاده کنیم یا اینکه از دیکوریتور استفاده کنیم .
@bot.on_message(filters.command('start')) async def test_bot(client, message):
در مثال بالا اومدیم یه دیکوریتور تعریف کردیم برای هندل کردن اپدیت هایی که میاد و با on_message نوع هندلر مون رو مشخص کردیم on پایه ثابت هستش و روی یه چیزی قرار میگیره در اینجا روی message ها هستش میتویند لیست دیکوریتور ها رو اینجا ببینید، اینجا ما یه فانکشن پایتونی زیر decorators نوشتیم که async هستش راجب async تو پایتون هم میتونید سرچ بکنید و یه آشنایی باهاش داشته باشید(در اینده بیشتر میگیم...).
بعد با استفاده از filter اومدیم گفتیم فقط کامند start/ رو بگیر داخل اپدیت ها(اینجا اگه خواستید چند تا کامند رو ست کنید براش میتونید به شکل لیست تعریف کنید (اون / رو هم میتونید تغیر بدید با استفاده از ارگمان prefixes
) ) و اگر کاربری الان start/ رو بفرسته به ربات در جواب ربات چیزی که درون تابع test_bot تعریف کردیم رو انجام میده اگه چیز دیگه ای رو هم بفرسته ربات کاری انجام نمیده. خود تابع test_bot هم 2 پارامتر client و message رو دریافت میکنه اولیش کلاینت و دومی هم اپدیت.
print(message)
در ادامش ما اومدیم اپدیتی که دریافت کردیم رو چاپ کردیم این اپدیت رو شما اگر کد رو اجرا کردید به دقت برسیش بکنید چون بیشتر مواردی که نیاز دارید در خود این اپدیت هستش و بیشتر کار ما هم با همین اپدیت ها هستش.. فرمتش به شکل json هست اگر اشنا نیستید با این فرمت سرچ کنید تو گوگل و یکم باهاش کار کنید چون در ادامه راه بهش نیاز پیدا میکنید.
تا اینجا ربات کار خاصی رو انجام نمیده یعنی اجرا نشده و به تلگرام کانکت نشده، برای اینکه کانکت بشه و دیگه رباتمون ران باشه میایم از متود run استفاده میکنیم
bot.run()
اینجا ما اون ابجکت bot که ساختیم رو run میکنیم و بعد از اینکه فایل پایتون مون رو اجرا بکنیم سعی میکنه با توجه به پارامتر هایی که براش ست کردیم(تو خط 2وم) به سرور تلگرام وصل بشه و بعد اگه start/ رو بفرستیم به ربات برامون اون اپدیت رو پرینت میکنه.
جدا از حالت بالا میتونید از متود های connect, start, idle هم استفاده کنید.
connect
میاد به سرور تلگرام وصل میشه و یه مقدار true یا false رو هم برمیگردونه(فقط اپدیت رو یادتون بمونه که نمیتونیم بگیریم چون کانکت میشه و بعد دیزکانکت).
start
مثل قبلی هستش با این تفاوت که مراحل لاگین کردن رو هم انجام میده بالاتر توضیح دادیم راجب سشن و این متود اگر سشن برای اولین بار ایجاد شده باشه مراحل گرفتن شماره، تایید کد و... رو انجام میده درضمن این متود مثل قبل بولین بر نمیگردونه و خود کلاینت رو استارت شدش رو برمیگردونه که میتونید ازش استفاده کنید(در ادامه ملموس تر میشه این قضیه)
idle
این متود هم برای زنده نگه داشتن اون کلاینت استفاده میشه در مورارد قبل اگر اجرا کنید اون مواردی که ست کرده باشید رو انجام میده و تموم میشه میاد بیرون exit میکنه میاد بیرون دیگه منتظره نمیمونه که ایا اپدیت جدیدی قرار بیاد یا نه و... با استفاده از این متود ما میتونیم اپدیت های جدیدی که میاد رو هم دریافت کنیم اگر از این متود استفاده کنیم باید قبلش کلاینت رو start کرده باشیم و بعد idle و در انتهای کد کلاینت رو stop کرده باشیم.
run
این متود شما همه متود های start, idle, stop رو انجام دادید در واقع کار رو اسون تر میکنه برای ما فقط تنها مشکلش و نقطه تمایزش با موارد قبل این هستش که این متود به ما اجازه نمیده چندین کلاینت ایجاد کنیم و فقط 1 کلاینت رو میتونیم اجرا کنیم اگه بیشتر باشه کلا block میکنه و اجرا نمیشه.
stop
زمانی که نیاز دارید ربات رو متوقف کنید از این متود میتونید استفاده کنید یه پارامتر رو میگیره به اسم block و زمانی بدرد میخوره که شما داخل یه هندلر بخواید ربات رو stop کنید اگه این ارگمانش رو ست نکنید به شکل کامل stop نمیشه و یه جورایی کدی که اجرا کردید کرش میکنه و بسته نمیشه مگر اینکه پروسسش رو kill کنید( درضمن این متود stop پروسس رو kill نمیکنه و فقط ربات رو stop میکنه و دیگه ربات کاری انجام نمیده) و حتی ممکن دیتابیس sqlite که پایرو استفاده میکنه lock شه(اگه کدی که استاپ شده رو suspend کنید).
خب بیایم کد بالا رو اجرا کنیم بیبنم چه اتفاقی میفته
خب همونطور که میبینید پیام اول که به ربات دادم start خالی بود یعنی یه تکست بود، در این حالت ربات بهش جواب نمیده ولی پیام دوم کامند start بود و ما این رو فیلتر کرده بودیم برای همین اون print ما انجام شد و update رو برامون چاپ کرد، همونطور که بالا تر گفتم فرمت اپدیت json هستش و باید کار کردن با این فورمت رو بلد باشید سخت نیست مثل دیکشنریه، مثلا اینجا میتونیم username, id زمان ارسال پیام نوع پیام و کلی چیز دیگه رو از اپدیت بگیریم و با توجه به نیازمون یه کارهایی رو انجام بدیم..
کد هایی که نوشتیم رو هم در لینک زیر میتونید مشاهد کنید :
قسمت دوم اموزش ربات :
اگر نظری انتقادی پیشنهادی چیزی داشتید میتونید کامنت بزارید✍️