قسمت اول

بسم الله الرحمن الرحیم

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

یه روز که منو همسرم تصمیم گرفتیم تا توی شبکه های اجتماعی محصولات شهرمون رو بفروشیم، اولش یه کانال درست کردیم و عکس محصولات رو با قیمتش میزاشتیم.

مشتریای عزیز به ایدی من یا خانمم پیام میدادن که از فلان چیز چند کیلو، از فلان چیز چند کلیو و ....

بعد از سفارش این قد بهمون پیام میدادن که توی لیست چت ها بعضی مشتری ها گم می شد و مجبور بودیم شماره تلفنشون رو بگیریم و همه سفارش ها رو روی یک کاغذ بنویسم و بعد شماره کارت بدیم و مشتری تا فردا پرداخت می کرد و عکس می فرستاد و اههههه! خیلی طول می کشید. حالا نوبت من بود چک کنم طرف درست پول واریز کرده یا نه و ....!

خیلی فرایند خِنِسی بود! دنبال یه راه حل دیگه بودم. فهمیده بودم میشه با پیام رسان بله کارت به کارت کرد. به بعضی از مشتری ها که بله داشتن پیشنهاد می دادم توی بله برام ارسال کنن تا، هم رسیدش برای من بیاد و مجبور نباشم تراکنشش رو چک کنم و سریع کارشو پیگیری کنم. تا این جا بخشی از مشتری ها کارشون سریع تر پیش میرفت. تا اینکه چند وقت دیدم در پیام رسان بله میشه یه قابلیت جدید به اسم « درخواست پول » هست. وقتی ازش استفاده کردم و حجم کاری که ازمون کم می کرد رو دیدم، عزمم رو جزم کردم تا کل فرایند ثبت سفارش رو ببریم توی پیام رسان بله.

اولش کانال رو اوردیم و بعدشم باتش رو زدیم و دیگه ما کاری با مشتری ها نداشیتم.

سفارششون رو توی بله با هر محصولی و هر مقداری که میخواستن ثبت میکردن، پرداخت می کردن، بعد از پرداخت موفق بهمون پیام میومد و سفارش رو پیگیری میکردیم و براش ارسال می کردیم.

بهتون حق میدم که شاید در دفعه اول خیلی ها از سفارش صرف نظر می کردن، ولی بعد از مدتی مشتری ها مون خداروشکر زیاد شد و الان میخوام این تجربه رو باهاتون به اشتراک بزارم و بتونید به سادگی فروشگاه خودکار خودتون رو توی بله راه اندازی کنین.

تمامی اموزش هامو سعی میکنم از سایت توسعه دهندگان بله به ادرس زیر پیش ببرم :

https://developers.bale.ai/

همون طور که میدونید مراجع رسمی اصلا اطلاعات درست درمونی نمیدن و باید از این طرف اون طرف مطالب رو گیر بیارین و توسعه بدین. پس منم همین نقشو میخوام اینجا براتون بازی کنم ان شاءالله.

اول به ایدی زیر در پیام رسان بله برید:

botfather@

بعد شروع کار با این بازو یک بات برای خودتون بسازید و توکنش(token) رو یه جایی توی فضای شخصی تون یادداشت کنین. این نکته رو هم بگم که این توکن رو به هیچ کس ندین! چون این توکن دست هر کسی باشه میتونه کنترل بازوی شما رو به دست بگیره. پس مث چیز ازش محافظت کنین.

بعد از اینکه بازو رو ساختین باید محیط توسعه خودتون رو درست کنین. البته هیچ اجباری روی این توصیه من نیست و لی من پیشنهادم اینه که از pycharm استفاده کنین. چون sdk بازوی بله رو با پایتون نوشتن باید از زبان برنامه نویسی پایتون برای این کار استفاده کنین.

خب میتونید پای چارم رو از لینک زیر دانلود کنین: دانلود

بعد از نصب پای چارم باید پایتون ۳.۵ به بالا رو روی سیستمتون نصب کنین. برای این کار سرچ کنین ساده اس. اموزش نصب پایتون

بعد از نصب پایتون باید pip3 رو نصب کنین : اموزش نصب پایپ۳

حالا که پایپ۳ رو نصب کردین، باید کتابخانه بله بات رو نصب کنین:

pip3 install balebot

حالا برید توی پای چارم و یک پروژه جدید بسازید و این قطعه کد رو از اینجا بردارید و توی یک فایل بریزید و مقدار TOKEN رو با توکنی که از بات فادر بله برای بازوی جدیدتون دریافت کردین جایگزین کنین:

"""Simple Bot to Reply to Bale messages.""" import asyncio from balebot.updater import Updater # Bale Bot Authorization Token updater = Updater(token="YOUR TOKEN", loop=asyncio.get_event_loop()) # Define dispatcher dispatcher = updater.dispatcher """ Your Code Comes here ... """ updater.run()

حالا این کد رو اجرا کنین:

اگر کار با موفقیت انجام شده باشه به سرور بله وصل شدین و این خروجی رو میبیند:

2018-05-12 11:31:52,669 network.py:32 DEBUG: "connect: wss://api.bale.ai/v1/bots/TOKEN"

اگر مشکلی پیش اومد:

