Rubka 4.4.6__tar.gz → 4.4.19__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. rubka-4.4.19/PKG-INFO +1025 -0
  2. rubka-4.4.19/README.md +991 -0
  3. rubka-4.4.19/Rubka.egg-info/PKG-INFO +1025 -0
  4. rubka-4.4.19/Rubka.egg-info/requires.txt +4 -0
  5. rubka-4.4.19/rubka/adaptorrubka/network/socket.py +31 -0
  6. {rubka-4.4.6 → rubka-4.4.19}/rubka/api.py +181 -56
  7. {rubka-4.4.6 → rubka-4.4.19}/rubka/context.py +7 -1
  8. {rubka-4.4.6 → rubka-4.4.19}/setup.py +8 -4
  9. rubka-4.4.6/PKG-INFO +0 -315
  10. rubka-4.4.6/README.md +0 -284
  11. rubka-4.4.6/Rubka.egg-info/PKG-INFO +0 -315
  12. rubka-4.4.6/Rubka.egg-info/requires.txt +0 -1
  13. rubka-4.4.6/rubka/adaptorrubka/network/socket.py +0 -24
  14. {rubka-4.4.6 → rubka-4.4.19}/Rubka.egg-info/SOURCES.txt +0 -0
  15. {rubka-4.4.6 → rubka-4.4.19}/Rubka.egg-info/dependency_links.txt +0 -0
  16. {rubka-4.4.6 → rubka-4.4.19}/Rubka.egg-info/top_level.txt +0 -0
  17. {rubka-4.4.6 → rubka-4.4.19}/rubka/__init__.py +0 -0
  18. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/__init__.py +0 -0
  19. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/client/__init__.py +0 -0
  20. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/client/client.py +0 -0
  21. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/crypto/__init__.py +0 -0
  22. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/crypto/crypto.py +0 -0
  23. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/enums.py +0 -0
  24. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/exceptions.py +0 -0
  25. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/methods/__init__.py +0 -0
  26. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/methods/methods.py +0 -0
  27. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/network/__init__.py +0 -0
  28. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/network/helper.py +0 -0
  29. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/network/network.py +0 -0
  30. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/sessions/__init__.py +0 -0
  31. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/sessions/sessions.py +0 -0
  32. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/types/__init__.py +0 -0
  33. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/types/socket/__init__.py +0 -0
  34. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/types/socket/message.py +0 -0
  35. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/utils/__init__.py +0 -0
  36. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/utils/configs.py +0 -0
  37. {rubka-4.4.6 → rubka-4.4.19}/rubka/adaptorrubka/utils/utils.py +0 -0
  38. {rubka-4.4.6 → rubka-4.4.19}/rubka/button.py +0 -0
  39. {rubka-4.4.6 → rubka-4.4.19}/rubka/config.py +0 -0
  40. {rubka-4.4.6 → rubka-4.4.19}/rubka/decorators.py +0 -0
  41. {rubka-4.4.6 → rubka-4.4.19}/rubka/exceptions.py +0 -0
  42. {rubka-4.4.6 → rubka-4.4.19}/rubka/jobs.py +0 -0
  43. {rubka-4.4.6 → rubka-4.4.19}/rubka/keyboards.py +0 -0
  44. {rubka-4.4.6 → rubka-4.4.19}/rubka/keypad.py +0 -0
  45. {rubka-4.4.6 → rubka-4.4.19}/rubka/logger.py +0 -0
  46. {rubka-4.4.6 → rubka-4.4.19}/rubka/rubino.py +0 -0
  47. {rubka-4.4.6 → rubka-4.4.19}/rubka/utils.py +0 -0
  48. {rubka-4.4.6 → rubka-4.4.19}/setup.cfg +0 -0
