Rubka 5.2.0__py3-none-any.whl → 6.4.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 +410 -20
- rubka/asynco.py +402 -33
- rubka/button.py +32 -1
- rubka/context.py +4 -0
- rubka/update.py +489 -0
- {rubka-5.2.0.dist-info → rubka-6.4.4.dist-info}/METADATA +1 -1
- {rubka-5.2.0.dist-info → rubka-6.4.4.dist-info}/RECORD +9 -8
- {rubka-5.2.0.dist-info → rubka-6.4.4.dist-info}/WHEEL +0 -0
- {rubka-5.2.0.dist-info → rubka-6.4.4.dist-info}/top_level.txt +0 -0
rubka/asynco.py
CHANGED
|
@@ -190,6 +190,324 @@ class Robot:
|
|
|
190
190
|
"""Check if the bot token is valid."""
|
|
191
191
|
if (await self.get_me())['status'] != "OK":
|
|
192
192
|
raise InvalidTokenError("The provided bot token is invalid or expired.")
|
|
193
|
+
from typing import Callable, Any, Optional, List
|
|
194
|
+
|
|
195
|
+
def on_message_private(
|
|
196
|
+
self,
|
|
197
|
+
chat_id: Optional[Union[str, List[str]]] = None,
|
|
198
|
+
commands: Optional[List[str]] = None,
|
|
199
|
+
filters: Optional[Callable[[Message], bool]] = None,
|
|
200
|
+
sender_id: Optional[Union[str, List[str]]] = None,
|
|
201
|
+
sender_type: Optional[str] = None,
|
|
202
|
+
allow_forwarded: bool = True,
|
|
203
|
+
allow_files: bool = True,
|
|
204
|
+
allow_stickers: bool = True,
|
|
205
|
+
allow_polls: bool = True,
|
|
206
|
+
allow_contacts: bool = True,
|
|
207
|
+
allow_locations: bool = True,
|
|
208
|
+
min_text_length: Optional[int] = None,
|
|
209
|
+
max_text_length: Optional[int] = None,
|
|
210
|
+
contains: Optional[str] = None,
|
|
211
|
+
startswith: Optional[str] = None,
|
|
212
|
+
endswith: Optional[str] = None,
|
|
213
|
+
case_sensitive: bool = False
|
|
214
|
+
):
|
|
215
|
+
"""
|
|
216
|
+
Advanced decorator for handling only private messages with extended filters.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
220
|
+
async def wrapper(bot, message: Message):
|
|
221
|
+
|
|
222
|
+
if not message.is_private:
|
|
223
|
+
return
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
if chat_id:
|
|
227
|
+
if isinstance(chat_id, str) and message.chat_id != chat_id:
|
|
228
|
+
return
|
|
229
|
+
if isinstance(chat_id, list) and message.chat_id not in chat_id:
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
if sender_id:
|
|
234
|
+
if isinstance(sender_id, str) and message.sender_id != sender_id:
|
|
235
|
+
return
|
|
236
|
+
if isinstance(sender_id, list) and message.sender_id not in sender_id:
|
|
237
|
+
return
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
if sender_type and message.sender_type != sender_type:
|
|
241
|
+
return
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
if not allow_forwarded and message.forwarded_from:
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
if not allow_files and message.file:
|
|
249
|
+
return
|
|
250
|
+
if not allow_stickers and message.sticker:
|
|
251
|
+
return
|
|
252
|
+
if not allow_polls and message.poll:
|
|
253
|
+
return
|
|
254
|
+
if not allow_contacts and message.contact_message:
|
|
255
|
+
return
|
|
256
|
+
if not allow_locations and (message.location or message.live_location):
|
|
257
|
+
return
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if message.text:
|
|
261
|
+
text = message.text if case_sensitive else message.text.lower()
|
|
262
|
+
if min_text_length and len(message.text) < min_text_length:
|
|
263
|
+
return
|
|
264
|
+
if max_text_length and len(message.text) > max_text_length:
|
|
265
|
+
return
|
|
266
|
+
if contains and (contains if case_sensitive else contains.lower()) not in text:
|
|
267
|
+
return
|
|
268
|
+
if startswith and not text.startswith(startswith if case_sensitive else startswith.lower()):
|
|
269
|
+
return
|
|
270
|
+
if endswith and not text.endswith(endswith if case_sensitive else endswith.lower()):
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
if commands:
|
|
275
|
+
if not message.text:
|
|
276
|
+
return
|
|
277
|
+
parts = message.text.strip().split()
|
|
278
|
+
cmd = parts[0].lstrip("/")
|
|
279
|
+
if cmd not in commands:
|
|
280
|
+
return
|
|
281
|
+
message.args = parts[1:]
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
if filters and not filters(message):
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
return await func(bot, message)
|
|
288
|
+
|
|
289
|
+
self._message_handlers.append({
|
|
290
|
+
"func": wrapper,
|
|
291
|
+
"filters": filters,
|
|
292
|
+
"commands": commands,
|
|
293
|
+
"chat_id": chat_id,
|
|
294
|
+
"private_only": True,
|
|
295
|
+
"sender_id": sender_id,
|
|
296
|
+
"sender_type": sender_type
|
|
297
|
+
})
|
|
298
|
+
return wrapper
|
|
299
|
+
return decorator
|
|
300
|
+
def on_message_channel(
|
|
301
|
+
self,
|
|
302
|
+
chat_id: Optional[Union[str, List[str]]] = None,
|
|
303
|
+
commands: Optional[List[str]] = None,
|
|
304
|
+
filters: Optional[Callable[[Message], bool]] = None,
|
|
305
|
+
sender_id: Optional[Union[str, List[str]]] = None,
|
|
306
|
+
sender_type: Optional[str] = None,
|
|
307
|
+
allow_forwarded: bool = True,
|
|
308
|
+
allow_files: bool = True,
|
|
309
|
+
allow_stickers: bool = True,
|
|
310
|
+
allow_polls: bool = True,
|
|
311
|
+
allow_contacts: bool = True,
|
|
312
|
+
allow_locations: bool = True,
|
|
313
|
+
min_text_length: Optional[int] = None,
|
|
314
|
+
max_text_length: Optional[int] = None,
|
|
315
|
+
contains: Optional[str] = None,
|
|
316
|
+
startswith: Optional[str] = None,
|
|
317
|
+
endswith: Optional[str] = None,
|
|
318
|
+
case_sensitive: bool = False
|
|
319
|
+
):
|
|
320
|
+
"""
|
|
321
|
+
Advanced decorator for handling only channel messages with extended filters.
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
325
|
+
async def wrapper(bot, message: Message):
|
|
326
|
+
|
|
327
|
+
if not message.is_channel:
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
if chat_id:
|
|
332
|
+
if isinstance(chat_id, str) and message.chat_id != chat_id:
|
|
333
|
+
return
|
|
334
|
+
if isinstance(chat_id, list) and message.chat_id not in chat_id:
|
|
335
|
+
return
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
if sender_id:
|
|
339
|
+
if isinstance(sender_id, str) and message.sender_id != sender_id:
|
|
340
|
+
return
|
|
341
|
+
if isinstance(sender_id, list) and message.sender_id not in sender_id:
|
|
342
|
+
return
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
if sender_type and message.sender_type != sender_type:
|
|
346
|
+
return
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
if not allow_forwarded and message.forwarded_from:
|
|
350
|
+
return
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
if not allow_files and message.file:
|
|
354
|
+
return
|
|
355
|
+
if not allow_stickers and message.sticker:
|
|
356
|
+
return
|
|
357
|
+
if not allow_polls and message.poll:
|
|
358
|
+
return
|
|
359
|
+
if not allow_contacts and message.contact_message:
|
|
360
|
+
return
|
|
361
|
+
if not allow_locations and (message.location or message.live_location):
|
|
362
|
+
return
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
if message.text:
|
|
366
|
+
text = message.text if case_sensitive else message.text.lower()
|
|
367
|
+
if min_text_length and len(message.text) < min_text_length:
|
|
368
|
+
return
|
|
369
|
+
if max_text_length and len(message.text) > max_text_length:
|
|
370
|
+
return
|
|
371
|
+
if contains and (contains if case_sensitive else contains.lower()) not in text:
|
|
372
|
+
return
|
|
373
|
+
if startswith and not text.startswith(startswith if case_sensitive else startswith.lower()):
|
|
374
|
+
return
|
|
375
|
+
if endswith and not text.endswith(endswith if case_sensitive else endswith.lower()):
|
|
376
|
+
return
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
if commands:
|
|
380
|
+
if not message.text:
|
|
381
|
+
return
|
|
382
|
+
parts = message.text.strip().split()
|
|
383
|
+
cmd = parts[0].lstrip("/")
|
|
384
|
+
if cmd not in commands:
|
|
385
|
+
return
|
|
386
|
+
message.args = parts[1:]
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
if filters and not filters(message):
|
|
390
|
+
return
|
|
391
|
+
|
|
392
|
+
return await func(bot, message)
|
|
393
|
+
|
|
394
|
+
self._message_handlers.append({
|
|
395
|
+
"func": wrapper,
|
|
396
|
+
"filters": filters,
|
|
397
|
+
"commands": commands,
|
|
398
|
+
"chat_id": chat_id,
|
|
399
|
+
"group_only": True,
|
|
400
|
+
"sender_id": sender_id,
|
|
401
|
+
"sender_type": sender_type
|
|
402
|
+
})
|
|
403
|
+
return wrapper
|
|
404
|
+
return decorator
|
|
405
|
+
def on_message_group(
|
|
406
|
+
self,
|
|
407
|
+
chat_id: Optional[Union[str, List[str]]] = None,
|
|
408
|
+
commands: Optional[List[str]] = None,
|
|
409
|
+
filters: Optional[Callable[[Message], bool]] = None,
|
|
410
|
+
sender_id: Optional[Union[str, List[str]]] = None,
|
|
411
|
+
sender_type: Optional[str] = None,
|
|
412
|
+
allow_forwarded: bool = True,
|
|
413
|
+
allow_files: bool = True,
|
|
414
|
+
allow_stickers: bool = True,
|
|
415
|
+
allow_polls: bool = True,
|
|
416
|
+
allow_contacts: bool = True,
|
|
417
|
+
allow_locations: bool = True,
|
|
418
|
+
min_text_length: Optional[int] = None,
|
|
419
|
+
max_text_length: Optional[int] = None,
|
|
420
|
+
contains: Optional[str] = None,
|
|
421
|
+
startswith: Optional[str] = None,
|
|
422
|
+
endswith: Optional[str] = None,
|
|
423
|
+
case_sensitive: bool = False
|
|
424
|
+
):
|
|
425
|
+
"""
|
|
426
|
+
Advanced decorator for handling only group messages with extended filters.
|
|
427
|
+
"""
|
|
428
|
+
|
|
429
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
430
|
+
async def wrapper(bot, message: Message):
|
|
431
|
+
|
|
432
|
+
if not message.is_group:
|
|
433
|
+
return
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
if chat_id:
|
|
437
|
+
if isinstance(chat_id, str) and message.chat_id != chat_id:
|
|
438
|
+
return
|
|
439
|
+
if isinstance(chat_id, list) and message.chat_id not in chat_id:
|
|
440
|
+
return
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
if sender_id:
|
|
444
|
+
if isinstance(sender_id, str) and message.sender_id != sender_id:
|
|
445
|
+
return
|
|
446
|
+
if isinstance(sender_id, list) and message.sender_id not in sender_id:
|
|
447
|
+
return
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
if sender_type and message.sender_type != sender_type:
|
|
451
|
+
return
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
if not allow_forwarded and message.forwarded_from:
|
|
455
|
+
return
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
if not allow_files and message.file:
|
|
459
|
+
return
|
|
460
|
+
if not allow_stickers and message.sticker:
|
|
461
|
+
return
|
|
462
|
+
if not allow_polls and message.poll:
|
|
463
|
+
return
|
|
464
|
+
if not allow_contacts and message.contact_message:
|
|
465
|
+
return
|
|
466
|
+
if not allow_locations and (message.location or message.live_location):
|
|
467
|
+
return
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
if message.text:
|
|
471
|
+
text = message.text if case_sensitive else message.text.lower()
|
|
472
|
+
if min_text_length and len(message.text) < min_text_length:
|
|
473
|
+
return
|
|
474
|
+
if max_text_length and len(message.text) > max_text_length:
|
|
475
|
+
return
|
|
476
|
+
if contains and (contains if case_sensitive else contains.lower()) not in text:
|
|
477
|
+
return
|
|
478
|
+
if startswith and not text.startswith(startswith if case_sensitive else startswith.lower()):
|
|
479
|
+
return
|
|
480
|
+
if endswith and not text.endswith(endswith if case_sensitive else endswith.lower()):
|
|
481
|
+
return
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
if commands:
|
|
485
|
+
if not message.text:
|
|
486
|
+
return
|
|
487
|
+
parts = message.text.strip().split()
|
|
488
|
+
cmd = parts[0].lstrip("/")
|
|
489
|
+
if cmd not in commands:
|
|
490
|
+
return
|
|
491
|
+
message.args = parts[1:]
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
if filters and not filters(message):
|
|
495
|
+
return
|
|
496
|
+
|
|
497
|
+
return await func(bot, message)
|
|
498
|
+
|
|
499
|
+
self._message_handlers.append({
|
|
500
|
+
"func": wrapper,
|
|
501
|
+
"filters": filters,
|
|
502
|
+
"commands": commands,
|
|
503
|
+
"chat_id": chat_id,
|
|
504
|
+
"group_only": True,
|
|
505
|
+
"sender_id": sender_id,
|
|
506
|
+
"sender_type": sender_type
|
|
507
|
+
})
|
|
508
|
+
return wrapper
|
|
509
|
+
return decorator
|
|
510
|
+
|
|
193
511
|
def on_message(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
194
512
|
def decorator(func: Callable[[Any, Message], None]):
|
|
195
513
|
self._message_handlers.append({
|
|
@@ -219,6 +537,16 @@ class Robot:
|
|
|
219
537
|
})
|
|
220
538
|
return func
|
|
221
539
|
return decorator
|
|
540
|
+
def on_callback_query(self, button_id: Optional[str] = None):
|
|
541
|
+
def decorator(func: Callable[[Any, Union[Message, InlineMessage]], None]):
|
|
542
|
+
if not hasattr(self, "_callback_handlers"):
|
|
543
|
+
self._callback_handlers = []
|
|
544
|
+
self._callback_handlers.append({
|
|
545
|
+
"func": func,
|
|
546
|
+
"button_id": button_id
|
|
547
|
+
})
|
|
548
|
+
return func
|
|
549
|
+
return decorator
|
|
222
550
|
def callback_query_handler(self, button_id: Optional[str] = None):
|
|
223
551
|
def decorator(func: Callable[[Any, Message], None]):
|
|
224
552
|
if not hasattr(self, "_callback_handlers"):
|
|
@@ -349,12 +677,12 @@ class Robot:
|
|
|
349
677
|
|
|
350
678
|
if not handler_info["commands"] and not handler_info["filters"]:
|
|
351
679
|
asyncio.create_task(handler_info["func"](self, context))
|
|
352
|
-
|
|
680
|
+
continue
|
|
353
681
|
|
|
354
682
|
|
|
355
683
|
if handler_info["commands"] or handler_info["filters"]:
|
|
356
|
-
asyncio.create_task(handler_info["func"](self, context))
|
|
357
|
-
|
|
684
|
+
asyncio.create_task(handler_info["func"](self, context))#jaq
|
|
685
|
+
continue
|
|
358
686
|
|
|
359
687
|
async def get_updates(self, offset_id: Optional[str] = None, limit: Optional[int] = None) -> Dict[str, Any]:
|
|
360
688
|
data = {}
|
|
@@ -1014,49 +1342,90 @@ class Robot:
|
|
|
1014
1342
|
return user_id in member_guids
|
|
1015
1343
|
return False
|
|
1016
1344
|
async def send_button_join(
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1345
|
+
self,
|
|
1346
|
+
chat_id,
|
|
1347
|
+
title_button : Union[str, list],
|
|
1348
|
+
username : Union[str, list],
|
|
1349
|
+
text,
|
|
1350
|
+
reply_to_message_id=None,
|
|
1351
|
+
id="None"):
|
|
1024
1352
|
from .button import InlineBuilder
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1353
|
+
builder = InlineBuilder()
|
|
1354
|
+
|
|
1355
|
+
if isinstance(username, (list, tuple)) and isinstance(title_button, (list, tuple)):
|
|
1356
|
+
for t, u in zip(title_button, username):
|
|
1357
|
+
builder = builder.row(
|
|
1358
|
+
InlineBuilder().button_join_channel(
|
|
1359
|
+
text=t,
|
|
1360
|
+
id=id,
|
|
1361
|
+
username=u
|
|
1362
|
+
)
|
|
1363
|
+
)
|
|
1364
|
+
elif isinstance(username, (list, tuple)) and isinstance(title_button, str):
|
|
1365
|
+
for u in username:
|
|
1366
|
+
builder = builder.row(
|
|
1367
|
+
InlineBuilder().button_join_channel(
|
|
1368
|
+
text=title_button,
|
|
1369
|
+
id=id,
|
|
1370
|
+
username=u
|
|
1371
|
+
)
|
|
1372
|
+
)
|
|
1373
|
+
else:
|
|
1374
|
+
builder = builder.row(
|
|
1375
|
+
InlineBuilder().button_join_channel(
|
|
1032
1376
|
text=title_button,
|
|
1033
1377
|
id=id,
|
|
1034
1378
|
username=username
|
|
1035
1379
|
)
|
|
1036
|
-
)
|
|
1380
|
+
)
|
|
1381
|
+
return await self.send_message(
|
|
1382
|
+
chat_id=chat_id,
|
|
1383
|
+
text=text,
|
|
1384
|
+
inline_keypad=builder.build(),
|
|
1037
1385
|
reply_to_message_id=reply_to_message_id
|
|
1038
1386
|
)
|
|
1039
1387
|
async def send_button_link(
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1388
|
+
self,
|
|
1389
|
+
chat_id,
|
|
1390
|
+
title_button: Union[str, list],
|
|
1391
|
+
url: Union[str, list],
|
|
1392
|
+
text,
|
|
1393
|
+
reply_to_message_id=None,
|
|
1394
|
+
id="None"
|
|
1395
|
+
):
|
|
1047
1396
|
from .button import InlineBuilder
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1397
|
+
builder = InlineBuilder()
|
|
1398
|
+
if isinstance(url, (list, tuple)) and isinstance(title_button, (list, tuple)):
|
|
1399
|
+
for t, u in zip(title_button, url):
|
|
1400
|
+
builder = builder.row(
|
|
1401
|
+
InlineBuilder().button_url_link(
|
|
1402
|
+
text=t,
|
|
1403
|
+
id=id,
|
|
1404
|
+
url=u
|
|
1405
|
+
)
|
|
1406
|
+
)
|
|
1407
|
+
elif isinstance(url, (list, tuple)) and isinstance(title_button, str):
|
|
1408
|
+
for u in url:
|
|
1409
|
+
builder = builder.row(
|
|
1410
|
+
InlineBuilder().button_url_link(
|
|
1411
|
+
text=title_button,
|
|
1412
|
+
id=id,
|
|
1413
|
+
url=u
|
|
1414
|
+
)
|
|
1415
|
+
)
|
|
1416
|
+
else:
|
|
1417
|
+
builder = builder.row(
|
|
1418
|
+
InlineBuilder().button_url_link(
|
|
1055
1419
|
text=title_button,
|
|
1056
1420
|
id=id,
|
|
1057
1421
|
url=url
|
|
1058
1422
|
)
|
|
1059
|
-
)
|
|
1423
|
+
)
|
|
1424
|
+
|
|
1425
|
+
return await self.send_message(
|
|
1426
|
+
chat_id=chat_id,
|
|
1427
|
+
text=text,
|
|
1428
|
+
inline_keypad=builder.build(),
|
|
1060
1429
|
reply_to_message_id=reply_to_message_id
|
|
1061
1430
|
)
|
|
1062
1431
|
|
rubka/button.py
CHANGED
|
@@ -370,4 +370,35 @@ class InlineBuilder:
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
def build(self) -> Dict:
|
|
373
|
-
return {"rows": self.rows}
|
|
373
|
+
return {"rows": self.rows}
|
|
374
|
+
class ChatKeypadBuilder:
|
|
375
|
+
def __init__(self):
|
|
376
|
+
self.rows: List[Dict[str, List[Dict[str, str]]]] = []
|
|
377
|
+
|
|
378
|
+
def row(self, *buttons: Dict[str, str]) -> "ChatKeypadBuilder":
|
|
379
|
+
"""
|
|
380
|
+
یک ردیف دکمه به کیپد اضافه میکند.
|
|
381
|
+
ورودی: چند دیکشنری که نماینده دکمهها هستند.
|
|
382
|
+
"""
|
|
383
|
+
self.rows.append({"buttons": list(buttons)})
|
|
384
|
+
return self
|
|
385
|
+
|
|
386
|
+
def button(self, id: str, text: str, type: str = "Simple") -> Dict[str, str]:
|
|
387
|
+
"""
|
|
388
|
+
دیکشنری یک دکمه میسازد.
|
|
389
|
+
"""
|
|
390
|
+
return {"id": id, "type": type, "button_text": text}
|
|
391
|
+
|
|
392
|
+
def build(
|
|
393
|
+
self,
|
|
394
|
+
resize_keyboard: bool = True,
|
|
395
|
+
on_time_keyboard: bool = False
|
|
396
|
+
) -> Dict[str, object]:
|
|
397
|
+
"""
|
|
398
|
+
ساختار نهایی chat_keypad را میسازد.
|
|
399
|
+
"""
|
|
400
|
+
return {
|
|
401
|
+
"rows": self.rows,
|
|
402
|
+
"resize_keyboard": resize_keyboard,
|
|
403
|
+
"on_time_keyboard": on_time_keyboard
|
|
404
|
+
}
|
rubka/context.py
CHANGED
|
@@ -199,6 +199,10 @@ class Message:
|
|
|
199
199
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
200
200
|
self.sender_type: str = self.raw_data.get("sender_type")
|
|
201
201
|
self.args = []
|
|
202
|
+
self.is_user = self.chat_id.startswith("b")
|
|
203
|
+
self.is_private = self.chat_id.startswith("b")
|
|
204
|
+
self.is_group = self.chat_id.startswith("g")
|
|
205
|
+
self.is_channel = self.chat_id.startswith("c")
|
|
202
206
|
self.reply_to_message_id: Optional[str] = self.raw_data.get("reply_to_message_id")
|
|
203
207
|
self.forwarded_from = ForwardedFrom(self.raw_data["forwarded_from"]) if "forwarded_from" in self.raw_data else None
|
|
204
208
|
self.file = File(self.raw_data["file"]) if "file" in self.raw_data else None
|