2018-05-12 11:36:09,011 network.py:112 WARNING: "network connection disconnected." 2018-05-12 11:36:09,012 network.py:36 ERROR: "connect error: 500, message='Invalid response status'" Traceback (most recent call last): File "/home/ehsan/PycharmProjects/example_bots/venv/lib/python3.5/site-packages/balebot/connection/network.py", line 31, in connect self._ws = await self._session.ws_connect(self.construct_url()) File "/home/ehsan/PycharmProjects/example_bots/venv/lib/python3.5/site-packages/aiohttp/helpers.py", line 109, in __await__ ret = yield from self._coro File "/home/ehsan/PycharmProjects/example_bots/venv/lib/python3.5/site-packages/aiohttp/client.py", line 465, in _ws_connect headers=resp.headers) aiohttp.client_exceptions.WSServerHandshakeError: 500, message='Invalid response status'

این قسمت اول بود که با ساخت بازو و ارتباطش با سرور بله رو با هم یاد گرفتیم.

 قسمت دوم

توی این قسمت میخوایم در مورد نحوه ارتباط با کاربر در بازوی بله صحبت کنیم.

خب شما موفق شدین در قسمت قبل بازوی خودتون رو بسازید و به سرور بله متصل بشید.

الان وقتشه با بازوی خودتون ارتباط برقرار کنین و پیام های مورد نظرتون مثل :

  1. متن
  2. تصویر
  3. صوت
  4. فیلم
  5. سند
  6. درخواست پول
  7. ...

رو هم براش بفرستید و هم ازش بگیرید.

در مورد اینکه چگونه بازو نسبت به این پیام ها حساسیت نشون میده و گوش میده به حرف های شما هم بحث خواهیم کرد.

در مثال اول فرض کنید میخوایم بازو هر چیزی رو که براش میفرستیم و رو صرفا برامون بازگو یا echo کنه.

چیکار کنیم؟

بازوی بله میتونه برای هر پیامی که دریافت میکنه، قسمت پردازشی متفاوتی داشته باشه، مثلا فرض کنین یه بازوی هوشمند دارید که بهش میگید برو سوسیس تخمرغ درست کن و اونم بعد از آماده شدن صداتون میکنه که بیا بزن بر بدن! ( آرزو بر جوانان عیب نیست).

بازوی بالا همیشه در حال شنیدن حرف های شما هست و اگر در قبال حرفی که میزنید، رفتاری رو در نظر داشته باشه، شروع به انجام کار میکنه.

بازوی بله هم چنین چیزی هست. اول که بهش میگید سلام! میتونه جواب سلام شما رو بده!

بهش بگید گزارش فلان روز رو بهم بده، در صورتی که از قبل نسبت به شنیدن این فرمان برنامه ریزی شده باشه، گزارش رو در قالب یک سند براتون ارسال میکنه.

اگر بهش بگید قیمت همه اجناس داخل سبد خرید رو جمع بزن و کد تخفیف رو بگیر و نسبت به خرید های مشتری و تعداد خرید های موفقی که داشته و درجه رطوبت هوا و بقیه عوامل، درخواست پول بفرست، همه این کار ها رو میکنه و براتون درخواست پول رو میفرسته! اگر پرداختتون صحیح بود بقیه کارهایی که بهش فکر میکنید رو براتون انجام میده! دیدم که میگم! :)

خب الان فهمیدیم که باید برای هر دستور، فرمان، درخواست، بیگاری، تقاضا و... هر چیزی باید برنامه ریزی بشه تا بتونه از شما فرمانبری کنه. پس اگر بازوی حرف گوش کنی میخواید باید اول خوب تربیتش کنین و ازش انتظار بی جا نداشته باشین.

برای اینکه بازو نسبت به یک پیام حساس بشه و در قبال شنیدن چنین پیامی کار یا مجموعه ای از کار ها رو انجام بده باید از handler ها استفاده کنیم.

نکته : الان خیلی به معماری بله کاری نداریم. فعلا کار شما رو برای راه اندازی یک فروشگاه دم دست راه میندازیم ان شاءالله و اگر دوست داشتین میتونیم در قسمت های اخر به معماری داخلی هم بپردازیم.

توی کدی که توی پست قبلی گذاشتم شما یک dispatcher دارید. این دیسپچر پیام ها رو میگیره اگر متناسب با پیام تابعی رو نوشته باشید کار رو شروع میکنه و پیام بعدی رو میگیره و.... یه جورایی گوش بازو هست. که میتونید برای هر پیامی کاری مشخص انجام بدین!

خب اولین مثالش رو اینجوری بالا گفتیم که هر چی بشنوه رو تکرار یا بازگو یا echo کنه:

dispatcher = updater.dispatcher

که ایشون از updater پیام ها رو میگیره.

میتونه روی هر پیام هندلری رو پیاده سازی کنه.

مثلا میخوایم بهش بگیم آقا هر چی شنیدی همونو بگو. برای این کار میتونیم یک message_handler بهش اضافه کنیم. علاوه بر این میتونید command_handler هم بهش اضافه کنین که در ادامه بهش میپردازیم.