rubka-4.4.19/PKG-INFO ADDED
@@ -0,0 +1,1025 @@
1
+ Metadata-Version: 2.4
2
+ Name: Rubka
3
+ Version: 4.4.19
4
+ Summary: A Python library for interacting with Rubika Bot API.
5
+ Home-page: https://github.com/Mahdy-Ahmadi/Rubka
6
+ Download-URL: https://github.com/Mahdy-Ahmadi/rubka/blob/main/project_library.zip
7
+ Author: Mahdi Ahmadi
8
+ Author-email: mahdiahmadi.1208@gmail.com
9
+ Maintainer: Mahdi Ahmadi
10
+ Maintainer-email: mahdiahmadi.1208@gmail.com
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Communications :: Chat
15
+ Classifier: Topic :: Software Development :: Libraries
16
+ Requires-Python: >=3.6
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: requests
19
+ Requires-Dist: Pillow
20
+ Requires-Dist: websocket-client
21
+ Requires-Dist: pycryptodome
22
+ Dynamic: author
23
+ Dynamic: author-email
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: download-url
28
+ Dynamic: home-page
29
+ Dynamic: maintainer
30
+ Dynamic: maintainer-email
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # 📚 Rubka Bot Python Library Documentation
36
+ # نمونه تنظیم وب‌هوک (Webhook) در کتابخونه rubla
37
+
38
+ برای مشاهده مستندات کامل و آخرین نسخه راهنما، لطفاً به آدرس زیر مراجعه کنید:
39
+ [github.com/Mahdy-Ahmadi](https://github.com/Mahdy-Ahmadi/rubka/blob/main/webhook.md))
40
+
41
+
42
+ ## 🧠 Introduction
43
+ `rubka` is a Python library to interact with the [Rubika Bot API](https://rubika.ir/). This library helps you create Telegram-like bots with support for messages, inline buttons, chat keypads, and callback handling.
44
+
45
+ ---
46
+
47
+ ## ⚙️ Installation
48
+
49
+ ```bash
50
+ pip install rubka
51
+ ```
52
+
53
+ If `importlib.metadata` is not available, it installs `importlib-metadata` automatically.
54
+
55
+ ---
56
+
57
+ ## 🚀 Getting Started
58
+
59
+ ```python
60
+ from rubka import Robot
61
+ from rubka.context import Message
62
+
63
+ bot = Robot(token="YOUR_TOKEN_HERE")
64
+
65
+ @bot.on_message(commands=["start"])
66
+ def start(bot: Robot, message: Message):
67
+ message.reply("سلام! خوش آمدید!")
68
+
69
+ bot.run()
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 📬 Handling Messages
75
+
76
+ You can handle incoming text messages using `@bot.on_message()`:
77
+
78
+ ```python
79
+ @bot.on_message(commands=["hello"])
80
+ def greet(bot: Robot, message: Message):
81
+ message.reply("سلام کاربر عزیز 👋")
82
+ ```
83
+
84
+ You can also add filters.
85
+
86
+ ---
87
+
88
+ ## 🎮 Handling Callback Buttons
89
+
90
+ ```python
91
+ from rubka.keypad import ChatKeypadBuilder
92
+
93
+ @bot.on_message(commands=["gender"])
94
+ def gender(bot: Robot, message: Message):
95
+ keypad = ChatKeypadBuilder().row(
96
+ ChatKeypadBuilder().button(id="male", text="👨 مرد"),
97
+ ChatKeypadBuilder().button(id="female", text="👩 زن")
98
+ ).build()
99
+ message.reply_keypad("جنسیت خود را انتخاب کنید:", keypad)
100
+
101
+ @bot.on_callback("male")
102
+ def on_male(bot: Robot, message: Message):
103
+ message.reply("شما مرد هستید")
104
+
105
+ @bot.on_callback("female")
106
+ def on_female(bot: Robot, message: Message):
107
+ message.reply("شما زن هستید")
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 🔘 Inline Button Builder
113
+
114
+ ```python
115
+ from rubka.button import InlineBuilder
116
+
117
+ builder = InlineBuilder().row(
118
+ InlineBuilder().button_simple(id="info", text="اطلاعات")
119
+ ).build()
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 🔄 Check if User Joined a Channel
125
+
126
+ ```python
127
+ channel_guid = "c0xABCDEF..."
128
+
129
+ @bot.on_message(commands=["check"])
130
+ def check(bot: Robot, message: Message):
131
+ if bot.check_join(channel_guid, message.chat_id):
132
+ message.reply("✅ شما عضو کانال هستید")
133
+ else:
134
+ message.reply("❌ لطفاً ابتدا در کانال عضو شوید")
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 💬 Utility Methods
140
+
141
+ | Method | Description |
142
+ |--------|-------------|
143
+ | `get_chat(chat_id)` | دریافت اطلاعات چت |
144
+ | `get_name(chat_id)` | دریافت نام کاربر |
145
+ | `get_username(chat_id)` | دریافت نام‌کاربری |
146
+ | `send_message(...)` | ارسال پیام متنی |
147
+ | `edit_message_text(...)` | ویرایش پیام |
148
+ | `delete_message(...)` | حذف پیام |
149
+ | `send_location(...)` | ارسال موقعیت مکانی |
150
+ | `send_poll(...)` | ارسال نظرسنجی |
151
+ | `send_contact(...)` | ارسال مخاطب |
152
+ | `forward_message(...)` | فوروارد پیام |
153
+
154
+ ---
155
+
156
+ ## 🎛 Inline Query Support
157
+
158
+ ```python
159
+ @bot.on_inline_query()
160
+ def inline(bot: Robot, message: InlineMessage):
161
+ message.answer("نتیجه اینلاین")
162
+ ```
163
+
164
+ ---
165
+
166
+ ## 🧱 Button Types
167
+
168
+ Supported inline button types include:
169
+
170
+ - `Simple`
171
+ - `Payment`
172
+ - `Calendar`
173
+ - `Location`
174
+ - `CameraImage`, `CameraVideo`
175
+ - `GalleryImage`, `GalleryVideo`
176
+ - `File`, `Audio`, `RecordAudio`
177
+ - `MyPhoneNumber`, `MyLocation`
178
+ - `Textbox`, `Barcode`, `Link`
179
+
180
+ See `InlineBuilder` for more.
181
+
182
+ ---
183
+
184
+ ## 🧩 Dynamic Chat Keypad
185
+
186
+ ```python
187
+ builder = ChatKeypadBuilder()
188
+ keypad = builder.row(
189
+ builder.button(id="play", text="🎮 بازی کن"),
190
+ builder.button(id="exit", text="❌ خروج")
191
+ ).build()
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 🧪 Set Commands
197
+
198
+ ```python
199
+ bot.set_commands([
200
+ {"command": "start", "description": "شروع"},
201
+ {"command": "help", "description": "راهنما"}
202
+ ])
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 🔄 Update Offset Automatically
208
+
209
+ Bot updates are handled using `get_updates()` and `offset_id` is managed internally.
210
+
211
+ ---
212
+
213
+ ## 🛠 Advanced Features
214
+
215
+ - `update_bot_endpoint()` – تنظیم webhook یا polling
216
+ - `remove_keypad()` – حذف صفحه‌کلید چت
217
+ - `edit_chat_keypad()` – ویرایش یا افزودن صفحه‌کلید چت
218
+
219
+ ---
220
+
221
+ # 📘 Rubka Bot Method Reference
222
+
223
+ مستندات مربوط به متدهای اصلی کلاس `Robot` در کتابخانه Rubka.
224
+
225
+ ---
226
+
227
+ ## ✅ پیام‌ها و هندلرها
228
+
229
+ ### `on_message(filters=None, commands=None)`
230
+ **توضیح:** ثبت هندلر برای پیام‌های ورودی.
231
+ - `filters`: تابع شرطی برای فیلتر پیام‌ها (اختیاری)
232
+ - `commands`: لیست دستورهایی که شروع با `/` هستند (اختیاری)
233
+
234
+ ### `on_callback(button_id=None)`
235
+ **توضیح:** ثبت هندلر برای دکمه‌های فشرده‌شده
236
+ - `button_id`: آیدی دکمه‌ای که باید هندل شود (اختیاری)
237
+
238
+ ### `on_inline_query()`
239
+ **توضیح:** ثبت هندلر برای پیام‌های اینلاین (inline query)
240
+
241
+ ---
242
+
243
+ ## 📨 ارسال پیام
244
+
245
+ ### `send_message(...)`
246
+ **توضیح:** ارسال پیام متنی به چت
247
+ - `chat_id`: آیدی چت مقصد *(str)* ✅
248
+ - `text`: محتوای پیام *(str)* ✅
249
+ - `chat_keypad`: کی‌پد معمولی *(dict)*
250
+ - `inline_keypad`: کی‌پد اینلاین *(dict)*
251
+ - `reply_to_message_id`: پاسخ به پیام خاص *(str)*
252
+ - `disable_notification`: بدون نوتیف *(bool)*
253
+ - `chat_keypad_type`: حالت کی‌پد *("New" | "Removed")*
254
+
255
+ ---
256
+
257
+ ## 📁 ارسال فایل‌ها
258
+
259
+ ### متدهای مشترک (فایل، موزیک، ویس، گیف، عکس):
260
+ - `send_document(...)`
261
+ - `send_music(...)`
262
+ - `send_voice(...)`
263
+ - `send_gif(...)`
264
+ - `send_image(...)`
265
+
266
+ **پارامترهای اصلی:**
267
+ - `chat_id`: آیدی چت
268
+ - `path`: مسیر فایل یا URL (اختیاری)
269
+ - `file_id`: اگر فایل قبلاً آپلود شده باشد
270
+ - `text`: کپشن فایل
271
+ - `file_name`: نام فایل
272
+ - `inline_keypad`, `chat_keypad`, `reply_to_message_id`, `disable_notification`, `chat_keypad_type`
273
+
274
+ ---
275
+
276
+ ## 📍 سایر متدهای مهم
277
+
278
+ ### `get_me()`
279
+ دریافت اطلاعات ربات
280
+
281
+ ### `get_chat(chat_id)`
282
+ دریافت اطلاعات یک چت
283
+
284
+ ### `get_name(chat_id)`
285
+ دریافت نام مخاطب بر اساس `first_name` و `last_name`
286
+
287
+ ### `get_username(chat_id)`
288
+ دریافت نام کاربری چت (در صورت وجود)
289
+
290
+ ### `check_join(channel_guid, chat_id)`
291
+ بررسی عضویت کاربر در کانال خاص
292
+
293
+ ### `remove_keypad(chat_id)`
294
+ حذف کی‌پد معمولی چت
295
+
296
+ ### `edit_chat_keypad(chat_id, chat_keypad)`
297
+ ویرایش یا اضافه کردن کی‌پد چت
298
+
299
+ ### `edit_message_text(chat_id, message_id, text)`
300
+ ویرایش متن پیام ارسال‌شده
301
+
302
+ ### `edit_inline_keypad(chat_id, message_id, inline_keypad)`
303
+ ویرایش کی‌پد اینلاین پیام
304
+
305
+ ### `delete_message(chat_id, message_id)`
306
+ حذف پیام از چت
307
+
308
+ ### `send_poll(chat_id, question, options)`
309
+ ارسال نظرسنجی به چت
310
+
311
+ ### `send_location(chat_id, latitude, longitude, ...)`
312
+ ارسال موقعیت مکانی به چت
313
+
314
+ ### `send_contact(chat_id, first_name, last_name, phone_number)`
315
+ ارسال مخاطب به چت
316
+
317
+ ### `forward_message(from_chat_id, message_id, to_chat_id)`
318
+ فروارد کردن پیام از یک چت به چت دیگر
319
+
320
+ ### `set_commands(bot_commands)`
321
+ تنظیم دستورات رسمی ربات (برای `/help` و ...)
322
+
323
+ ### `update_bot_endpoint(url, type)`
324
+ تنظیم وب‌هوک یا polling برای دریافت پیام‌ها
325
+
326
+ ---
327
+
328
+ ## 📦 مدیریت فایل و آپلود
329
+
330
+ ### `get_upload_url(media_type)`
331
+ دریافت آدرس آپلود فایل برای انواع مختلف: File, Image, Voice, Music, Gif
332
+
333
+ ### `upload_media_file(upload_url, name, path)`
334
+ آپلود فایل از مسیر محلی یا URL به Rubika و دریافت `file_id`
335
+
336
+ ---
337
+
338
+ ## 🔄 دریافت بروزرسانی‌ها
339
+
340
+ ### `get_updates(offset_id=None, limit=None)`
341
+ دریافت بروزرسانی‌ها (برای polling)
342
+
343
+
344
+ ---
345
+
346
+ # 📦 Rubka `Message` Class & Media Reply API Documentation
347
+
348
+ ## 🧾 معرفی کلاس `Message`
349
+
350
+ کلاس `Message` در کتابخانه Rubka ابزاری کلیدی برای مدیریت پیام‌های دریافتی در ربات است. این کلاس، قابلیت‌هایی همچون پاسخ به پیام، ارسال مدیا، حذف یا ویرایش پیام، و استفاده از صفحه‌کلید و دکمه‌های اینلاین را فراهم می‌کند.
351
+
352
+ ---
353
+
354
+ ## ⚙️ مشخصات کلاس `Message`
355
+
356
+ ```python
357
+ Message(bot, chat_id, message_id, sender_id, text=None, raw_data=None)
358
+ ```
359
+
360
+ ### پارامترها:
361
+
362
+ | پارامتر | توضیح |
363
+ | ------------ | ---------------------------------------- |
364
+ | `bot` | نمونه‌ی شی ربات |
365
+ | `chat_id` | شناسه چت |
366
+ | `message_id` | آیدی پیام |
367
+ | `sender_id` | شناسه فرستنده |
368
+ | `text` | متن پیام |
369
+ | `raw_data` | داده‌ی خام پیام (دیکشنری دریافتی از API) |
370
+
371
+ ### ویژگی‌ها (Attributes):
372
+
373
+ - `reply_to_message_id` – اگر پیام در پاسخ ارسال شده باشد، آیدی پیام اولیه
374
+ - `file`, `sticker`, `poll`, `contact_message`, `location`, ... – داده‌های مربوطه اگر وجود داشته باشند
375
+
376
+ ---
377
+
378
+ ## 📩 متدهای پاسخ‌دهی
379
+
380
+ ### ✉️ `reply(text: str, **kwargs)`
381
+
382
+ پاسخ متنی به پیام با قابلیت ارسال دکمه و گزینه‌های اضافی.
383
+
384
+ ### 📊 `reply_poll(question, options, **kwargs)`
385
+
386
+ ارسال نظرسنجی در پاسخ به پیام.
387
+
388
+ ### 📎 `reply_document(...)`
389
+
390
+ ارسال فایل یا سند با متن اختیاری و دکمه.
391
+
392
+ ### 🖼 `reply_image(...)`
393
+
394
+ ارسال تصویر با قابلیت reply همراه دکمه‌های chat یا inline.
395
+
396
+ ### 🎵 `reply_music(...)`
397
+
398
+ ارسال موزیک در پاسخ.
399
+
400
+ ### 🎤 `reply_voice(...)`
401
+
402
+ ارسال پیام صوتی (voice).
403
+
404
+ ### 🎞 `reply_gif(...)`
405
+
406
+ ارسال گیف در پاسخ به پیام.
407
+
408
+ ### 🗺 `reply_location(latitude, longitude, **kwargs)`
409
+
410
+ ارسال لوکیشن در پاسخ.
411
+
412
+ ### 📇 `reply_contact(first_name, last_name, phone_number, **kwargs)`
413
+
414
+ ارسال مخاطب در پاسخ.
415
+
416
+ ---
417
+
418
+ ## 🔘 پاسخ با دکمه‌ها
419
+
420
+ ### `reply_keypad(text, keypad, **kwargs)`
421
+
422
+ ارسال پیام با صفحه‌کلید چتی (ChatKeypad).
423
+
424
+ ### `reply_inline(text, inline_keypad, **kwargs)`
425
+
426
+ ارسال پیام با دکمه‌های شیشه‌ای (Inline).
427
+
428
+ ---
429
+
430
+ ## 📦 پاسخ با فایل‌ها و استیکر
431
+
432
+ ### `reply_sticker(sticker_id, **kwargs)`
433
+
434
+ ارسال استیکر در پاسخ به پیام.
435
+
436
+ ### `reply_file(file_id, **kwargs)`
437
+
438
+ ارسال فایل بر اساس File ID.
439
+
440
+ ---
441
+
442
+ ## ✏️ ویرایش و حذف
443
+
444
+ ### `edit(new_text)`
445
+
446
+ ویرایش متن پیام.
447
+
448
+ ### `delete()`
449
+
450
+ حذف پیام فعلی.
451
+
452
+ ---
453
+
454
+ ## 📤 مثال کاربردی کامل
455
+
456
+ ```python
457
+ @bot.on_message()
458
+ def handler(bot: Robot, message: Message):
459
+ # پاسخ با تصویر و دکمه‌های مختلف
460
+ message.reply_image(
461
+ path="https://s6.uupload.ir/files/sample.png",
462
+ text="📷 تصویر پاسخ‌داده‌شده با دکمه‌ها",
463
+ inline_keypad=inline_keypad
464
+ )
465
+
466
+ message.reply_image(
467
+ path="https://s6.uupload.ir/files/sample.png",
468
+ text="📷 تصویر دوم با صفحه‌کلید",
469
+ chat_keypad=chat_keypad,
470
+ chat_keypad_type="New"
471
+ )
472
+
473
+ @bot.on_callback()
474
+ def callback_handler(bot: Robot, message: Message):
475
+ data = message.aux_data.button_id
476
+ if data == "btn_male":
477
+ message.reply("سلام آقا 👨")
478
+ elif data == "btn_female":
479
+ message.reply("سلام خانم 👩")
480
+ else:
481
+ message.reply(f"دکمه ناشناخته: {data}")
482
+ ```
483
+
484
+ ---
485
+
486
+ ## 🧠 نکته
487
+
488
+ تمامی متدهای `reply_*` به‌صورت خودکار پیام جدید را در پاسخ به پیام اصلی ارسال می‌کنند (`reply_to_message_id` به‌صورت داخلی تنظیم می‌شود).
489
+
490
+ ---
491
+
492
+ ---
493
+
494
+ ## 📤 مثال کاربردی کامل
495
+
496
+ ```python
497
+ from rubka import Robot
498
+ from rubka.keypad import ChatKeypadBuilder
499
+ from rubka.button import InlineBuilder
500
+ from rubka.context import Message
501
+
502
+ chat_keypad = ChatKeypadBuilder().row(
503
+ ChatKeypadBuilder().button(id="btn_female", text="زن"),
504
+ ChatKeypadBuilder().button(id="btn_male", text="مرد")
505
+ ).build()
506
+
507
+ inline_keypad = (
508
+ InlineBuilder()
509
+ .row(
510
+ InlineBuilder().button_simple("btn_bets", "button1"),
511
+ InlineBuilder().button_simple("btn_rps", "button2")
512
+ )
513
+ .row(
514
+ InlineBuilder().button_simple("btn_chatid", "butthon3")
515
+ )
516
+ .build()
517
+ )
518
+
519
+ bot = Robot("توکن شما")
520
+
521
+ @bot.on_message()
522
+ def handler(bot: Robot, message: Message):
523
+ message.reply_image(
524
+ path="https://s6.uupload.ir/files/chatgpt_image_jul_20,_2025,_10_22_47_pm_oiql.png",
525
+ text="📷 عکس ریپلای شده دکمه شیشه ای",
526
+ inline_keypad=inline_keypad
527
+ )
528
+
529
+ message.reply_image(
530
+ path="https://s6.uupload.ir/files/chatgpt_image_jul_20,_2025,_10_22_47_pm_oiql.png",
531
+ text="📷 عکس ریپلای شده دکمه کیبوردی",
532
+ chat_keypad=chat_keypad,
533
+ chat_keypad_type="New"
534
+ )
535
+
536
+ @bot.on_callback()
537
+ def callback_handler(bot: Robot, message: Message):
538
+ data = message.aux_data.button_id
539
+ if data == "btn_male":
540
+ message.reply("سلام مرد")
541
+ elif data == "btn_female":
542
+ message.reply("سلام زن")
543
+ else:
544
+ message.reply(f"دکمه ناشناخته: {data}")
545
+
546
+ bot.run()
547
+ ```
548
+
549
+ ---
550
+
551
+ ## 🧱 مستندات کلاس `InlineBuilder`
552
+
553
+ کلاس `InlineBuilder` برای ساخت دکمه‌های اینلاین استفاده می‌شود که در پیام‌های ربات قابل استفاده هستند.
554
+
555
+ ### ✅ روش استفاده
556
+
557
+ ```python
558
+ from rubka.button import InlineBuilder
559
+
560
+ builder = InlineBuilder()
561
+ inline_keypad = builder.row(
562
+ builder.button_simple("btn_1", "دکمه ۱"),
563
+ builder.button_simple("btn_2", "دکمه ۲")
564
+ ).build()
565
+ ```
566
+
567
+ ### 📚 دکمه‌های پشتیبانی‌شده
568
+
569
+ - `button_simple(id, text)` – دکمه ساده
570
+ - `button_payment(id, title, amount, description=None)` – پرداخت
571
+ - `button_calendar(id, title, type_, ...)` – انتخاب تاریخ
572
+ - `button_location(id, type_, image_url, ...)` – ارسال موقعیت مکانی
573
+ - `button_string_picker(...)` – انتخاب گزینه از لیست
574
+ - `button_number_picker(...)` – انتخاب عدد از بازه
575
+ - `button_textbox(...)` – فیلد ورود متنی
576
+ - `button_selection(...)` – انتخاب چندگزینه‌ای پیشرفته
577
+ - `button_camera_image(...)`, `button_camera_video(...)`
578
+ - `button_gallery_image(...)`, `button_gallery_video(...)`
579
+ - `button_file(...)`, `button_audio(...)`, `button_record_audio(...)`
580
+ - `button_my_phone_number(...)`, `button_my_location(...)`
581
+ - `button_ask_my_phone_number(...)`, `button_ask_location(...)`
582
+ - `button_barcode(...)`
583
+ - `button_link(id, title, url)` – لینک خارجی
584
+
585
+ ### 🧱 ساخت نهایی
586
+
587
+ ```python
588
+ keypad = builder.build()
589
+ ```
590
+
591
+ خروجی به صورت دیکشنری با کلید `rows` خواهد بود که می‌توانید در متد `send_message` یا `reply_*` استفاده کنید.
592
+
593
+ ---
594
+
595
+ ## ⌨️ مستندات کلاس `ChatKeypadBuilder`
596
+
597
+ کلاس `ChatKeypadBuilder` برای ساخت صفحه‌کلید چتی (chat keypad) استفاده می‌شود.
598
+
599
+ ### 🛠 روش استفاده
600
+
601
+ ```python
602
+ from rubka.keypad import ChatKeypadBuilder
603
+
604
+ keypad = ChatKeypadBuilder().row(
605
+ ChatKeypadBuilder().button("btn_1", "دکمه ۱"),
606
+ ChatKeypadBuilder().button("btn_2", "دکمه ۲")
607
+ ).build()
608
+ ```
609
+
610
+ ### 📋 متدها
611
+
612
+ - `button(id, text, type="Simple")` – ساخت یک دکمه ساده یا از نوع خاص
613
+ - `row(*buttons)` – افزودن یک ردیف به کیبورد (دکمه‌ها باید با `button()` ساخته شوند)
614
+ - `build(resize_keyboard=True, on_time_keyboard=False)` – ساخت خروجی نهایی برای ارسال به کاربر
615
+
616
+ ### 📦 خروجی `build()`
617
+
618
+ ```json
619
+ {
620
+ "rows": [
621
+ {"buttons": [
622
+ {"id": "btn_1", "type": "Simple", "button_text": "دکمه ۱"},
623
+ {"id": "btn_2", "type": "Simple", "button_text": "دکمه ۲"}
624
+ ]}
625
+ ],
626
+ "resize_keyboard": true,
627
+ "on_time_keyboard": false
628
+ }
629
+ ```
630
+
631
+ ---
632
+
633
+ # مستندات پروژه: تایمر پیام در ربات Rubika
634
+
635
+ این پروژه یک ربات بر پایه کتابخانه‌ی `rubka` است که به کاربر امکان می‌دهد با استفاده از کی‌پد، یک تایمر تنظیم کرده و پس از پایان تایمر، پیامی برای او ارسال شود. تمرکز اصلی این مستند، بر روی کلاس `Job` است که برای زمان‌بندی اجرای دستورات استفاده شده است.
636
+
637
+ ## ساختار کلی پروژه
638
+ - استفاده از کتابخانه `rubka` برای ارتباط با Rubika Bot API
639
+ - تعریف یک کی‌پد با گزینه‌های تاخیر زمانی مختلف (۱۰ الی ۱۵۰ ثانیه)
640
+ - استفاده از کلاس `Job` برای مدیریت اجرای زمان‌بندی‌شده یک تابع
641
+ - نمایش شمارش معکوس با به‌روزرسانی مداوم پیام
642
+
643
+ ---
644
+
645
+ ## کلاس `Job` چیست؟
646
+ کلاس `Job` در فایل `rubka.jobs` تعریف شده و هدف آن اجرای یک تابع خاص پس از گذشت یک بازه زمانی مشخص است.
647
+
648
+ ### نحوه استفاده:
649
+ ```python
650
+ from rubka.jobs import Job
651
+
652
+ job = Job(delay_in_seconds, callback_function)
653
+ ```
654
+
655
+ ### پارامترها:
656
+ | پارامتر | نوع | توضیح |
657
+ |--------|-----|-------|
658
+ | `delay_in_seconds` | `int` | مدت زمانی که باید قبل از اجرای تابع منتظر بماند |
659
+ | `callback_function` | `function` | تابعی که بعد از پایان زمان باید اجرا شود |
660
+
661
+ ### ویژگی‌ها:
662
+ - اجرای غیرهمزمان (با استفاده از Thread داخلی)
663
+ - مناسب برای سناریوهایی مانند تایمرها، یادآورها و اعلان‌های زمان‌بندی شده
664
+
665
+ ---
666
+
667
+ ## مثال از استفاده در پروژه:
668
+
669
+ ```python
670
+ def delayed_send():
671
+ if user_id not in active_jobs:
672
+ return
673
+ bot.send_message(
674
+ message.chat_id,
675
+ f"✅ کاربر {user_id} : زمان {seconds} ثانیه گذشت و دستور اجرا شد! ⏰"
676
+ )
677
+ active_jobs.pop(user_id, None)
678
+
679
+ job = Job(seconds, delayed_send)
680
+ active_jobs[user_id] = job
681
+ ```
682
+
683
+ در این مثال، پس از انتخاب تاخیر زمانی توسط کاربر، یک شی از کلاس `Job` ساخته می‌شود که تابع `delayed_send` را پس از `seconds` ثانیه اجرا می‌کند.
684
+
685
+ ---
686
+
687
+ ## تابع `countdown_edit`
688
+ این تابع تایمر فعال را به صورت زنده باقیمانده زمان را به‌روزرسانی می‌کند:
689
+ ```python
690
+ def countdown_edit(chat_id, message_id, duration_sec):
691
+ # اجرای یک Thread برای به‌روزرسانی پیام در هر ثانیه
692
+ ```
693
+
694
+ ---
695
+ ## نمونه کد ساخته شده
696
+ ```python
697
+ from rubka import Robot
698
+ from rubka.context import Message
699
+ from rubka.keypad import ChatKeypadBuilder
700
+ from rubka.jobs import Job
701
+ from datetime import datetime, timedelta
702
+ import threading
703
+ import time
704
+
705
+ bot = Robot("token")
706
+
707
+ active_jobs = {}
708
+
709
+ def build_delay_keypad():
710
+ delays = [10, 20, 30, 40, 50, 60, 75, 90, 120, 150]
711
+ builder = ChatKeypadBuilder()
712
+ buttons = []
713
+ for sec in delays:
714
+ buttons.append(builder.button(id=f"delay_{sec}", text=f"⏳ بعد از {sec} ثانیه"))
715
+ buttons.append(builder.button(id="cancel", text="❌ انصراف"))
716
+
717
+ rows = [buttons[i:i+3] for i in range(0, len(buttons), 3)]
718
+ keypad = ChatKeypadBuilder()
719
+ for row in rows:
720
+ keypad.row(*row)
721
+ return keypad.build()
722
+
723
+ def countdown_edit(chat_id: str, message_id: str, duration_sec: int):
724
+ start_time = datetime.now()
725
+ end_time = start_time + timedelta(seconds=duration_sec)
726
+
727
+ def run():
728
+ while True:
729
+ now = datetime.now()
730
+ if now >= end_time:
731
+ try:
732
+ bot.edit_message_text(chat_id, message_id, "⏰ زمان تمام شد!")
733
+ except Exception as e:
734
+ print("خطا در ویرایش پیام:", e)
735
+ break
736
+
737
+ remaining = end_time - now
738
+ text = (
739
+ f"⏳ تایمر فعال است...\n"
740
+ f"🕰 شروع: {start_time.strftime('%H:%M:%S')}\n"
741
+ f"⏲ پایان: {end_time.strftime('%H:%M:%S')}\n"
742
+ f"⌛ باقی‌مانده: {str(remaining).split('.')[0]}"
743
+ )
744
+ try:
745
+ bot.edit_message_text(chat_id, message_id, text)
746
+ except Exception as e:
747
+ print("خطا در ویرایش پیام:", e)
748
+ time.sleep(1)
749
+
750
+ threading.Thread(target=run, daemon=True).start()
751
+
752
+ @bot.on_message(commands=["start"])
753
+ def start_handler(bot: Robot, message: Message):
754
+ keypad = build_delay_keypad()
755
+ message.reply_keypad(
756
+ "سلام 👋\n"
757
+ "یک زمان برای ارسال پیام انتخاب کنید:\n"
758
+ "📅 تاریخ و ساعت فعلی: " + datetime.now().strftime("%Y/%m/%d %H:%M:%S"),
759
+ keypad
760
+ )
761
+
762
+ @bot.on_callback()
763
+ def callback_delay(bot: Robot, message: Message):
764
+ btn_id = message.aux_data.button_id
765
+ user_id = message.sender_id
766
+
767
+ if btn_id == "cancel":
768
+ if user_id in active_jobs:
769
+ active_jobs.pop(user_id)
770
+ message.reply("❌ همه ارسال‌های زمان‌بندی شده لغو شدند.")
771
+ else:
772
+ message.reply("⚠️ شما هیچ ارسال زمان‌بندی شده‌ای ندارید.")
773
+ return
774
+
775
+ if not btn_id.startswith("delay_"):
776
+ message.reply("❌ دکمه نامعتبر است!")
777
+ return
778
+
779
+ seconds = int(btn_id.split("_")[1])
780
+
781
+ if user_id in active_jobs:
782
+ active_jobs.pop(user_id)
783
+
784
+ sent_msg = bot.send_message(
785
+ message.chat_id,
786
+ f"⏳ تایمر {seconds} ثانیه‌ای شروع شد...\n🕰 زمان شروع: {datetime.now().strftime('%H:%M:%S')}"
787
+ )
788
+
789
+ countdown_edit(message.chat_id, sent_msg['data']['message_id'], seconds)
790
+ def delayed_send():
791
+ if user_id not in active_jobs:
792
+ return
793
+ bot.send_message(
794
+ message.chat_id,
795
+ f"✅ کاربر {user_id} : زمان {seconds} ثانیه گذشت و دستور اجرا شد! ⏰"
796
+ )
797
+ active_jobs.pop(user_id, None)
798
+
799
+ job = Job(seconds, delayed_send)
800
+ active_jobs[user_id] = job
801
+
802
+ message.reply(
803
+ f"⏳ ثبت شد! پیام شما پس از {seconds} ثانیه ارسال خواهد شد.\n"
804
+ f"🕰 زمان شروع ثبت شده: {datetime.now().strftime('%H:%M:%S')}"
805
+ )
806
+ bot.run()
807
+ ```
808
+
809
+ ##مثال ساده تر
810
+ ```python
811
+ from rubka import Robot
812
+ from rubka.context import Message
813
+ from rubka.jobs import Job
814
+ from datetime import datetime
815
+
816
+ bot = Robot("")
817
+
818
+ active_jobs = {}
819
+
820
+ @bot.on_message(commands=["timer"])
821
+ def timer_handler(bot: Robot, message: Message):
822
+ user_id = message.sender_id
823
+ chat_id = message.chat_id
824
+ parts = message.text.split()
825
+
826
+ if len(parts) != 2 or not parts[1].isdigit():
827
+ return message.reply("⚠️ لطفاً مدت زمان را به صورت صحیح وارد کنید. مثل: `/timer 30`", parse_mode="markdown")
828
+
829
+ seconds = int(parts[1])
830
+ if user_id in active_jobs:
831
+ active_jobs.pop(user_id)
832
+
833
+ message.reply(f"⏳ تایمر {seconds} ثانیه‌ای شروع شد!\n🕰 زمان شروع: {datetime.now().strftime('%H:%M:%S')}")
834
+
835
+ def after_delay():
836
+ if user_id not in active_jobs:
837
+ return
838
+ bot.send_message(chat_id, f"✅ تایمر {seconds} ثانیه‌ای تمام شد! ⏰")
839
+ active_jobs.pop(user_id, None)
840
+
841
+ job = Job(seconds, after_delay)
842
+ active_jobs[user_id] = job
843
+
844
+ bot.run()
845
+
846
+ ```
847
+
848
+ ##نمونه کد ادیت تایم و کرون جاب با اینلاین کیبورد
849
+
850
+ ```python
851
+ from rubka import Robot
852
+ from rubka.context import Message
853
+ from rubka.keypad import ChatKeypadBuilder
854
+ from rubka.jobs import Job
855
+ from datetime import datetime, timedelta
856
+ import threading
857
+ import time
858
+
859
+ bot = Robot("token")
860
+ bot.edit_inline_keypad
861
+ active_jobs = {}
862
+
863
+ def build_delay_keypad():
864
+ delays = [10, 20, 30, 40, 50, 60, 75, 90, 120, 150]
865
+ builder = ChatKeypadBuilder()
866
+ buttons = []
867
+ for sec in delays:
868
+ buttons.append(builder.button(id=f"delay_{sec}", text=f"⏳ بعد از {sec} ثانیه"))
869
+ buttons.append(builder.button(id="cancel", text="❌ انصراف"))
870
+
871
+ rows = [buttons[i:i+3] for i in range(0, len(buttons), 3)]
872
+ keypad = ChatKeypadBuilder()
873
+ for row in rows:
874
+ keypad.row(*row)
875
+ return keypad.build()
876
+
877
+ def countdown_edit(chat_id: str, message_id: str, duration_sec: int):
878
+ start_time = datetime.now()
879
+ end_time = start_time + timedelta(seconds=duration_sec)
880
+
881
+ def run():
882
+ while True:
883
+ now = datetime.now()
884
+ if now >= end_time:
885
+ try:
886
+ bot.edit_message_text(chat_id, message_id, "⏰ زمان تمام شد!")
887
+ except Exception as e:
888
+ print("خطا در ویرایش پیام:", e)
889
+ break
890
+
891
+ remaining = end_time - now
892
+ text = (
893
+ f"⏳ تایمر فعال است...\n"
894
+ f"🕰 شروع: {start_time.strftime('%H:%M:%S')}\n"
895
+ f"⏲ پایان: {end_time.strftime('%H:%M:%S')}\n"
896
+ f"⌛ باقی‌مانده: {str(remaining).split('.')[0]}"
897
+ )
898
+ try:
899
+ bot.edit_message_text(chat_id, message_id, text)
900
+ except Exception as e:
901
+ print("خطا در ویرایش پیام:", e)
902
+ time.sleep(1)
903
+
904
+ threading.Thread(target=run, daemon=True).start()
905
+
906
+ @bot.on_message(commands=["start"])
907
+ def start_handler(bot: Robot, message: Message):
908
+ keypad = build_delay_keypad()
909
+ message.reply_keypad(
910
+ "سلام 👋\n"
911
+ "یک زمان برای ارسال پیام انتخاب کنید:\n"
912
+ "📅 تاریخ و ساعت فعلی: " + datetime.now().strftime("%Y/%m/%d %H:%M:%S"),
913
+ keypad
914
+ )
915
+
916
+ @bot.on_callback()
917
+ def callback_delay(bot: Robot, message: Message):
918
+ btn_id = message.aux_data.button_id
919
+ user_id = message.sender_id
920
+
921
+ if btn_id == "cancel":
922
+ if user_id in active_jobs:
923
+ active_jobs.pop(user_id)
924
+ message.reply("❌ همه ارسال‌های زمان‌بندی شده لغو شدند.")
925
+ else:
926
+ message.reply("⚠️ شما هیچ ارسال زمان‌بندی شده‌ای ندارید.")
927
+ return
928
+ if not btn_id.startswith("delay_"):
929
+ message.reply("❌ دکمه نامعتبر است!")
930
+ return
931
+ seconds = int(btn_id.split("_")[1])
932
+ if user_id in active_jobs:
933
+ active_jobs.pop(user_id)
934
+ sent_msg = bot.edit_inline_keypad(
935
+ message.chat_id,
936
+ f"⏳ تایمر {seconds} ثانیه‌ای شروع شد...\n🕰 زمان شروع: {datetime.now().strftime('%H:%M:%S')}"
937
+ )
938
+ print(sent_msg)
939
+ countdown_edit(message.chat_id, sent_msg['data']['message_id'], seconds)
940
+ def delayed_send():
941
+ if user_id not in active_jobs:
942
+ return
943
+
944
+ bot.send_message(
945
+ message.chat_id,
946
+ f"✅ کاربر {user_id} : زمان {seconds} ثانیه گذشت و دستور اجرا شد! ⏰"
947
+ )
948
+ active_jobs.pop(user_id, None)
949
+
950
+ job = Job(seconds, delayed_send)
951
+ active_jobs[user_id] = job
952
+
953
+ message.reply(
954
+ f"⏳ ثبت شد! پیام شما پس از {seconds} ثانیه ارسال خواهد شد.\n"
955
+ f"🕰 زمان شروع ثبت شده: {datetime.now().strftime('%H:%M:%S')}"
956
+ )
957
+
958
+ bot.run()
959
+ ```
960
+ # ✅ Force Join (اجبار به عضویت در کانال) — Rubka Bot
961
+
962
+ این مستند نحوه استفاده از قابلیت **اجبار به عضویت در یک کانال (Force Join)** در ربات‌های ساخته‌شده با کتابخانه Rubka را توضیح می‌دهد.
963
+
964
+ ---
965
+
966
+ ## 🎯 هدف
967
+
968
+ اطمینان از اینکه کاربر عضو یک کانال خاص است، قبل از ادامه تعامل با ربات. اگر عضو نبود، به او اطلاع داده شود یا لینک عضویت ارسال گردد.
969
+
970
+ ---
971
+
972
+ ## 📦 پیش‌نیازها
973
+
974
+ - نصب و راه‌اندازی کتابخانه `rubka`
975
+ - توکن معتبر ربات Rubika
976
+ - دسترسی به `channel_guid` (شناسه عددی کانال)
977
+ - ربات باید در کانال، **ادمین** باشد
978
+
979
+ ---
980
+
981
+ ## 💡 نحوه استفاده
982
+
983
+ ### کد بهینه‌شده:
984
+
985
+ ```python
986
+ from rubka import Robot
987
+ from rubka.context import Message
988
+
989
+ bot = Robot(token="your_token")
990
+ CHANNEL_GUID = "c0xABCDEF..." # GUID کانال هدف
991
+
992
+ @bot.on_message()
993
+ def handle_force_join(bot: Robot, message: Message):
994
+ name = bot.get_name(message.chat_id)
995
+
996
+ if bot.check_join(CHANNEL_GUID, message.chat_id):
997
+ message.reply(f"سلام {name} 👋\nشما عضو کانال هستید ✅")
998
+ else:
999
+ join_link = "https://rubika.ir/rubka_library"
1000
+ message.reply(
1001
+ f"سلام {name} 👋\nشما عضو کانال نیستید ❌\n\n"
1002
+ f"لطفاً ابتدا عضو کانال شوید سپس دوباره تلاش کنید:\n{join_link}"
1003
+ )
1004
+
1005
+ bot.run()
1006
+ ```
1007
+
1008
+ ---
1009
+
1010
+ ## 🔍 شرح متدها
1011
+
1012
+ | متد | کاربرد |
1013
+ | ------------------------------------- | ------------------------------------ |
1014
+ | `check_join(channel_guid, user_guid)` | بررسی عضویت کاربر در کانال مشخص‌شده |
1015
+ | `get_name(user_guid)` | دریافت نام نمایشی کاربر از طریق GUID |
1016
+ | `message.reply(text)` | پاسخ مستقیم به پیام دریافت‌شده |
1017
+
1018
+ ---
1019
+
1020
+ ## 🔐 نکات مهم امنیتی
1021
+
1022
+ - ربات باید حتماً **ادمین کانال** باشد.
1023
+ - در صورت عدم عضویت، بهتر است لینک دعوت به کانال نمایش داده شود.
1024
+
1025
+ ##Mahdi Ahmadi