Rubka 3.2.5__py3-none-any.whl → 4.3.4__py3-none-any.whl
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.
- rubka/api.py +84 -20
- rubka/button.py +264 -0
- rubka/context.py +0 -1
- rubka/keypad.py +255 -5
- {rubka-3.2.5.dist-info → rubka-4.3.4.dist-info}/METADATA +1 -1
- {rubka-3.2.5.dist-info → rubka-4.3.4.dist-info}/RECORD +8 -7
- {rubka-3.2.5.dist-info → rubka-4.3.4.dist-info}/WHEEL +0 -0
- {rubka-3.2.5.dist-info → rubka-4.3.4.dist-info}/top_level.txt +0 -0
rubka/api.py
CHANGED
|
@@ -73,6 +73,8 @@ class Robot:
|
|
|
73
73
|
self._callback_handler = None
|
|
74
74
|
self._message_handler = None
|
|
75
75
|
self._inline_query_handler = None
|
|
76
|
+
self._callback_handlers = None
|
|
77
|
+
self._callback_handlers = [] # ✅ این خط مهمه
|
|
76
78
|
|
|
77
79
|
|
|
78
80
|
logger.info(f"Initialized RubikaBot with token: {token[:8]}***")
|
|
@@ -108,7 +110,16 @@ class Robot:
|
|
|
108
110
|
return func
|
|
109
111
|
return decorator
|
|
110
112
|
|
|
111
|
-
|
|
113
|
+
def on_callback(self, button_id: Optional[str] = None):
|
|
114
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
115
|
+
if not hasattr(self, "_callback_handlers"):
|
|
116
|
+
self._callback_handlers = []
|
|
117
|
+
self._callback_handlers.append({
|
|
118
|
+
"func": func,
|
|
119
|
+
"button_id": button_id
|
|
120
|
+
})
|
|
121
|
+
return func
|
|
122
|
+
return decorator
|
|
112
123
|
def on_inline_query(self):
|
|
113
124
|
def decorator(func: Callable[[Any, InlineMessage], None]):
|
|
114
125
|
self._inline_query_handler = func
|
|
@@ -116,12 +127,14 @@ class Robot:
|
|
|
116
127
|
return decorator
|
|
117
128
|
|
|
118
129
|
def _process_update(self, update: Dict[str, Any]):
|
|
119
|
-
import threading
|
|
130
|
+
import threading, time
|
|
131
|
+
|
|
120
132
|
if update.get('type') == 'ReceiveQuery':
|
|
121
133
|
msg = update.get("inline_message", {})
|
|
122
134
|
if self._inline_query_handler:
|
|
123
135
|
context = InlineMessage(bot=self, raw_data=msg)
|
|
124
136
|
threading.Thread(target=self._inline_query_handler, args=(self, context), daemon=True).start()
|
|
137
|
+
return # اگر inline بود ادامه نده
|
|
125
138
|
|
|
126
139
|
if update.get('type') == 'NewMessage':
|
|
127
140
|
msg = update.get('new_message', {})
|
|
@@ -129,16 +142,27 @@ class Robot:
|
|
|
129
142
|
message_id = msg.get('message_id')
|
|
130
143
|
sender_id = msg.get('sender_id')
|
|
131
144
|
text = msg.get('text')
|
|
145
|
+
|
|
146
|
+
# فیلتر زمان قدیمی
|
|
132
147
|
try:
|
|
133
|
-
import time
|
|
134
148
|
if msg.get("time") and (time.time() - float(msg["time"])) > 20:
|
|
135
149
|
return
|
|
136
150
|
except Exception:
|
|
137
151
|
return
|
|
138
152
|
|
|
153
|
+
# ساخت context یکجا
|
|
154
|
+
context = Message(bot=self, chat_id=chat_id, message_id=message_id, sender_id=sender_id, text=text, raw_data=msg)
|
|
155
|
+
|
|
156
|
+
# 💠 اول بررسی دکمهها (callback)
|
|
157
|
+
if context.aux_data and hasattr(self, "_callback_handlers"):
|
|
158
|
+
for handler in self._callback_handlers:
|
|
159
|
+
if not handler["button_id"] or context.aux_data.button_id == handler["button_id"]:
|
|
160
|
+
threading.Thread(target=handler["func"], args=(self, context), daemon=True).start()
|
|
161
|
+
return # فقط اولین callback اجرا شود
|
|
162
|
+
|
|
163
|
+
# 💠 بعد بررسی پیامهای متنی معمولی
|
|
139
164
|
if self._message_handler:
|
|
140
165
|
handler = self._message_handler
|
|
141
|
-
context = Message(bot=self, chat_id=chat_id, message_id=message_id, sender_id=sender_id, text=text, raw_data=msg)
|
|
142
166
|
|
|
143
167
|
if handler["commands"]:
|
|
144
168
|
if not context.text or not context.text.startswith("/"):
|
|
@@ -149,22 +173,11 @@ class Robot:
|
|
|
149
173
|
return
|
|
150
174
|
context.args = parts[1:]
|
|
151
175
|
|
|
152
|
-
if handler["filters"]:
|
|
153
|
-
|
|
154
|
-
return
|
|
176
|
+
if handler["filters"] and not handler["filters"](context):
|
|
177
|
+
return
|
|
155
178
|
|
|
156
179
|
threading.Thread(target=handler["func"], args=(self, context), daemon=True).start()
|
|
157
180
|
|
|
158
|
-
elif update.get('type') == 'ReceiveQuery':
|
|
159
|
-
msg = update.get("inline_message", {})
|
|
160
|
-
chat_id = msg.get("chat_id")
|
|
161
|
-
message_id = msg.get("message_id")
|
|
162
|
-
sender_id = msg.get("sender_id")
|
|
163
|
-
text = msg.get("text")
|
|
164
|
-
|
|
165
|
-
if hasattr(self, "_callback_handler"):
|
|
166
|
-
context = Message(bot=self, chat_id=chat_id, message_id=message_id, sender_id=sender_id, text=text, raw_data=msg)
|
|
167
|
-
threading.Thread(target=self._callback_handler, args=(self, context), daemon=True).start()
|
|
168
181
|
|
|
169
182
|
|
|
170
183
|
|
|
@@ -222,9 +235,40 @@ class Robot:
|
|
|
222
235
|
|
|
223
236
|
return self._post("sendMessage", payload)
|
|
224
237
|
|
|
225
|
-
def
|
|
226
|
-
|
|
227
|
-
|
|
238
|
+
def _get_client(self):
|
|
239
|
+
return Client_get(show_last_six_words(self.token))
|
|
240
|
+
|
|
241
|
+
def check_join(self, channel_guid: str, chat_id: str = None) -> bool | list[str]:
|
|
242
|
+
client = self._get_client()
|
|
243
|
+
|
|
244
|
+
if chat_id:
|
|
245
|
+
chat_info = self.get_chat(chat_id).get('data', {}).get('chat', {})
|
|
246
|
+
username = chat_info.get('username')
|
|
247
|
+
user_id = chat_info.get('user_id')
|
|
248
|
+
|
|
249
|
+
if username:
|
|
250
|
+
members = self.get_all_member(channel_guid, search_text=username).get('in_chat_members', [])
|
|
251
|
+
return any(m.get('username') == username for m in members)
|
|
252
|
+
|
|
253
|
+
elif user_id:
|
|
254
|
+
member_guids = client.get_all_members(channel_guid, just_get_guids=True)
|
|
255
|
+
return user_id in member_guids
|
|
256
|
+
|
|
257
|
+
return False
|
|
258
|
+
|
|
259
|
+
return False
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def get_all_member(
|
|
263
|
+
self,
|
|
264
|
+
channel_guid: str,
|
|
265
|
+
search_text: str = None,
|
|
266
|
+
start_id: str = None,
|
|
267
|
+
just_get_guids: bool = False
|
|
268
|
+
):
|
|
269
|
+
client = self._get_client()
|
|
270
|
+
return client.get_all_members(channel_guid, search_text, start_id, just_get_guids)
|
|
271
|
+
|
|
228
272
|
def send_poll(
|
|
229
273
|
self,
|
|
230
274
|
chat_id: str,
|
|
@@ -373,3 +417,23 @@ class Robot:
|
|
|
373
417
|
"chat_keypad_type": "New",
|
|
374
418
|
"chat_keypad": chat_keypad
|
|
375
419
|
})
|
|
420
|
+
def get_name(self, chat_id: str) -> str:
|
|
421
|
+
try:
|
|
422
|
+
chat = self.get_chat(chat_id)
|
|
423
|
+
chat_info = chat.get("data", {}).get("chat", {})
|
|
424
|
+
first_name = chat_info.get("first_name", "")
|
|
425
|
+
last_name = chat_info.get("last_name", "")
|
|
426
|
+
|
|
427
|
+
if first_name and last_name:
|
|
428
|
+
return f"{first_name} {last_name}"
|
|
429
|
+
elif first_name:
|
|
430
|
+
return first_name
|
|
431
|
+
elif last_name:
|
|
432
|
+
return last_name
|
|
433
|
+
else:
|
|
434
|
+
return "Unknown"
|
|
435
|
+
except Exception:
|
|
436
|
+
return "Unknown"
|
|
437
|
+
def get_username(self, chat_id: str) -> str:
|
|
438
|
+
chat_info = self.get_chat(chat_id).get("data", {}).get("chat", {})
|
|
439
|
+
return chat_info.get("username", "None")
|
rubka/button.py
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from typing import Dict, List, Optional, Union
|
|
4
|
+
from typing import Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
class InlineBuilder:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.rows: List[Dict] = []
|
|
9
|
+
|
|
10
|
+
def row(self, *buttons: Dict) -> "InlineBuilder":
|
|
11
|
+
"""
|
|
12
|
+
افزودن یک ردیف دکمه به کیبورد
|
|
13
|
+
حداقل یک دکمه باید داده شود.
|
|
14
|
+
"""
|
|
15
|
+
if not buttons:
|
|
16
|
+
raise ValueError("حداقل یک دکمه باید به row داده شود")
|
|
17
|
+
self.rows.append({"buttons": list(buttons)})
|
|
18
|
+
return self
|
|
19
|
+
|
|
20
|
+
def button_simple(self, id: str, text: str) -> Dict:
|
|
21
|
+
return {"id": id, "type": "Simple", "button_text": text}
|
|
22
|
+
|
|
23
|
+
def button_selection(self, id: str, text: str, selection: Dict) -> Dict:
|
|
24
|
+
"""
|
|
25
|
+
selection: dict با فیلدهای:
|
|
26
|
+
- selection_id (str)
|
|
27
|
+
- search_type (str) [ButtonSelectionSearchEnum: None, Local, Api]
|
|
28
|
+
- get_type (str) [ButtonSelectionGetEnum: Local, Api]
|
|
29
|
+
- items (list of ButtonSelectionItem)
|
|
30
|
+
- is_multi_selection (bool)
|
|
31
|
+
- columns_count (str)
|
|
32
|
+
- title (str)
|
|
33
|
+
"""
|
|
34
|
+
return {
|
|
35
|
+
"id": id,
|
|
36
|
+
"type": "Selection",
|
|
37
|
+
"button_text": text,
|
|
38
|
+
"button_selection": selection
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def button_calendar(self, id: str, title: str, type_: str,
|
|
42
|
+
default_value: Optional[str] = None,
|
|
43
|
+
min_year: Optional[str] = None,
|
|
44
|
+
max_year: Optional[str] = None) -> Dict:
|
|
45
|
+
"""
|
|
46
|
+
type_: ButtonCalendarTypeEnum = "DatePersian" | "DateGregorian"
|
|
47
|
+
"""
|
|
48
|
+
calendar = {
|
|
49
|
+
"title": title,
|
|
50
|
+
"type": type_,
|
|
51
|
+
}
|
|
52
|
+
if default_value:
|
|
53
|
+
calendar["default_value"] = default_value
|
|
54
|
+
if min_year:
|
|
55
|
+
calendar["min_year"] = min_year
|
|
56
|
+
if max_year:
|
|
57
|
+
calendar["max_year"] = max_year
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
"id": id,
|
|
61
|
+
"type": "Calendar",
|
|
62
|
+
"button_text": title,
|
|
63
|
+
"button_calendar": calendar
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
def button_number_picker(self, id: str, title: str, min_value: str, max_value: str,
|
|
67
|
+
default_value: Optional[str] = None) -> Dict:
|
|
68
|
+
picker = {
|
|
69
|
+
"title": title,
|
|
70
|
+
"min_value": min_value,
|
|
71
|
+
"max_value": max_value,
|
|
72
|
+
}
|
|
73
|
+
if default_value:
|
|
74
|
+
picker["default_value"] = default_value
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
"id": id,
|
|
78
|
+
"type": "NumberPicker",
|
|
79
|
+
"button_text": title,
|
|
80
|
+
"button_number_picker": picker
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
def button_string_picker(self, id: str, title: Optional[str], items: List[str],
|
|
84
|
+
default_value: Optional[str] = None) -> Dict:
|
|
85
|
+
picker = {
|
|
86
|
+
"items": items
|
|
87
|
+
}
|
|
88
|
+
if default_value:
|
|
89
|
+
picker["default_value"] = default_value
|
|
90
|
+
if title:
|
|
91
|
+
picker["title"] = title
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
"id": id,
|
|
95
|
+
"type": "StringPicker",
|
|
96
|
+
"button_text": title if title else "انتخاب",
|
|
97
|
+
"button_string_picker": picker
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
def button_location(self, id: str, type_: str, location_image_url: str,
|
|
101
|
+
default_pointer_location: Optional[Dict] = None,
|
|
102
|
+
default_map_location: Optional[Dict] = None,
|
|
103
|
+
title: Optional[str] = None) -> Dict:
|
|
104
|
+
"""
|
|
105
|
+
type_: ButtonLocationTypeEnum = "Picker" | "View"
|
|
106
|
+
location_image_url: str آدرس عکس دکمه موقعیت
|
|
107
|
+
default_pointer_location و default_map_location هر کدام دیکشنری Location (latitude, longitude)
|
|
108
|
+
"""
|
|
109
|
+
loc = {
|
|
110
|
+
"type": type_,
|
|
111
|
+
"location_image_url": location_image_url,
|
|
112
|
+
}
|
|
113
|
+
if default_pointer_location:
|
|
114
|
+
loc["default_pointer_location"] = default_pointer_location
|
|
115
|
+
if default_map_location:
|
|
116
|
+
loc["default_map_location"] = default_map_location
|
|
117
|
+
if title:
|
|
118
|
+
loc["title"] = title
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
"id": id,
|
|
122
|
+
"type": "Location",
|
|
123
|
+
"button_text": title if title else "موقعیت مکانی",
|
|
124
|
+
"button_location": loc
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
def button_textbox(self, id: str, title: Optional[str],
|
|
128
|
+
type_line: str, type_keypad: str,
|
|
129
|
+
place_holder: Optional[str] = None,
|
|
130
|
+
default_value: Optional[str] = None) -> Dict:
|
|
131
|
+
"""
|
|
132
|
+
type_line: ButtonTextboxTypeLineEnum = "SingleLine" | "MultiLine"
|
|
133
|
+
type_keypad: ButtonTextboxTypeKeypadEnum = "String" | "Number"
|
|
134
|
+
"""
|
|
135
|
+
textbox = {
|
|
136
|
+
"type_line": type_line,
|
|
137
|
+
"type_keypad": type_keypad
|
|
138
|
+
}
|
|
139
|
+
if place_holder:
|
|
140
|
+
textbox["place_holder"] = place_holder
|
|
141
|
+
if default_value:
|
|
142
|
+
textbox["default_value"] = default_value
|
|
143
|
+
if title:
|
|
144
|
+
textbox["title"] = title
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
"id": id,
|
|
148
|
+
"type": "Textbox",
|
|
149
|
+
"button_text": title if title else "متن",
|
|
150
|
+
"button_textbox": textbox
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
def button_payment(self, id: str, title: str, amount: int, description: Optional[str] = None) -> Dict:
|
|
154
|
+
"""
|
|
155
|
+
نمونهای ساده برای دکمه پرداخت (مقدار و توضیح دلخواه)
|
|
156
|
+
"""
|
|
157
|
+
payment = {
|
|
158
|
+
"title": title,
|
|
159
|
+
"amount": amount
|
|
160
|
+
}
|
|
161
|
+
if description:
|
|
162
|
+
payment["description"] = description
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
"id": id,
|
|
166
|
+
"type": "Payment",
|
|
167
|
+
"button_text": title,
|
|
168
|
+
"button_payment": payment
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
def button_camera_image(self, id: str, title: str) -> Dict:
|
|
172
|
+
return {
|
|
173
|
+
"id": id,
|
|
174
|
+
"type": "CameraImage",
|
|
175
|
+
"button_text": title
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
def button_camera_video(self, id: str, title: str) -> Dict:
|
|
179
|
+
return {
|
|
180
|
+
"id": id,
|
|
181
|
+
"type": "CameraVideo",
|
|
182
|
+
"button_text": title
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
def button_gallery_image(self, id: str, title: str) -> Dict:
|
|
186
|
+
return {
|
|
187
|
+
"id": id,
|
|
188
|
+
"type": "GalleryImage",
|
|
189
|
+
"button_text": title
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
def button_gallery_video(self, id: str, title: str) -> Dict:
|
|
193
|
+
return {
|
|
194
|
+
"id": id,
|
|
195
|
+
"type": "GalleryVideo",
|
|
196
|
+
"button_text": title
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
def button_file(self, id: str, title: str) -> Dict:
|
|
200
|
+
return {
|
|
201
|
+
"id": id,
|
|
202
|
+
"type": "File",
|
|
203
|
+
"button_text": title
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
def button_audio(self, id: str, title: str) -> Dict:
|
|
207
|
+
return {
|
|
208
|
+
"id": id,
|
|
209
|
+
"type": "Audio",
|
|
210
|
+
"button_text": title
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
def button_record_audio(self, id: str, title: str) -> Dict:
|
|
214
|
+
return {
|
|
215
|
+
"id": id,
|
|
216
|
+
"type": "RecordAudio",
|
|
217
|
+
"button_text": title
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
def button_my_phone_number(self, id: str, title: str) -> Dict:
|
|
221
|
+
return {
|
|
222
|
+
"id": id,
|
|
223
|
+
"type": "MyPhoneNumber",
|
|
224
|
+
"button_text": title
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
def button_my_location(self, id: str, title: str) -> Dict:
|
|
228
|
+
return {
|
|
229
|
+
"id": id,
|
|
230
|
+
"type": "MyLocation",
|
|
231
|
+
"button_text": title
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
def button_link(self, id: str, title: str, url: str) -> Dict:
|
|
235
|
+
return {
|
|
236
|
+
"id": id,
|
|
237
|
+
"type": "Link",
|
|
238
|
+
"button_text": title,
|
|
239
|
+
"url": url
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
def button_ask_my_phone_number(self, id: str, title: str) -> Dict:
|
|
243
|
+
return {
|
|
244
|
+
"id": id,
|
|
245
|
+
"type": "AskMyPhoneNumber",
|
|
246
|
+
"button_text": title
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
def button_ask_location(self, id: str, title: str) -> Dict:
|
|
250
|
+
return {
|
|
251
|
+
"id": id,
|
|
252
|
+
"type": "AskLocation",
|
|
253
|
+
"button_text": title
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
def button_barcode(self, id: str, title: str) -> Dict:
|
|
257
|
+
return {
|
|
258
|
+
"id": id,
|
|
259
|
+
"type": "Barcode",
|
|
260
|
+
"button_text": title
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
def build(self) -> Dict:
|
|
264
|
+
return {"rows": self.rows}
|
rubka/context.py
CHANGED
|
@@ -195,7 +195,6 @@ class Message:
|
|
|
195
195
|
self.time: str = self.raw_data.get("time")
|
|
196
196
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
197
197
|
self.sender_type: str = self.raw_data.get("sender_type")
|
|
198
|
-
|
|
199
198
|
self.args = []
|
|
200
199
|
self.reply_to_message_id: Optional[str] = self.raw_data.get("reply_to_message_id")
|
|
201
200
|
self.forwarded_from = ForwardedFrom(self.raw_data["forwarded_from"]) if "forwarded_from" in self.raw_data else None
|
rubka/keypad.py
CHANGED
|
@@ -1,18 +1,268 @@
|
|
|
1
1
|
from typing import Dict
|
|
2
2
|
|
|
3
|
+
from typing import Dict, List, Optional, Union
|
|
4
|
+
from typing import Dict, List, Optional
|
|
5
|
+
|
|
3
6
|
class InlineBuilder:
|
|
4
7
|
def __init__(self):
|
|
5
|
-
self.rows = []
|
|
8
|
+
self.rows: List[Dict] = []
|
|
6
9
|
|
|
7
|
-
def row(self, *buttons: Dict
|
|
10
|
+
def row(self, *buttons: Dict) -> "InlineBuilder":
|
|
11
|
+
"""
|
|
12
|
+
افزودن یک ردیف دکمه به کیبورد
|
|
13
|
+
حداقل یک دکمه باید داده شود.
|
|
14
|
+
"""
|
|
15
|
+
if not buttons:
|
|
16
|
+
raise ValueError("حداقل یک دکمه باید به row داده شود")
|
|
8
17
|
self.rows.append({"buttons": list(buttons)})
|
|
9
18
|
return self
|
|
10
19
|
|
|
11
|
-
def
|
|
12
|
-
return {"id": id, "type":
|
|
20
|
+
def button_simple(self, id: str, text: str) -> Dict:
|
|
21
|
+
return {"id": id, "type": "Simple", "button_text": text}
|
|
22
|
+
|
|
23
|
+
def button_selection(self, id: str, text: str, selection: Dict) -> Dict:
|
|
24
|
+
"""
|
|
25
|
+
selection: dict با فیلدهای:
|
|
26
|
+
- selection_id (str)
|
|
27
|
+
- search_type (str) [ButtonSelectionSearchEnum: None, Local, Api]
|
|
28
|
+
- get_type (str) [ButtonSelectionGetEnum: Local, Api]
|
|
29
|
+
- items (list of ButtonSelectionItem)
|
|
30
|
+
- is_multi_selection (bool)
|
|
31
|
+
- columns_count (str)
|
|
32
|
+
- title (str)
|
|
33
|
+
"""
|
|
34
|
+
return {
|
|
35
|
+
"id": id,
|
|
36
|
+
"type": "Selection",
|
|
37
|
+
"button_text": text,
|
|
38
|
+
"button_selection": selection
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def button_calendar(self, id: str, title: str, type_: str,
|
|
42
|
+
default_value: Optional[str] = None,
|
|
43
|
+
min_year: Optional[str] = None,
|
|
44
|
+
max_year: Optional[str] = None) -> Dict:
|
|
45
|
+
"""
|
|
46
|
+
type_: ButtonCalendarTypeEnum = "DatePersian" | "DateGregorian"
|
|
47
|
+
"""
|
|
48
|
+
calendar = {
|
|
49
|
+
"title": title,
|
|
50
|
+
"type": type_,
|
|
51
|
+
}
|
|
52
|
+
if default_value:
|
|
53
|
+
calendar["default_value"] = default_value
|
|
54
|
+
if min_year:
|
|
55
|
+
calendar["min_year"] = min_year
|
|
56
|
+
if max_year:
|
|
57
|
+
calendar["max_year"] = max_year
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
"id": id,
|
|
61
|
+
"type": "Calendar",
|
|
62
|
+
"button_text": title,
|
|
63
|
+
"button_calendar": calendar
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
def button_number_picker(self, id: str, title: str, min_value: str, max_value: str,
|
|
67
|
+
default_value: Optional[str] = None) -> Dict:
|
|
68
|
+
picker = {
|
|
69
|
+
"title": title,
|
|
70
|
+
"min_value": min_value,
|
|
71
|
+
"max_value": max_value,
|
|
72
|
+
}
|
|
73
|
+
if default_value:
|
|
74
|
+
picker["default_value"] = default_value
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
"id": id,
|
|
78
|
+
"type": "NumberPicker",
|
|
79
|
+
"button_text": title,
|
|
80
|
+
"button_number_picker": picker
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
def button_string_picker(self, id: str, title: Optional[str], items: List[str],
|
|
84
|
+
default_value: Optional[str] = None) -> Dict:
|
|
85
|
+
picker = {
|
|
86
|
+
"items": items
|
|
87
|
+
}
|
|
88
|
+
if default_value:
|
|
89
|
+
picker["default_value"] = default_value
|
|
90
|
+
if title:
|
|
91
|
+
picker["title"] = title
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
"id": id,
|
|
95
|
+
"type": "StringPicker",
|
|
96
|
+
"button_text": title if title else "انتخاب",
|
|
97
|
+
"button_string_picker": picker
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
def button_location(self, id: str, type_: str, location_image_url: str,
|
|
101
|
+
default_pointer_location: Optional[Dict] = None,
|
|
102
|
+
default_map_location: Optional[Dict] = None,
|
|
103
|
+
title: Optional[str] = None) -> Dict:
|
|
104
|
+
"""
|
|
105
|
+
type_: ButtonLocationTypeEnum = "Picker" | "View"
|
|
106
|
+
location_image_url: str آدرس عکس دکمه موقعیت
|
|
107
|
+
default_pointer_location و default_map_location هر کدام دیکشنری Location (latitude, longitude)
|
|
108
|
+
"""
|
|
109
|
+
loc = {
|
|
110
|
+
"type": type_,
|
|
111
|
+
"location_image_url": location_image_url,
|
|
112
|
+
}
|
|
113
|
+
if default_pointer_location:
|
|
114
|
+
loc["default_pointer_location"] = default_pointer_location
|
|
115
|
+
if default_map_location:
|
|
116
|
+
loc["default_map_location"] = default_map_location
|
|
117
|
+
if title:
|
|
118
|
+
loc["title"] = title
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
"id": id,
|
|
122
|
+
"type": "Location",
|
|
123
|
+
"button_text": title if title else "موقعیت مکانی",
|
|
124
|
+
"button_location": loc
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
def button_textbox(self, id: str, title: Optional[str],
|
|
128
|
+
type_line: str, type_keypad: str,
|
|
129
|
+
place_holder: Optional[str] = None,
|
|
130
|
+
default_value: Optional[str] = None) -> Dict:
|
|
131
|
+
"""
|
|
132
|
+
type_line: ButtonTextboxTypeLineEnum = "SingleLine" | "MultiLine"
|
|
133
|
+
type_keypad: ButtonTextboxTypeKeypadEnum = "String" | "Number"
|
|
134
|
+
"""
|
|
135
|
+
textbox = {
|
|
136
|
+
"type_line": type_line,
|
|
137
|
+
"type_keypad": type_keypad
|
|
138
|
+
}
|
|
139
|
+
if place_holder:
|
|
140
|
+
textbox["place_holder"] = place_holder
|
|
141
|
+
if default_value:
|
|
142
|
+
textbox["default_value"] = default_value
|
|
143
|
+
if title:
|
|
144
|
+
textbox["title"] = title
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
"id": id,
|
|
148
|
+
"type": "Textbox",
|
|
149
|
+
"button_text": title if title else "متن",
|
|
150
|
+
"button_textbox": textbox
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
def button_payment(self, id: str, title: str, amount: int, description: Optional[str] = None) -> Dict:
|
|
154
|
+
"""
|
|
155
|
+
نمونهای ساده برای دکمه پرداخت (مقدار و توضیح دلخواه)
|
|
156
|
+
"""
|
|
157
|
+
payment = {
|
|
158
|
+
"title": title,
|
|
159
|
+
"amount": amount
|
|
160
|
+
}
|
|
161
|
+
if description:
|
|
162
|
+
payment["description"] = description
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
"id": id,
|
|
166
|
+
"type": "Payment",
|
|
167
|
+
"button_text": title,
|
|
168
|
+
"button_payment": payment
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
def button_camera_image(self, id: str, title: str) -> Dict:
|
|
172
|
+
return {
|
|
173
|
+
"id": id,
|
|
174
|
+
"type": "CameraImage",
|
|
175
|
+
"button_text": title
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
def button_camera_video(self, id: str, title: str) -> Dict:
|
|
179
|
+
return {
|
|
180
|
+
"id": id,
|
|
181
|
+
"type": "CameraVideo",
|
|
182
|
+
"button_text": title
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
def button_gallery_image(self, id: str, title: str) -> Dict:
|
|
186
|
+
return {
|
|
187
|
+
"id": id,
|
|
188
|
+
"type": "GalleryImage",
|
|
189
|
+
"button_text": title
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
def button_gallery_video(self, id: str, title: str) -> Dict:
|
|
193
|
+
return {
|
|
194
|
+
"id": id,
|
|
195
|
+
"type": "GalleryVideo",
|
|
196
|
+
"button_text": title
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
def button_file(self, id: str, title: str) -> Dict:
|
|
200
|
+
return {
|
|
201
|
+
"id": id,
|
|
202
|
+
"type": "File",
|
|
203
|
+
"button_text": title
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
def button_audio(self, id: str, title: str) -> Dict:
|
|
207
|
+
return {
|
|
208
|
+
"id": id,
|
|
209
|
+
"type": "Audio",
|
|
210
|
+
"button_text": title
|
|
211
|
+
}
|
|
13
212
|
|
|
14
|
-
def
|
|
213
|
+
def button_record_audio(self, id: str, title: str) -> Dict:
|
|
214
|
+
return {
|
|
215
|
+
"id": id,
|
|
216
|
+
"type": "RecordAudio",
|
|
217
|
+
"button_text": title
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
def button_my_phone_number(self, id: str, title: str) -> Dict:
|
|
221
|
+
return {
|
|
222
|
+
"id": id,
|
|
223
|
+
"type": "MyPhoneNumber",
|
|
224
|
+
"button_text": title
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
def button_my_location(self, id: str, title: str) -> Dict:
|
|
228
|
+
return {
|
|
229
|
+
"id": id,
|
|
230
|
+
"type": "MyLocation",
|
|
231
|
+
"button_text": title
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
def button_link(self, id: str, title: str, url: str) -> Dict:
|
|
235
|
+
return {
|
|
236
|
+
"id": id,
|
|
237
|
+
"type": "Link",
|
|
238
|
+
"button_text": title,
|
|
239
|
+
"url": url
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
def button_ask_my_phone_number(self, id: str, title: str) -> Dict:
|
|
243
|
+
return {
|
|
244
|
+
"id": id,
|
|
245
|
+
"type": "AskMyPhoneNumber",
|
|
246
|
+
"button_text": title
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
def button_ask_location(self, id: str, title: str) -> Dict:
|
|
250
|
+
return {
|
|
251
|
+
"id": id,
|
|
252
|
+
"type": "AskLocation",
|
|
253
|
+
"button_text": title
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
def button_barcode(self, id: str, title: str) -> Dict:
|
|
257
|
+
return {
|
|
258
|
+
"id": id,
|
|
259
|
+
"type": "Barcode",
|
|
260
|
+
"button_text": title
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
def build(self) -> Dict:
|
|
15
264
|
return {"rows": self.rows}
|
|
265
|
+
|
|
16
266
|
from typing import List, Dict, Optional
|
|
17
267
|
|
|
18
268
|
class ChatKeypadBuilder:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 4.3.4
|
|
4
4
|
Summary: A Python library for interacting with Rubika Bot API.
|
|
5
5
|
Home-page: https://github.com/Mahdy-Ahmadi/Rubka
|
|
6
6
|
Download-URL: https://github.com/Mahdy-Ahmadi/Rubka/archive/refs/tags/v0.1.0.tar.gz
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
rubka/__init__.py,sha256=3f4H6Uj1ylrfBYlTHmTvzZSvaPJsdNhCocyX3Bbvuv0,254
|
|
2
|
-
rubka/api.py,sha256=
|
|
2
|
+
rubka/api.py,sha256=2Oe7fZ6HkCBVt654RgpAgMQjUz8zRq5225cHJtBJGck,16104
|
|
3
|
+
rubka/button.py,sha256=4fMSZR7vUADxSmw1R3_pZ4dw5uMLZX5sOkwPPyNTBDE,8437
|
|
3
4
|
rubka/config.py,sha256=Bck59xkOiqioLv0GkQ1qPGnBXVctz1hKk6LT4h2EPx0,78
|
|
4
|
-
rubka/context.py,sha256=
|
|
5
|
+
rubka/context.py,sha256=BSb_O1PiB0QEPeY_u2F97oIVxg-3J9Re2iV1HWywz4M,12841
|
|
5
6
|
rubka/decorators.py,sha256=hGwUoE4q2ImrunJIGJ_kzGYYxQf1ueE0isadqraKEts,1157
|
|
6
7
|
rubka/exceptions.py,sha256=tujZt1XrhWaw-lmdeVadVceUptpw4XzNgE44sAAY0gs,90
|
|
7
8
|
rubka/jobs.py,sha256=GvLMLsVhcSEzRTgkvnPISPEBN71suW2xXI0hUaUZPTo,378
|
|
8
9
|
rubka/keyboards.py,sha256=7nr-dT2bQJVQnQ6RMWPTSjML6EEk6dsBx-4d8pab8xk,488
|
|
9
|
-
rubka/keypad.py,sha256=
|
|
10
|
+
rubka/keypad.py,sha256=yGsNt8W5HtUFBzVF1m_p7GySlu1hwIcSvXZ4BTdrlvg,9558
|
|
10
11
|
rubka/logger.py,sha256=J2I6NiK1z32lrAzC4H1Et6WPMBXxXGCVUsW4jgcAofs,289
|
|
11
12
|
rubka/utils.py,sha256=XUQUZxQt9J2f0X5hmAH_MH1kibTAfdT1T4AaBkBhBBs,148
|
|
12
13
|
rubka/adaptorrubka/__init__.py,sha256=6o2tCXnVeES7nx-LjnzsuMqjKcWIm9qwKficLE54s-U,83
|
|
@@ -30,7 +31,7 @@ rubka/adaptorrubka/types/socket/message.py,sha256=0WgLMZh4eow8Zn7AiSX4C3GZjQTkIg
|
|
|
30
31
|
rubka/adaptorrubka/utils/__init__.py,sha256=OgCFkXdNFh379quNwIVOAWY2NP5cIOxU5gDRRALTk4o,54
|
|
31
32
|
rubka/adaptorrubka/utils/configs.py,sha256=nMUEOJh1NqDJsf9W9PurkN_DLYjO6kKPMm923i4Jj_A,492
|
|
32
33
|
rubka/adaptorrubka/utils/utils.py,sha256=5-LioLNYX_TIbQGDeT50j7Sg9nAWH2LJUUs-iEXpsUY,8816
|
|
33
|
-
rubka-3.
|
|
34
|
-
rubka-3.
|
|
35
|
-
rubka-3.
|
|
36
|
-
rubka-3.
|
|
34
|
+
rubka-4.3.4.dist-info/METADATA,sha256=qtXGjYKe_MxSogYEP_j32a8xHPXViqVkmSdZLB5atNA,8168
|
|
35
|
+
rubka-4.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
36
|
+
rubka-4.3.4.dist-info/top_level.txt,sha256=vy2A4lot11cRMdQS-F4HDCIXL3JK8RKfu7HMDkezJW4,6
|
|
37
|
+
rubka-4.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|