یه نکته کوچیک که بعدا بازش میکنم ان شاءالله: message های مختلفی توی بله داریم. مثل متن و عکس و سند و درخواست پول و موقعیت و ... که میتونیم برای هر کدوم هندلرش رو بزاریم و باهاشون کار کنیم.

خب حالا بهش میگیم هر چی شنیدی، تابع پایینی رو اجرا کنه و اطلاعاتت رو بهش بفرست :

@dispatcher.message_handler(filters=DefaultFilter()) def echo(bot, update): message = TextMessage('*Hello*') # Send a message to client bot.reply(update, message, success_callback=success, failure_callback=failure)

خب در بالا فیلترش رو روی پیش فرض گذاشتیم. به صورتی که اگر هندلری برای پیام نداشت، از این هندلر استفاده میکنه.

توابعی که بعد از دیسپچر هست دوتا ورودی bot و update میگیرن که حاوی کلی اطلاعات هست که بعدا خیلی باهاش کار داریم ان شاءالله.

با این کار هر چیزی که به بازو بفرستید این تابع echo روش اجرا میشه.

نمونه های دیگه ای از هندلر ها رو میتونید در لینک های زیر ببینید :

لینک نمونه

@dispatcher.command_handler("start") def handle_start(bot, update): """ Some Code here """

که در صورتی که دستور start/ رو بزنین کاری رو که در تابع handle_start رو انجام میده.

یه مثال دیگه از کامند هندلر:

@dispatcher.command_handler(["/Register"])

اینم یه نمونه پیشرفته از هندلر هاست که وقتی انواع پیام رو بهتون بگم میتونید ازشون استفاده کنین و منو برای هر مرحله بزارید.

@dispatcher.message_handler(filters=TemplateResponseFilter(keywords="Newrequest"))

خب در این قسمت فهمیدیم چجوری برای بازو گوش درست کنیم که به حرفمون گوش بده.

سوالی بود در خدمتم.

ان شاءالله در مرحله بعد و پست بعدی با هم نحوه ایجاد یک گفتگو رو خواهیم داشت که چجوری بازو سلسله ای پیام ها رو گوش بده و کاری رو برامون انجام بده.

اینم کد کلی برای اجرا: لینک

"""Simple Bot to Reply to Bale messages.""" import asyncio from balebot.filters import DefaultFilter from balebot.models.messages import TextMessage from balebot.updater import Updater # Bale Bot Authorization Token updater = Updater(token="PUT YOUR TOKEN HERE", loop=asyncio.get_event_loop()) # Define dispatcher dispatcher = updater.dispatcher # Both of success and failure functions are optional def success(response, user_data): print("success : ", response) print(user_data) def failure(response, user_data): print("failure : ", response) print(user_data) @dispatcher.message_handler(filters=DefaultFilter()) def echo(bot, update): message = TextMessage('*Hello*') # Send a message to client bot.reply(update, message, success_callback=success, failure_callback=failure) # Run the bot! updater.run()

قسمت سوم

در قسمت دوم یه قول داده بودم که در رابطه ایجاد یک گفتگو با هم بحث کنیم.

الان که بیشتر فکر کردم، فهمیدم که قبلش باید یه سری جزییاتی رو باهم یاد بگیریم تا بتونیم یک محاوره یا گفتگو ی با کیفیت رو بسازیم.

در قسمت های قبلی تونستیم یه گوش برای بازو بسازیم که به یک پیام خاص، کامند یا دستور خاص و یا به همه پیام ها گوش بده و مطابق با اون پیام کاری رو شروع کنه.

حالا از این به بعد کار رو باید با جدیت بیشتری پیگیری کینم. چرا؟ چون مدیریت گفتگو ها رو از قبل باید پیش بینی کنید و به صورتی یک گفتگو رو برنامه ریزی و سناریو نویسی کنین که دوتا گفتگو با هم قاطی نشن و کاربر با هر کاری فقط وارد یک بخش خاصی از بازو بشه! منظورم اینه که اگر یه پیام داد، دو تا کار توی بازو برای یک پیام تعریف نشده باشن! این یه تجربه خیلی سختی بود که بعد از مدت ها بهش رسیدم. پس وارث خوبی باشین :)

یک مثال بزنم:

مرحله اول: کاربر دستور « من قهوه لاته میخوام » رو برای بازو ارسال میکنه.

به چند طریق میتونید این کار رو انجام بدین:

۱- استفاده از یک کامند خاص مثلا : get_latte_coffee/

۲- استفاده از دکمه هایی که بازوی بله در اختیارمون میزاره: این موارد رو در قالب پیام های template_message باید بسازیم و روش کار کنیم که بهش مفصل میپردازیم ان شاءالله

۳- ارسال یک پیام متنی که شامل کلید واژه های «قهوه» یا «لاته» که این مورد اخر یکم پیچیده میشه و توصیه میکنم از این روش استفاده نکنین - راه های ۱ و ۲ به صورت کامل نیاز های شماره رو براورده می کنن.

مرحله ۲: اگر موارد دیگه ای برای قهوه مد نظر تون بود رو میتونید در مراحل بعدی از کاربر بگیرید. فرض کنید کامند get_latte_coffee/ رو زده و شما برای این کامند از طریق dispatcher یک کامند هندلر گذاشتی( ارجاع به قسمت دوم اموزش). در این مرحله بازو برای تهیه یک قهوه آماده میشه و اگر سوال دیگه ای داشته باشه رو از کاربر میپرسه! میپرسه؟ چجوری میپرسه؟

اینجاست که باید با یک تعریف دیگه ای در بازو اشنا بشیم به اسم next_step!
یعنی اینکه بعد از شنیدن یک دستور خاص وارد یک تابع خاص میشیم و از اون به بعد محدوده شنیداری بازو رو باید به صورتی تعیین کنیم که به پیام های خاص دیگه ای گوش بده و اگر توی next_step هاش بود، کاری رو انجام بده! همین روال رو تا پایان گفتگو باید انجام بدین.

مثال مرحله ۲: آیا قهوه خود را با عسل نوش جان می نمایید یا با شهد خرما؟

اینجا باید از template_message استفاده کنیم. که دوتا دکمه داره! دکمه عسل و دکمه شهد خرما

تمپلیت مسیج دارای یک متن هست و یه سری دکمه. متنش رو باید از نوع TextMessage بسازید و دکمه هاش رو اینجوری:

TemplateMessageButton(text="عسل", value="عسل", action=0)

این دکمه همراه پیام میاد. دکمه ها رو باید به صورت لیستی از دکمه ها به بازو بدین.

در کد زیر نمونه ای لیست رو میبنید:

btn = [ TemplateMessageButton(text="عسل", value="عسل", action=0), TemplateMessageButton(text="شهد خرما", value="شهد خرما", action=0) ]

و حالا ساخت یک پیام تمپلیت مسیج:

text_message = TextMessage("قهوه شما دارای چه افزودنی باشد سرورم؟") btn = [ TemplateMessageButton(text="عسل", value="عسل", action=0), TemplateMessageButton(text="شهد خرما", value="شهد خرما", action=0) ] template_message = TemplateMessage(general_message=text_message, btn_list=btn)

که text چیزی هست که به کاربر در پیام نشون میدیم. مث چیزی که تصویر زیر نشون میده.

و value مقداری هست که هنگام فشردن دکمه برای بازو ارسال میشه.

پارامتر action هم فعلا نیاز به توضیح نداره.

اینم پیام ارسالی که کاربر در بازو خواهد دید:

حالا شما میتونید بقیه گفتگو رو اینجوری جلو ببرید. ولی مث اینکه هنوز زنجیره گفتگو کامل نشده و ما نمیتونیم با اطلاعات فعلی مراحل رو به هم وصل کنیم.

در اینجا باید از dispatcher استفاده کنیم و محدوده شنوایی که بالا بهش اشاره کردم رو برای ادامه گفتگو تعبیه کنیم.

فرض کنید میخوایم یک تابع بنویسیم که اضافه کردن عسل رو به عهده داشته باشه و یک تابع دیگه اضافه کردن شهد خرما.

پس برای هر دکمه باید تابع جداگانه بنویسید و پردازشش رو به اون تابع محول کنین.

خب سوالی که پیش میاد اینه که چجوری این زنجیره گفتگو رو به هم وصل کنیم؟

اینجوری:

با استفاده از تابع register_conversation_next_step_handler که یکی از توابع دیسپچر هست. این تابع دوتا پارامتر میگیره. یکی update هست و دیگری لیستی از هندلر ها یا مراحل بعدی که بازو توی این مرحله می شنوه و بهشون عمل میکنه
بدین گونه:

dispatcher.register_conversation_next_step_handler(update, [ MessageHandler(TemplateResponseFilter(keywords="عسل"), add_assal), MessageHandler(TemplateResponseFilter(keywords="شهد خرما"), add_shahd_khorma), ])

هندلر های متفاوتی داشتیم! یادتونه؟ مسیج هندلر و کامند هندلر.

اینجا هم روی مسیج ها هندلر میزاریم و از مسیج هندلر میسازیم.

مسیج هندلر که در بالا لیستی از اون ها رو میبیند دارای ۲ پارامتر هست. یکی نوع پیامی که باید بهش گوش بده و دیگری تابعی هست که بعد از شنیدن پیام مورد نظر باید بهش هدایت کنه.

در اینجا اگر کاربر عسل رو بزنه به که عسل یک جواب تمپلیت مسیج هست، به تابع add_assal میره و اگر شهد خرما رو بزنه به تابع add_shahd_khorma میره.

اینم از نمونه کار بازو تا اینجا:

اینم کد کلی بازو تا اینجا:

"""Simple Bot to Reply to Bale messages.""" import asyncio from balebot.filters import DefaultFilter, TemplateResponseFilter from balebot.handlers import MessageHandler from balebot.models.messages import TextMessage, TemplateMessageButton, TemplateMessage from balebot.updater import Updater # Bale Bot Authorization Token updater = Updater(token="توکن بازوی خود را در اینجا بگذارید.", loop=asyncio.get_event_loop()) # Define dispatcher dispatcher = updater.dispatcher # Both of success and failure functions are optional def success(response, user_data): print("success : ", response) print(user_data) def failure(response, user_data): print("failure : ", response) print(user_data) @dispatcher.command_handler(["get_latte_coffee"]) def coffee_request_starter(bot, update): user = update.get_effective_user() text_message = TextMessage("قهوه شما دارای چه افزودنی باشد سرورم؟") btn = [ TemplateMessageButton(text="عسل", value="عسل", action=0), TemplateMessageButton(text="شهد خرما", value="شهد خرما", action=0) ] template_message = TemplateMessage(general_message=text_message, btn_list=btn) bot.send_message(template_message, user,success_callback=success, failure_callback=failure) dispatcher.register_conversation_next_step_handler(update, [ MessageHandler(TemplateResponseFilter(keywords="عسل"), add_assal), MessageHandler(TemplateResponseFilter(keywords="شهد خرما"), add_shahd_khorma), ]) def add_assal(bot, update): text_msg = TextMessage("عسل به قهوه حضرت والا اضافه گردید.") bot.send_message(text_msg, update.get_effective_user(), success_callback=success, failure_callback=failure) dispatcher.finish_conversation(update) def add_shahd_khorma(bot, update): text_msg = TextMessage("شهد توت به قهوه حضرت والا اضافه گردید.") bot.send_message(text_msg, update.get_effective_user(), success_callback=success, failure_callback=failure) dispatcher.finish_conversation(update) # Run the bot! updater.run()

قسمت چهارم

در قسمت های قبلی سعی شد روال ایجاد یک گفتگو رو با هم ببینیم و توی این قسمت میخوایم سعی کنیم از مقادیر دکمه ها استفاده کنیم.

در مثال قبلی وقتی در سفارش قهوه، افزودن عسل رو می زد، به یک تابع فرستاده می شود. حالا با این اوصاف میخوایم سفارش رو ثبت کنیم و درخواست پولی رو به مشتری بفرستیم و بعد از پرداخت، اگر پرداخت صحیح بود، بات به یکی از گارسن ها پیام بده که مشتری عزیز قهوه با چنین مشخصاتی رو درخواست داده براش ببرین. ( این پیام در صورتی هست که پرداخت با موفق انجام شده باشه.)

خب، بعد از انتخاب عسل باید یک درخواست پول با تصویر یک قهوه عسلی برای کاربر بفرستیم و قیمتش رو هم تعیین کنیم. پس دست به کار خواهیم شد:

خب، احتمالا درخواست پول های پیام رسان بله رو دیدین:

قهو عسلی
قهو عسلی

همون طور که میبینید، این پیام یک عکس وزین همراه با توضیحات و قیمت داره که در ادامه میخوایم همه رو اینا رو سر هم کنیم تا یه درخواست پول رو بسازیم:

purchase_message = PurchaseMessage(msg=photo_message, account_number="6037991889250159", amount=amount, money_request_type=normal)

پیام درخواست پول یک پیام تصویری، شماره کارت، قیمت، و نوع میخواد که اول از همه باید پیام تصویری اش رو بسازیم:

اون متن توضیح ( قهوه عسلی) یک پیام متنی هست که در پیام تصویری باید بهش بدیم:

v_message = PhotoMessage(file_id=file_id, access_hash=access_hash, name="Bale", file_size=file_size, mime_type="image/jpeg", caption_text=TextMessage(text="قهوه عسلی"), file_storage_version=1, thumb=thumb)

برای ساخت پیام تصویری نیاز داریم یک عکس رو از روی سرور ها بله ادرس دهی کنیم تا برای کاربر ارسال بشه. برای اینکه اطلاعات یک عکس رو از سرور بله دریافت کنین یک عکس برای بات بفرستید و در لاگی که براتون میندازه میتونید تمامی اطلاعاتش رو ببینید:

"[transport] receiving : WSMessage(type=<WSMsgType.TEXT: 1>, data='{"$type":"FatSeqUpdate","seq":150,"body":{"$type":"Message","peer":{"$type":"User","id":463989315,"accessHash":"7224971076189921109"},"sender":{"$type":"User","id":463989315,"accessHash":"7224971076189921109"},"date":"1550752496695","randomId":"4257268464820720381","message":{"$type":"Document","fileId":"5774371186290462464","accessHash":"463989315","fileSize":"369438","name":"latte-xxlarge.jpg","mimeType":"image/jpeg","thumb":{"width":90,"height":56,"thumb":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA4KCw0LCQ4NDA0QDw4RFiQXFhQUFiwgIRokNC43NjMuMjI6QVNGOj1OPjIySGJJTlZYXV5dOEVmbWVabFNbXVn/2wBDAQ8QEBYTFioXFypZOzI7WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVn/wAARCAA4AFoDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAABAUAAgMGAf/EADcQAAEDAgQDBQUGBwAAAAAAAAEAAgMEEQUSITETQVEGFDJh0SIjQoGxcXORk6HBJTRDUmJy8f/EABgBAAMBAQAAAAAAAAAAAAAAAAECAwAE/8QAHREAAwADAQEBAQAAAAAAAAAAAAECAxEhEjEiMv/aAAwDAQACEQMRAD8AfhwuraHQICOUm3REsebqI2ja4BsdbqwZfYBUHtPAF7lbZc+gNmDc9UyWwN6Mi5rTYAvPkP3QlVXS08rGCiLy7oCbJVifaCQyupsLaAG6GUj6JUW4hMc8lZMXH/MotzI84rrp1sNS2obZ0L4yN7ehRBjGQlpzNXI02I4nQvB4pnjG7X6rrMNrIcRg4sIyPGj2Hkt+a+AqKj6ZPYDrf5LBzOWYomqj4ZzAWaf0QT5Bmtf9VNmXSj4svxuv9qOivwme2fCOaXZy4nUBMYr8Jm3hHJBGYvheSfL7UdFm/wClK6cbWAt0IRkdyDfQFEwzhBs489kLj0j4cMEMJtJO7JfoOaKoGe7N98yzxuEvFO8C4Y5O35jYJW7SYoo8Op4YBGGku5usrR4dPM5zYmXDTum+GNaW+0OeqbMhY3wtFjquSJd9OqsvjhycmETMYXyNuBvY6he4Uzulc0t8L9CujrHiJpv0SmlhD3sJGxug9xSSCr9w9jGsjz07wN7XCQudYEkFbxdoIjWT0tTaMgkMcdig45C+Lc/iuzIjjgmfXd3zCPid7pmnwhLHOcGn2vndHwvdwY/aPhH0U0OwWN2XZw/EIpsmmw080MxwaSLgHzJKuJbHVwP4+qIBlh9R74seRZ226OrpIBEGSO8Rtouee9uUkOs47Wv6qlPL3q8cbjxB4sxu4qk6fGJW11DZokpH5hqw8+qLbiLcu2vkUpNTUUEdgwSs5scsT2jom341BK13lYhQeC5f4fCqyzX9IazvNY4ZR8lazaduQkGV3LoFz1R2te4cOgoxFf436kfJTDqlzA+oq5dd3OcU+PA0/VfRbyc8ye9qMPo2UDqlxLJrgMtzKTYNiTy/us+p+EqYtXPxmqGUOFPHowdfNXw+nkhN8rr9dFW2vgsp6GwsbjS6ZRRDhM28ISzMGeMub/sB6JlEW8FmrfCOQUkMwR1FWNbmbQTud5xOP7K7KWvyh3c5w7pwiFFE3kGz19LXOP8AK1Nvu3eiX1GG4jn4kVNWNeNQRE70UURSMbRVeMNGSswermH97IXX+itIzii5wnEmnp3V/oooqpiOUAyRVMV+74HiDz1dTuA+iXVGH45WO97h9a1g2YIHgfRRRZsKSCKfBsSZb+HVYH3bvRGxYdiDHX7lV/lO9FFFJrY+wp1LiDmWNFVfklMIqWrELAaWYENH9IqKIJG2f//Z"},"ext":{"$type":"Photo","width":1500,"height":938},"caption":{"$type":"Text","text":""},"checkSum":"checksum","algorithm":"algorithm","fileStorageVersion":1}},"users":[[463989315,{"id":463989315,"accessHash":"7224971076189921109","name":"Amirio","sex":1,"about":"موجیم که آسودگی ما عدم ماست...\\nDeveloper @ Bale","avatar":{"smallImage":{"fileLocation":{"fileId":"-2408282308550062334","accessHash":"463989315","fileStorageVersion":1},"width":100,"height":100,"fileSize":3480},"largeImage":{"fileLocation":{"fileId":"-8461560012386398719","accessHash":"463989315","fileStorageVersion":1},"width":200,"height":200,"fileSize":7942},"fullImage":{"fileLocation":{"fileId":"7223562696070663683","accessHash":"463989315","fileStorageVersion":1},"width":970,"height":970,"fileSize":117086}},"username":"Amirio","isBot":false,"contactRecords":[],"timeZone":"Asia/Tehran","preferredLanguages":["fa-IR","fa"],"botCommands":[]}]],"groups":[]}', extra='')"

حالا هر اطلاعاتی از قبیل

file_id

access_hash,

name,

file_size,

mime_type,

thumb

رو از قست Document که در قطعه لاگ بالا هست رو بردارید و پیام تصویری خودتون رو بسازید.

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

p_message = PhotoMessage(file_id="5774371186290462464", access_hash="463989315", name="name", file_size="369438", mime_type="image/jpeg", caption_text=TextMessage( text="قهوه عسلی مخصوص عمو حسن با گوشت گوسفندی"), file_storage_version=1, thumb="/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA4KCw0LCQ4NDA0QDw4RFiQXFhQUFiwgIRokNC43NjMuMjI6QVNGOj1OPjIySGJJTlZYXV5dOEVmbWVabFNbXVn/2wBDAQ8QEBYTFioXFypZOzI7WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVn/wAARCAA4AFoDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAABAUAAgMGAf/EADcQAAEDAgQDBQUGBwAAAAAAAAEAAgMEEQUSITETQVEGFDJh0SIjQoGxcXORk6HBJTRDUmJy8f/EABgBAAMBAQAAAAAAAAAAAAAAAAECAwAE/8QAHREAAwADAQEBAQAAAAAAAAAAAAECAxEhEjEiMv/aAAwDAQACEQMRAD8AfhwuraHQICOUm3REsebqI2ja4BsdbqwZfYBUHtPAF7lbZc+gNmDc9UyWwN6Mi5rTYAvPkP3QlVXS08rGCiLy7oCbJVifaCQyupsLaAG6GUj6JUW4hMc8lZMXH/MotzI84rrp1sNS2obZ0L4yN7ehRBjGQlpzNXI02I4nQvB4pnjG7X6rrMNrIcRg4sIyPGj2Hkt+a+AqKj6ZPYDrf5LBzOWYomqj4ZzAWaf0QT5Bmtf9VNmXSj4svxuv9qOivwme2fCOaXZy4nUBMYr8Jm3hHJBGYvheSfL7UdFm/wClK6cbWAt0IRkdyDfQFEwzhBs489kLj0j4cMEMJtJO7JfoOaKoGe7N98yzxuEvFO8C4Y5O35jYJW7SYoo8Op4YBGGku5usrR4dPM5zYmXDTum+GNaW+0OeqbMhY3wtFjquSJd9OqsvjhycmETMYXyNuBvY6he4Uzulc0t8L9CujrHiJpv0SmlhD3sJGxug9xSSCr9w9jGsjz07wN7XCQudYEkFbxdoIjWT0tTaMgkMcdig45C+Lc/iuzIjjgmfXd3zCPid7pmnwhLHOcGn2vndHwvdwY/aPhH0U0OwWN2XZw/EIpsmmw080MxwaSLgHzJKuJbHVwP4+qIBlh9R74seRZ226OrpIBEGSO8Rtouee9uUkOs47Wv6qlPL3q8cbjxB4sxu4qk6fGJW11DZokpH5hqw8+qLbiLcu2vkUpNTUUEdgwSs5scsT2jom341BK13lYhQeC5f4fCqyzX9IazvNY4ZR8lazaduQkGV3LoFz1R2te4cOgoxFf436kfJTDqlzA+oq5dd3OcU+PA0/VfRbyc8ye9qMPo2UDqlxLJrgMtzKTYNiTy/us+p+EqYtXPxmqGUOFPHowdfNXw+nkhN8rr9dFW2vgsp6GwsbjS6ZRRDhM28ISzMGeMub/sB6JlEW8FmrfCOQUkMwR1FWNbmbQTud5xOP7K7KWvyh3c5w7pwiFFE3kGz19LXOP8AK1Nvu3eiX1GG4jn4kVNWNeNQRE70UURSMbRVeMNGSswermH97IXX+itIzii5wnEmnp3V/oooqpiOUAyRVMV+74HiDz1dTuA+iXVGH45WO97h9a1g2YIHgfRRRZsKSCKfBsSZb+HVYH3bvRGxYdiDHX7lV/lO9FFFJrY+wp1LiDmWNFVfklMIqWrELAaWYENH9IqKIJG2f//Z" )

حالا این پیام تصویری رو با یک پیام درخواست پول ترکیب میکنیم و برای کاربر میفرستیم و منتظر میمونمی تا پرداخت کنه.

به این صورت:

purchase_message = PurchaseMessage(msg=p_message, account_number="6037991889250159", amount="100000", money_request_type=MoneyRequestType.normal) bot.send_message(purchase_message, update.get_effective_user(), success_callback=success, failure_callback=failure)

که در اینجا شماره کارت و مقدار پول و نوع درخواست پول که normal هست رو میزاریم.

یک هندلر هم اضافه میکنیم که اگر پرداختش از سمت سرور بله تایید شه بره مرحله بعد:

به این صورت.

اینم کد کلی :

"""Simple Bot to Reply to Bale messages.""" import asyncio from balebot.filters import DefaultFilter, TemplateResponseFilter, BankMessageFilter from balebot.handlers import MessageHandler from balebot.models.messages import TextMessage, TemplateMessageButton, TemplateMessage, PhotoMessage, PurchaseMessage from balebot.models.messages.banking.money_request_type import MoneyRequestType from balebot.updater import Updater # Bale Bot Authorization Token updater = Updater(token="token", loop=asyncio.get_event_loop()) # Define dispatcher dispatcher = updater.dispatcher # Both of success and failure functions are optional def success(response, user_data): print("success : ", response) print(user_data) def failure(response, user_data): print("failure : ", response) print(user_data) # # @dispatcher.message_handler(filters=DefaultFilter()) # def echo(bot, update): # message = TextMessage('*Hello*') # # Send a message to client # bot.reply(update, message, success_callback=success, failure_callback=failure) # @dispatcher.command_handler(["get_latte_coffee"]) def coffee_request_starter(bot, update): user = update.get_effective_user() text_message = TextMessage("قهوه شما دارای چه افزودنی باشد سرورم؟") btn = [ TemplateMessageButton(text="عسل", value="عسل", action=0), TemplateMessageButton(text="شهد خرما", value="شهد خرما", action=0) ] template_message = TemplateMessage(general_message=text_message, btn_list=btn) bot.send_message(template_message, user,success_callback=success, failure_callback=failure) dispatcher.register_conversation_next_step_handler(update, [ MessageHandler(TemplateResponseFilter(keywords="عسل"), add_assal), MessageHandler(TemplateResponseFilter(keywords="شهد خرما"), add_shahd_khorma), ]) def add_assal(bot, update): p_message = PhotoMessage(file_id="5774371186290462464", access_hash="463989315", name="name", file_size="369438", mime_type="image/jpeg", caption_text=TextMessage( text="قهوه عسلی مخصوص عمو حسن با گوشت گوسفندی"), file_storage_version=1, thumb="/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA4KCw0LCQ4NDA0QDw4RFiQXFhQUFiwgIRokNC43NjMuMjI6QVNGOj1OPjIySGJJTlZYXV5dOEVmbWVabFNbXVn/2wBDAQ8QEBYTFioXFypZOzI7WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVn/wAARCAA4AFoDASIAAhEBAxEB/8QAGgAAAgMBAQAAAAAAAAAAAAAABAUAAgMGAf/EADcQAAEDAgQDBQUGBwAAAAAAAAEAAgMEEQUSITETQVEGFDJh0SIjQoGxcXORk6HBJTRDUmJy8f/EABgBAAMBAQAAAAAAAAAAAAAAAAECAwAE/8QAHREAAwADAQEBAQAAAAAAAAAAAAECAxEhEjEiMv/aAAwDAQACEQMRAD8AfhwuraHQICOUm3REsebqI2ja4BsdbqwZfYBUHtPAF7lbZc+gNmDc9UyWwN6Mi5rTYAvPkP3QlVXS08rGCiLy7oCbJVifaCQyupsLaAG6GUj6JUW4hMc8lZMXH/MotzI84rrp1sNS2obZ0L4yN7ehRBjGQlpzNXI02I4nQvB4pnjG7X6rrMNrIcRg4sIyPGj2Hkt+a+AqKj6ZPYDrf5LBzOWYomqj4ZzAWaf0QT5Bmtf9VNmXSj4svxuv9qOivwme2fCOaXZy4nUBMYr8Jm3hHJBGYvheSfL7UdFm/wClK6cbWAt0IRkdyDfQFEwzhBs489kLj0j4cMEMJtJO7JfoOaKoGe7N98yzxuEvFO8C4Y5O35jYJW7SYoo8Op4YBGGku5usrR4dPM5zYmXDTum+GNaW+0OeqbMhY3wtFjquSJd9OqsvjhycmETMYXyNuBvY6he4Uzulc0t8L9CujrHiJpv0SmlhD3sJGxug9xSSCr9w9jGsjz07wN7XCQudYEkFbxdoIjWT0tTaMgkMcdig45C+Lc/iuzIjjgmfXd3zCPid7pmnwhLHOcGn2vndHwvdwY/aPhH0U0OwWN2XZw/EIpsmmw080MxwaSLgHzJKuJbHVwP4+qIBlh9R74seRZ226OrpIBEGSO8Rtouee9uUkOs47Wv6qlPL3q8cbjxB4sxu4qk6fGJW11DZokpH5hqw8+qLbiLcu2vkUpNTUUEdgwSs5scsT2jom341BK13lYhQeC5f4fCqyzX9IazvNY4ZR8lazaduQkGV3LoFz1R2te4cOgoxFf436kfJTDqlzA+oq5dd3OcU+PA0/VfRbyc8ye9qMPo2UDqlxLJrgMtzKTYNiTy/us+p+EqYtXPxmqGUOFPHowdfNXw+nkhN8rr9dFW2vgsp6GwsbjS6ZRRDhM28ISzMGeMub/sB6JlEW8FmrfCOQUkMwR1FWNbmbQTud5xOP7K7KWvyh3c5w7pwiFFE3kGz19LXOP8AK1Nvu3eiX1GG4jn4kVNWNeNQRE70UURSMbRVeMNGSswermH97IXX+itIzii5wnEmnp3V/oooqpiOUAyRVMV+74HiDz1dTuA+iXVGH45WO97h9a1g2YIHgfRRRZsKSCKfBsSZb+HVYH3bvRGxYdiDHX7lV/lO9FFFJrY+wp1LiDmWNFVfklMIqWrELAaWYENH9IqKIJG2f//Z" ) purchase_message = PurchaseMessage(msg=p_message, account_number="693799746648000", amount="1", money_request_type=MoneyRequestType.normal) bot.send_message(purchase_message, update.get_effective_user(), success_callback=success, failure_callback=failure) dispatcher.register_conversation_next_step_handler(update, [MessageHandler(BankMessageFilter(), payment_done), MessageHandler(DefaultFilter(), coffee_request_starter)]) def payment_done(bot, update): text_msg = TextMessage("پرداخت شما مورد تایید قرار گرفت و به زودی قهوه به شما تحویل خواهد گردید.") bot.send_message(text_msg, update.get_effective_user(), success_callback=success, failure_callback=failure) dispatcher.finish_conversation(update) def add_shahd_khorma(bot, update): text_msg = TextMessage("شهد توت به قهوه حضرت والا اضافه گردید.") bot.send_message(text_msg, update.get_effective_user(), success_callback=success, failure_callback=failure) dispatcher.finish_conversation(update) # Run the bot! updater.run()

در مرحله ای که پردات با درستی تکمیل میشه باید به یکی از گارسون ها پیام بدیم که ان شاءالله در قسمت پنجم بهش میپردازیم.