Rubka 6.4.6__tar.gz → 6.5.2__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.
- {rubka-6.4.6 → rubka-6.5.2}/PKG-INFO +1 -1
- {rubka-6.4.6 → rubka-6.5.2}/Rubka.egg-info/PKG-INFO +1 -1
- {rubka-6.4.6 → rubka-6.5.2}/Rubka.egg-info/SOURCES.txt +1 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/api.py +180 -3
- {rubka-6.4.6 → rubka-6.5.2}/rubka/asynco.py +169 -22
- {rubka-6.4.6 → rubka-6.5.2}/rubka/context.py +16 -2
- rubka-6.5.2/rubka/filters.py +317 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/update.py +16 -2
- {rubka-6.4.6 → rubka-6.5.2}/setup.py +1 -1
- {rubka-6.4.6 → rubka-6.5.2}/README.md +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/Rubka.egg-info/dependency_links.txt +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/Rubka.egg-info/requires.txt +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/Rubka.egg-info/top_level.txt +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/client/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/client/client.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/crypto/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/crypto/crypto.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/enums.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/exceptions.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/methods/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/methods/methods.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/network/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/network/helper.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/network/network.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/network/socket.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/sessions/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/sessions/sessions.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/types/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/types/socket/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/types/socket/message.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/utils/__init__.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/utils/configs.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/adaptorrubka/utils/utils.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/button.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/config.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/decorators.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/exceptions.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/jobs.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/keyboards.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/keypad.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/logger.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/rubino.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/rubka/utils.py +0 -0
- {rubka-6.4.6 → rubka-6.5.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.2
|
|
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/blob/main/project_library.zip
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Rubka
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.2
|
|
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/blob/main/project_library.zip
|
|
@@ -3,6 +3,7 @@ from typing import List, Optional, Dict, Any, Literal
|
|
|
3
3
|
from .exceptions import APIRequestError
|
|
4
4
|
from .adaptorrubka import Client as Client_get
|
|
5
5
|
from .logger import logger
|
|
6
|
+
from . import filters
|
|
6
7
|
from typing import Callable
|
|
7
8
|
from .context import Message,InlineMessage
|
|
8
9
|
from typing import Optional, Union, Literal, Dict, Any
|
|
@@ -489,15 +490,191 @@ class Robot:
|
|
|
489
490
|
|
|
490
491
|
return decorator
|
|
491
492
|
|
|
492
|
-
def on_message(
|
|
493
|
+
def on_message(
|
|
494
|
+
self,
|
|
495
|
+
filters: Optional[Callable[[Message], bool]] = None,
|
|
496
|
+
commands: Optional[List[str]] = None
|
|
497
|
+
):
|
|
493
498
|
def decorator(func: Callable[[Any, Message], None]):
|
|
499
|
+
def wrapper(bot, message: Message):
|
|
500
|
+
if filters and not filters(message):
|
|
501
|
+
return
|
|
502
|
+
if commands:
|
|
503
|
+
if not getattr(message, "is_command", False):
|
|
504
|
+
return
|
|
505
|
+
cmd = message.text.split()[0].lstrip("/") if message.text else ""
|
|
506
|
+
if cmd not in commands:
|
|
507
|
+
return
|
|
508
|
+
return func(bot, message)
|
|
494
509
|
self._message_handlers.append({
|
|
495
|
-
"func":
|
|
510
|
+
"func": wrapper,
|
|
496
511
|
"filters": filters,
|
|
497
512
|
"commands": commands
|
|
498
513
|
})
|
|
499
|
-
return
|
|
514
|
+
return wrapper
|
|
515
|
+
return decorator
|
|
516
|
+
def on_message_file(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
517
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
518
|
+
def wrapper(bot, message: Message):
|
|
519
|
+
if not message.file:
|
|
520
|
+
return
|
|
521
|
+
if filters and not filters(message):
|
|
522
|
+
return
|
|
523
|
+
return func(bot, message)
|
|
524
|
+
|
|
525
|
+
self._message_handlers.append({
|
|
526
|
+
"func": wrapper,
|
|
527
|
+
"filters": filters,
|
|
528
|
+
"file_only": True,
|
|
529
|
+
"commands":commands
|
|
530
|
+
})
|
|
531
|
+
return wrapper
|
|
532
|
+
return decorator
|
|
533
|
+
|
|
534
|
+
def on_message_forwarded(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
535
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
536
|
+
def wrapper(bot, message: Message):
|
|
537
|
+
if not message.is_forwarded:
|
|
538
|
+
return
|
|
539
|
+
if filters and not filters(message):
|
|
540
|
+
return
|
|
541
|
+
return func(bot, message)
|
|
542
|
+
|
|
543
|
+
self._message_handlers.append({
|
|
544
|
+
"func": wrapper,
|
|
545
|
+
"filters": filters,
|
|
546
|
+
"forwarded_only": True,
|
|
547
|
+
"commands":commands
|
|
548
|
+
})
|
|
549
|
+
return wrapper
|
|
550
|
+
return decorator
|
|
551
|
+
|
|
552
|
+
def on_message_reply(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
553
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
554
|
+
def wrapper(bot, message: Message):
|
|
555
|
+
if not message.is_reply:
|
|
556
|
+
return
|
|
557
|
+
if filters and not filters(message):
|
|
558
|
+
return
|
|
559
|
+
return func(bot, message)
|
|
560
|
+
|
|
561
|
+
self._message_handlers.append({
|
|
562
|
+
"func": wrapper,
|
|
563
|
+
"filters": filters,
|
|
564
|
+
"reply_only": True,
|
|
565
|
+
"commands":commands
|
|
566
|
+
})
|
|
567
|
+
return wrapper
|
|
568
|
+
return decorator
|
|
569
|
+
|
|
570
|
+
def on_message_text(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
571
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
572
|
+
def wrapper(bot, message: Message):
|
|
573
|
+
if not message.text:
|
|
574
|
+
return
|
|
575
|
+
if filters and not filters(message):
|
|
576
|
+
return
|
|
577
|
+
return func(bot, message)
|
|
578
|
+
|
|
579
|
+
self._message_handlers.append({
|
|
580
|
+
"func": wrapper,
|
|
581
|
+
"filters": filters,
|
|
582
|
+
"text_only": True,
|
|
583
|
+
"commands":commands
|
|
584
|
+
})
|
|
585
|
+
return wrapper
|
|
586
|
+
return decorator
|
|
587
|
+
|
|
588
|
+
def on_message_media(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
589
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
590
|
+
def wrapper(bot, message: Message):
|
|
591
|
+
if not message.is_media:
|
|
592
|
+
return
|
|
593
|
+
if filters and not filters(message):
|
|
594
|
+
return
|
|
595
|
+
return func(bot, message)
|
|
596
|
+
|
|
597
|
+
self._message_handlers.append({
|
|
598
|
+
"func": wrapper,
|
|
599
|
+
"filters": filters,
|
|
600
|
+
"media_only": True,
|
|
601
|
+
"commands":commands
|
|
602
|
+
})
|
|
603
|
+
return wrapper
|
|
604
|
+
return decorator
|
|
605
|
+
|
|
606
|
+
def on_message_sticker(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
607
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
608
|
+
def wrapper(bot, message: Message):
|
|
609
|
+
if not message.sticker:
|
|
610
|
+
return
|
|
611
|
+
if filters and not filters(message):
|
|
612
|
+
return
|
|
613
|
+
return func(bot, message)
|
|
614
|
+
|
|
615
|
+
self._message_handlers.append({
|
|
616
|
+
"func": wrapper,
|
|
617
|
+
"filters": filters,
|
|
618
|
+
"sticker_only": True,
|
|
619
|
+
"commands":commands
|
|
620
|
+
})
|
|
621
|
+
return wrapper
|
|
622
|
+
return decorator
|
|
623
|
+
|
|
624
|
+
def on_message_contact(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
625
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
626
|
+
def wrapper(bot, message: Message):
|
|
627
|
+
if not message.is_contact:
|
|
628
|
+
return
|
|
629
|
+
if filters and not filters(message):
|
|
630
|
+
return
|
|
631
|
+
return func(bot, message)
|
|
632
|
+
|
|
633
|
+
self._message_handlers.append({
|
|
634
|
+
"func": wrapper,
|
|
635
|
+
"filters": filters,
|
|
636
|
+
"contact_only": True,
|
|
637
|
+
"commands":commands
|
|
638
|
+
})
|
|
639
|
+
return wrapper
|
|
500
640
|
return decorator
|
|
641
|
+
|
|
642
|
+
def on_message_location(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
643
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
644
|
+
def wrapper(bot, message: Message):
|
|
645
|
+
if not message.is_location:
|
|
646
|
+
return
|
|
647
|
+
if filters and not filters(message):
|
|
648
|
+
return
|
|
649
|
+
return func(bot, message)
|
|
650
|
+
|
|
651
|
+
self._message_handlers.append({
|
|
652
|
+
"func": wrapper,
|
|
653
|
+
"filters": filters,
|
|
654
|
+
"location_only": True,
|
|
655
|
+
"commands":commands
|
|
656
|
+
})
|
|
657
|
+
return wrapper
|
|
658
|
+
return decorator
|
|
659
|
+
|
|
660
|
+
def on_message_poll(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
661
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
662
|
+
def wrapper(bot, message: Message):
|
|
663
|
+
if not message.is_poll:
|
|
664
|
+
return
|
|
665
|
+
if filters and not filters(message):
|
|
666
|
+
return
|
|
667
|
+
return func(bot, message)
|
|
668
|
+
|
|
669
|
+
self._message_handlers.append({
|
|
670
|
+
"func": wrapper,
|
|
671
|
+
"filters": filters,
|
|
672
|
+
"poll_only": True,
|
|
673
|
+
"commands":commands
|
|
674
|
+
})
|
|
675
|
+
return wrapper
|
|
676
|
+
return decorator
|
|
677
|
+
|
|
501
678
|
def message_handler(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
502
679
|
def decorator(func: Callable[[Any, Message], None]):
|
|
503
680
|
self._message_handlers.append({
|
|
@@ -5,6 +5,7 @@ from typing import List, Optional, Dict, Any, Literal, Callable, Union
|
|
|
5
5
|
from .exceptions import APIRequestError
|
|
6
6
|
from .adaptorrubka import Client as Client_get
|
|
7
7
|
from .logger import logger
|
|
8
|
+
from . import filters
|
|
8
9
|
try:
|
|
9
10
|
from .context import Message, InlineMessage
|
|
10
11
|
except (ImportError, ModuleNotFoundError):
|
|
@@ -218,6 +219,9 @@ class Robot:
|
|
|
218
219
|
raise InvalidTokenError("The provided bot token is invalid or expired.")
|
|
219
220
|
from typing import Callable, Any, Optional, List
|
|
220
221
|
|
|
222
|
+
|
|
223
|
+
#decorator#
|
|
224
|
+
|
|
221
225
|
def on_message_private(
|
|
222
226
|
self,
|
|
223
227
|
chat_id: Optional[Union[str, List[str]]] = None,
|
|
@@ -247,30 +251,20 @@ class Robot:
|
|
|
247
251
|
|
|
248
252
|
if not message.is_private:
|
|
249
253
|
return
|
|
250
|
-
|
|
251
|
-
|
|
252
254
|
if chat_id:
|
|
253
255
|
if isinstance(chat_id, str) and message.chat_id != chat_id:
|
|
254
256
|
return
|
|
255
257
|
if isinstance(chat_id, list) and message.chat_id not in chat_id:
|
|
256
258
|
return
|
|
257
|
-
|
|
258
|
-
|
|
259
259
|
if sender_id:
|
|
260
260
|
if isinstance(sender_id, str) and message.sender_id != sender_id:
|
|
261
261
|
return
|
|
262
262
|
if isinstance(sender_id, list) and message.sender_id not in sender_id:
|
|
263
263
|
return
|
|
264
|
-
|
|
265
|
-
|
|
266
264
|
if sender_type and message.sender_type != sender_type:
|
|
267
265
|
return
|
|
268
|
-
|
|
269
|
-
|
|
270
266
|
if not allow_forwarded and message.forwarded_from:
|
|
271
267
|
return
|
|
272
|
-
|
|
273
|
-
|
|
274
268
|
if not allow_files and message.file:
|
|
275
269
|
return
|
|
276
270
|
if not allow_stickers and message.sticker:
|
|
@@ -534,14 +528,162 @@ class Robot:
|
|
|
534
528
|
return wrapper
|
|
535
529
|
return decorator
|
|
536
530
|
|
|
537
|
-
def on_message(
|
|
531
|
+
def on_message(
|
|
532
|
+
self,
|
|
533
|
+
filters: Optional[Callable[[Message], bool]] = None,
|
|
534
|
+
commands: Optional[List[str]] = None
|
|
535
|
+
):
|
|
538
536
|
def decorator(func: Callable[[Any, Message], None]):
|
|
537
|
+
async def wrapper(bot, message: Message):
|
|
538
|
+
if filters and not filters(message):return
|
|
539
|
+
if commands:
|
|
540
|
+
if not message.is_command:return
|
|
541
|
+
cmd = message.text.split()[0].lstrip("/")
|
|
542
|
+
if cmd not in commands:return
|
|
543
|
+
return await func(bot, message)
|
|
539
544
|
self._message_handlers.append({
|
|
540
|
-
"func":
|
|
545
|
+
"func": wrapper,
|
|
541
546
|
"filters": filters,
|
|
542
547
|
"commands": commands
|
|
543
548
|
})
|
|
544
|
-
return
|
|
549
|
+
return wrapper
|
|
550
|
+
return decorator
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def on_message_file(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
554
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
555
|
+
async def wrapper(bot, message: Message):
|
|
556
|
+
if not message.file:return
|
|
557
|
+
if filters and not filters(message):return
|
|
558
|
+
return await func(bot, message)
|
|
559
|
+
|
|
560
|
+
self._message_handlers.append({
|
|
561
|
+
"func": wrapper,
|
|
562
|
+
"filters": filters,
|
|
563
|
+
"file_only": True,
|
|
564
|
+
"commands": commands
|
|
565
|
+
})
|
|
566
|
+
return wrapper
|
|
567
|
+
return decorator
|
|
568
|
+
def on_message_forwarded(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
569
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
570
|
+
async def wrapper(bot, message: Message):
|
|
571
|
+
if not message.is_forwarded:return
|
|
572
|
+
if filters and not filters(message):return
|
|
573
|
+
return await func(bot, message)
|
|
574
|
+
|
|
575
|
+
self._message_handlers.append({
|
|
576
|
+
"func": wrapper,
|
|
577
|
+
"filters": filters,
|
|
578
|
+
"forwarded_only": True,
|
|
579
|
+
"commands": commands
|
|
580
|
+
})
|
|
581
|
+
return wrapper
|
|
582
|
+
return decorator
|
|
583
|
+
def on_message_reply(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
584
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
585
|
+
async def wrapper(bot, message: Message):
|
|
586
|
+
if not message.is_reply:return
|
|
587
|
+
if filters and not filters(message):return
|
|
588
|
+
return await func(bot, message)
|
|
589
|
+
|
|
590
|
+
self._message_handlers.append({
|
|
591
|
+
"func": wrapper,
|
|
592
|
+
"filters": filters,
|
|
593
|
+
"reply_only": True,
|
|
594
|
+
"commands": commands
|
|
595
|
+
})
|
|
596
|
+
return wrapper
|
|
597
|
+
return decorator
|
|
598
|
+
def on_message_text(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
599
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
600
|
+
async def wrapper(bot, message: Message):
|
|
601
|
+
if not message.text:return
|
|
602
|
+
if filters and not filters(message):return
|
|
603
|
+
return await func(bot, message)
|
|
604
|
+
|
|
605
|
+
self._message_handlers.append({
|
|
606
|
+
"func": wrapper,
|
|
607
|
+
"filters": filters,
|
|
608
|
+
"text_only": True,
|
|
609
|
+
"commands": commands
|
|
610
|
+
})
|
|
611
|
+
return wrapper
|
|
612
|
+
return decorator
|
|
613
|
+
def on_message_media(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
614
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
615
|
+
async def wrapper(bot, message: Message):
|
|
616
|
+
if not message.is_media:return
|
|
617
|
+
if filters and not filters(message):return
|
|
618
|
+
return await func(bot, message)
|
|
619
|
+
|
|
620
|
+
self._message_handlers.append({
|
|
621
|
+
"func": wrapper,
|
|
622
|
+
"filters": filters,
|
|
623
|
+
"media_only": True,
|
|
624
|
+
"commands": commands
|
|
625
|
+
})
|
|
626
|
+
return wrapper
|
|
627
|
+
return decorator
|
|
628
|
+
def on_message_sticker(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
629
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
630
|
+
async def wrapper(bot, message: Message):
|
|
631
|
+
if not message.sticker:return
|
|
632
|
+
if filters and not filters(message):return
|
|
633
|
+
return await func(bot, message)
|
|
634
|
+
|
|
635
|
+
self._message_handlers.append({
|
|
636
|
+
"func": wrapper,
|
|
637
|
+
"filters": filters,
|
|
638
|
+
"sticker_only": True,
|
|
639
|
+
"commands": commands
|
|
640
|
+
})
|
|
641
|
+
return wrapper
|
|
642
|
+
return decorator
|
|
643
|
+
def on_message_contact(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
644
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
645
|
+
async def wrapper(bot, message: Message):
|
|
646
|
+
if not message.is_contact:return
|
|
647
|
+
if filters and not filters(message):return
|
|
648
|
+
return await func(bot, message)
|
|
649
|
+
|
|
650
|
+
self._message_handlers.append({
|
|
651
|
+
"func": wrapper,
|
|
652
|
+
"filters": filters,
|
|
653
|
+
"contact_only": True,
|
|
654
|
+
"commands": commands
|
|
655
|
+
})
|
|
656
|
+
return wrapper
|
|
657
|
+
return decorator
|
|
658
|
+
def on_message_location(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
659
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
660
|
+
async def wrapper(bot, message: Message):
|
|
661
|
+
if not message.is_location:return
|
|
662
|
+
if filters and not filters(message):return
|
|
663
|
+
return await func(bot, message)
|
|
664
|
+
|
|
665
|
+
self._message_handlers.append({
|
|
666
|
+
"func": wrapper,
|
|
667
|
+
"filters": filters,
|
|
668
|
+
"location_only": True,
|
|
669
|
+
"commands": commands
|
|
670
|
+
})
|
|
671
|
+
return wrapper
|
|
672
|
+
return decorator
|
|
673
|
+
def on_message_poll(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
674
|
+
def decorator(func: Callable[[Any, Message], None]):
|
|
675
|
+
async def wrapper(bot, message: Message):
|
|
676
|
+
if not message.is_poll:return
|
|
677
|
+
if filters and not filters(message):return
|
|
678
|
+
return await func(bot, message)
|
|
679
|
+
|
|
680
|
+
self._message_handlers.append({
|
|
681
|
+
"func": wrapper,
|
|
682
|
+
"filters": filters,
|
|
683
|
+
"poll_only": True,
|
|
684
|
+
"commands": commands
|
|
685
|
+
})
|
|
686
|
+
return wrapper
|
|
545
687
|
return decorator
|
|
546
688
|
def on_update(self, filters: Optional[Callable[[Message], bool]] = None, commands: Optional[List[str]] = None):
|
|
547
689
|
def decorator(func: Callable[[Any, Message], None]):
|
|
@@ -1516,7 +1658,6 @@ class Robot:
|
|
|
1516
1658
|
json_data = await response.json()
|
|
1517
1659
|
if is_temp_file:
|
|
1518
1660
|
os.remove(path)
|
|
1519
|
-
print(json_data)
|
|
1520
1661
|
return json_data.get('data', {}).get('file_id')
|
|
1521
1662
|
except :
|
|
1522
1663
|
raise FeatureNotAvailableError(f"files is not currently supported by the server.")
|
|
@@ -1642,7 +1783,7 @@ class Robot:
|
|
|
1642
1783
|
"inline_keypad":inline_keypad,
|
|
1643
1784
|
"chat_keypad_type":chat_keypad_type
|
|
1644
1785
|
}
|
|
1645
|
-
return
|
|
1786
|
+
return result
|
|
1646
1787
|
|
|
1647
1788
|
async def _send_file_generic(self, media_type, chat_id, path, file_id, text, file_name, inline_keypad, chat_keypad, reply_to_message_id, disable_notification, chat_keypad_type):
|
|
1648
1789
|
if path:
|
|
@@ -1702,13 +1843,19 @@ class Robot:
|
|
|
1702
1843
|
try:
|
|
1703
1844
|
chat = await self.get_chat(chat_id)
|
|
1704
1845
|
chat_info = chat.get("data", {}).get("chat", {})
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1846
|
+
chat_type = chat_info.get("chat_type", "").lower()
|
|
1847
|
+
if chat_type == "user":
|
|
1848
|
+
first_name = chat_info.get("first_name", "")
|
|
1849
|
+
last_name = chat_info.get("last_name", "")
|
|
1850
|
+
full_name = f"{first_name} {last_name}".strip()
|
|
1851
|
+
return full_name if full_name else "null"
|
|
1852
|
+
elif chat_type in ["group", "channel"]:
|
|
1853
|
+
title = chat_info.get("title", "")
|
|
1854
|
+
return title if title else "null"
|
|
1855
|
+
else:return "null"
|
|
1856
|
+
except Exception:return "null"
|
|
1857
|
+
|
|
1858
|
+
|
|
1712
1859
|
|
|
1713
1860
|
async def get_username(self, chat_id: str) -> str:
|
|
1714
1861
|
chat_info = await self.get_chat(chat_id)
|
|
@@ -190,8 +190,10 @@ from pathlib import Path
|
|
|
190
190
|
class Message:
|
|
191
191
|
def __init__(self, bot, chat_id, message_id, sender_id, text=None, raw_data=None):
|
|
192
192
|
self.bot = bot
|
|
193
|
-
self.chat_id = chat_id
|
|
194
193
|
self.raw_data = raw_data or {}
|
|
194
|
+
self.chat_id = chat_id
|
|
195
|
+
self.object_guid = chat_id
|
|
196
|
+
self.author_guid = self.raw_data.get("sender_id", sender_id)
|
|
195
197
|
self.message_id: str = self.raw_data.get("message_id", message_id)
|
|
196
198
|
self.text: str = self.raw_data.get("text", text)
|
|
197
199
|
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
@@ -199,6 +201,7 @@ class Message:
|
|
|
199
201
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
200
202
|
self.sender_type: str = self.raw_data.get("sender_type")
|
|
201
203
|
self.args = []
|
|
204
|
+
self.is_command = bool(self.text and self.text.startswith("/"))
|
|
202
205
|
self.is_user = self.chat_id.startswith("b")
|
|
203
206
|
self.is_private = self.chat_id.startswith("b")
|
|
204
207
|
self.is_group = self.chat_id.startswith("g")
|
|
@@ -212,7 +215,18 @@ class Message:
|
|
|
212
215
|
self.location = Location(self.raw_data["location"]) if "location" in self.raw_data else None
|
|
213
216
|
self.live_location = LiveLocation(self.raw_data["live_location"]) if "live_location" in self.raw_data else None
|
|
214
217
|
self.aux_data = AuxData(self.raw_data["aux_data"]) if "aux_data" in self.raw_data else None
|
|
215
|
-
|
|
218
|
+
self.is_reply = self.reply_to_message_id is not None
|
|
219
|
+
self.has_media = any([self.file, self.sticker, self.poll, self.location, self.live_location])
|
|
220
|
+
self.is_forwarded = self.forwarded_from is not None
|
|
221
|
+
self.is_text = bool(self.text and not self.has_media)
|
|
222
|
+
self.is_media = self.has_media
|
|
223
|
+
self.is_poll = self.poll is not None
|
|
224
|
+
self.is_location = self.location is not None
|
|
225
|
+
self.is_live_location = self.live_location is not None
|
|
226
|
+
self.is_contact = self.contact_message is not None
|
|
227
|
+
self.has_any_media = any([self.file, self.sticker, self.poll, self.location, self.live_location])
|
|
228
|
+
self.edited_text = self.raw_data.get("edited_text") if self.is_edited else None
|
|
229
|
+
self.info = {attr: value for attr, value in vars(self).items()}
|
|
216
230
|
@property
|
|
217
231
|
def session(self):
|
|
218
232
|
if self.chat_id not in self.bot.sessions:
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
class Filter:
|
|
5
|
+
def __init__(self, func: Callable):
|
|
6
|
+
self.func = func
|
|
7
|
+
|
|
8
|
+
def __call__(self, message):
|
|
9
|
+
return self.func(message)
|
|
10
|
+
|
|
11
|
+
def __and__(self, other):
|
|
12
|
+
return Filter(lambda m: self(m) and other(m))
|
|
13
|
+
|
|
14
|
+
def __or__(self, other):
|
|
15
|
+
return Filter(lambda m: self(m) or other(m))
|
|
16
|
+
|
|
17
|
+
def __invert__(self):
|
|
18
|
+
return Filter(lambda m: not self(m))
|
|
19
|
+
|
|
20
|
+
def __xor__(self, other):
|
|
21
|
+
return Filter(lambda m: self(m) != other(m))
|
|
22
|
+
|
|
23
|
+
def __eq__(self, other):
|
|
24
|
+
return Filter(lambda m: self(m) == other)
|
|
25
|
+
|
|
26
|
+
def __ne__(self, other):
|
|
27
|
+
return Filter(lambda m: self(m) != other)
|
|
28
|
+
|
|
29
|
+
def __lt__(self, other):
|
|
30
|
+
return Filter(lambda m: self(m) < other)
|
|
31
|
+
|
|
32
|
+
def __le__(self, other):
|
|
33
|
+
return Filter(lambda m: self(m) <= other)
|
|
34
|
+
|
|
35
|
+
def __gt__(self, other):
|
|
36
|
+
return Filter(lambda m: self(m) > other)
|
|
37
|
+
|
|
38
|
+
def __ge__(self, other):
|
|
39
|
+
return Filter(lambda m: self(m) >= other)
|
|
40
|
+
|
|
41
|
+
def __add__(self, other):
|
|
42
|
+
return Filter(lambda m: self(m) + (other(m) if callable(other) else other))
|
|
43
|
+
|
|
44
|
+
def __sub__(self, other):
|
|
45
|
+
return Filter(lambda m: self(m) - (other(m) if callable(other) else other))
|
|
46
|
+
|
|
47
|
+
def __mul__(self, other):
|
|
48
|
+
return Filter(lambda m: self(m) * (other(m) if callable(other) else other))
|
|
49
|
+
|
|
50
|
+
def __truediv__(self, other):
|
|
51
|
+
return Filter(lambda m: self(m) / (other(m) if callable(other) else other))
|
|
52
|
+
|
|
53
|
+
is_text = Filter(lambda m: getattr(m, "is_text", False))
|
|
54
|
+
is_file = Filter(lambda m: getattr(m, "file", None) is not None)
|
|
55
|
+
is_sticker = Filter(lambda m: getattr(m, "sticker", None) is not None)
|
|
56
|
+
is_contact = Filter(lambda m: getattr(m, "contact_message", None) is not None)
|
|
57
|
+
is_poll = Filter(lambda m: getattr(m, "poll", None) is not None)
|
|
58
|
+
is_location = Filter(lambda m: getattr(m, "location", None) is not None)
|
|
59
|
+
is_live_location = Filter(lambda m: getattr(m, "live_location", None) is not None)
|
|
60
|
+
has_any_media = Filter(lambda m: getattr(m, "has_any_media", False))
|
|
61
|
+
has_media = Filter(lambda m: getattr(m, "has_media", False))
|
|
62
|
+
is_command = Filter(lambda m: getattr(m, "is_command", False))
|
|
63
|
+
is_user = Filter(lambda m: getattr(m, "is_user", False))
|
|
64
|
+
is_private = Filter(lambda m: getattr(m, "is_private", False))
|
|
65
|
+
is_group = Filter(lambda m: getattr(m, "is_group", False))
|
|
66
|
+
is_channel = Filter(lambda m: getattr(m, "is_channel", False))
|
|
67
|
+
is_reply = Filter(lambda m: getattr(m, "is_reply", False))
|
|
68
|
+
is_forwarded = Filter(lambda m: getattr(m, "is_forwarded", False))
|
|
69
|
+
is_edited = Filter(lambda m: getattr(m, "is_edited", False))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def text(keyword: str):
|
|
75
|
+
return Filter(lambda m: getattr(m, "text", "") and keyword in m.text)
|
|
76
|
+
|
|
77
|
+
def text_length(min_len: int = 0, max_len: int = None):
|
|
78
|
+
def _filter(m):
|
|
79
|
+
t = getattr(m, "text", "")
|
|
80
|
+
if not t: return False
|
|
81
|
+
if len(t) < min_len: return False
|
|
82
|
+
if max_len is not None and len(t) > max_len: return False
|
|
83
|
+
return True
|
|
84
|
+
return Filter(_filter)
|
|
85
|
+
|
|
86
|
+
def text_regex(pattern: str):
|
|
87
|
+
regex = re.compile(pattern)
|
|
88
|
+
return Filter(lambda m: getattr(m, "text", "") and regex.search(m.text))
|
|
89
|
+
|
|
90
|
+
def text_startswith(prefix: str):
|
|
91
|
+
return Filter(lambda m: getattr(m, "text", "").startswith(prefix) if getattr(m, "text", None) else False)
|
|
92
|
+
|
|
93
|
+
def text_endswith(suffix: str):
|
|
94
|
+
return Filter(lambda m: getattr(m, "text", "").endswith(suffix) if getattr(m, "text", None) else False)
|
|
95
|
+
|
|
96
|
+
def text_upper():
|
|
97
|
+
return Filter(lambda m: getattr(m, "text", "").isupper() if getattr(m, "text", None) else False)
|
|
98
|
+
|
|
99
|
+
def text_lower():
|
|
100
|
+
return Filter(lambda m: getattr(m, "text", "").islower() if getattr(m, "text", None) else False)
|
|
101
|
+
|
|
102
|
+
def text_digit():
|
|
103
|
+
return Filter(lambda m: getattr(m, "text", "").isdigit() if getattr(m, "text", None) else False)
|
|
104
|
+
|
|
105
|
+
def text_word_count(min_words: int = 1, max_words: int = None):
|
|
106
|
+
def _filter(m):
|
|
107
|
+
t = getattr(m, "text", "")
|
|
108
|
+
if not t: return False
|
|
109
|
+
wc = len(t.split())
|
|
110
|
+
if wc < min_words: return False
|
|
111
|
+
if max_words is not None and wc > max_words: return False
|
|
112
|
+
return True
|
|
113
|
+
return Filter(_filter)
|
|
114
|
+
|
|
115
|
+
def text_contains_any(keywords: list):
|
|
116
|
+
return Filter(lambda m: getattr(m, "text", "") and any(k in m.text for k in keywords))
|
|
117
|
+
|
|
118
|
+
def text_equals(value: str):
|
|
119
|
+
return Filter(lambda m: getattr(m, "text", None) == value)
|
|
120
|
+
|
|
121
|
+
def text_not_equals(value: str):
|
|
122
|
+
return Filter(lambda m: getattr(m, "text", None) != value)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def file_size_gt(size: int):
|
|
128
|
+
return Filter(lambda m: m.file and getattr(m.file, "size", 0) > size)
|
|
129
|
+
|
|
130
|
+
def file_size_lt(size: int):
|
|
131
|
+
return Filter(lambda m: m.file and getattr(m.file, "size", 0) < size)
|
|
132
|
+
|
|
133
|
+
def file_name_contains(substring: str):
|
|
134
|
+
return Filter(lambda m: m.file and substring in getattr(m.file, "file_name", ""))
|
|
135
|
+
|
|
136
|
+
def file_extension(ext: str):
|
|
137
|
+
return Filter(lambda m: m.file and getattr(m.file, "file_name", "").endswith(ext))
|
|
138
|
+
|
|
139
|
+
def file_id_is(file_id: str):
|
|
140
|
+
return Filter(lambda m: m.file and getattr(m.file, "file_id", None) == file_id)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def sticker_id_is(sid: str):
|
|
146
|
+
return Filter(lambda m: m.sticker and getattr(m.sticker, "sticker_id", None) == sid)
|
|
147
|
+
|
|
148
|
+
def sticker_emoji_is(emoji: str):
|
|
149
|
+
return Filter(lambda m: m.sticker and getattr(m.sticker, "emoji", None) == emoji)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def poll_question_contains(keyword: str):
|
|
155
|
+
return Filter(lambda m: m.poll and keyword in getattr(m.poll, "question", ""))
|
|
156
|
+
|
|
157
|
+
def poll_option_count(min_options: int = 1, max_options: int = None):
|
|
158
|
+
def _filter(m):
|
|
159
|
+
if not getattr(m, "poll", None): return False
|
|
160
|
+
options = getattr(m.poll, "options", [])
|
|
161
|
+
if len(options) < min_options: return False
|
|
162
|
+
if max_options is not None and len(options) > max_options: return False
|
|
163
|
+
return True
|
|
164
|
+
return Filter(_filter)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def location_within(lat_min, lat_max, long_min, long_max):
|
|
170
|
+
def _filter(m):
|
|
171
|
+
loc = getattr(m, "location", None)
|
|
172
|
+
if not loc: return False
|
|
173
|
+
return lat_min <= getattr(loc, "lat", 0) <= lat_max and long_min <= getattr(loc, "long", 0) <= long_max
|
|
174
|
+
return Filter(_filter)
|
|
175
|
+
|
|
176
|
+
def live_location_within(lat_min, lat_max, long_min, long_max):
|
|
177
|
+
def _filter(m):
|
|
178
|
+
loc = getattr(m, "live_location", None)
|
|
179
|
+
if not loc: return False
|
|
180
|
+
return lat_min <= getattr(loc, "lat", 0) <= lat_max and long_min <= getattr(loc, "long", 0) <= long_max
|
|
181
|
+
return Filter(_filter)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def has_media_types(types: list):
|
|
187
|
+
return Filter(lambda m: any(getattr(m, t, None) for t in types))
|
|
188
|
+
|
|
189
|
+
def message_id_is(mid: str):
|
|
190
|
+
return Filter(lambda m: getattr(m, "message_id", None) == mid)
|
|
191
|
+
|
|
192
|
+
def is_reply_to_user(user_id: str):
|
|
193
|
+
return Filter(lambda m: getattr(m, "reply_to_message_id", None) == user_id)
|
|
194
|
+
|
|
195
|
+
def is_forwarded_from(user_id: str):
|
|
196
|
+
return Filter(lambda m: getattr(m.forwarded_from, "sender_id", None) == user_id if getattr(m, "forwarded_from", None) else False)
|
|
197
|
+
|
|
198
|
+
def edited_text_contains(keyword: str):
|
|
199
|
+
return Filter(lambda m: getattr(m, "edited_text", "") and keyword in m.edited_text)
|
|
200
|
+
|
|
201
|
+
def aux_data_contains(key: str, value):
|
|
202
|
+
return Filter(lambda m: getattr(m.aux_data, key, None) == value if getattr(m, "aux_data", None) else False)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def file_attr(attr_name):
|
|
208
|
+
return Filter(lambda m: m.file and getattr(m.file, attr_name, None))
|
|
209
|
+
|
|
210
|
+
def sticker_attr(attr_name):
|
|
211
|
+
return Filter(lambda m: m.sticker and getattr(m.sticker, attr_name, None))
|
|
212
|
+
|
|
213
|
+
def poll_attr(attr_name):
|
|
214
|
+
return Filter(lambda m: m.poll and getattr(m.poll, attr_name, None))
|
|
215
|
+
|
|
216
|
+
def location_attr(attr_name):
|
|
217
|
+
return Filter(lambda m: m.location and getattr(m.location, attr_name, None))
|
|
218
|
+
|
|
219
|
+
def live_location_attr(attr_name):
|
|
220
|
+
return Filter(lambda m: m.live_location and getattr(m.live_location, attr_name, None))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
file_size = file_attr("size")
|
|
226
|
+
file_name = file_attr("file_name")
|
|
227
|
+
sticker_id = sticker_attr("sticker_id")
|
|
228
|
+
poll_question = poll_attr("question")
|
|
229
|
+
location_lat = location_attr("lat")
|
|
230
|
+
location_long = location_attr("long")
|
|
231
|
+
live_location_lat = live_location_attr("lat")
|
|
232
|
+
live_location_long = live_location_attr("long")
|
|
233
|
+
|
|
234
|
+
_custom_filters = {}
|
|
235
|
+
def chat_title_contains(keyword: str):
|
|
236
|
+
|
|
237
|
+
return Filter(lambda m: getattr(m, "chat", None) and keyword in getattr(m.chat, "title", ""))
|
|
238
|
+
|
|
239
|
+
def chat_title_equals(value: str):
|
|
240
|
+
|
|
241
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "title", "") == value)
|
|
242
|
+
|
|
243
|
+
def chat_id_is(cid: str):
|
|
244
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "id", None) == cid)
|
|
245
|
+
|
|
246
|
+
def chat_member_count(min_count: int = 0, max_count: int = None):
|
|
247
|
+
|
|
248
|
+
def _filter(m):
|
|
249
|
+
c = getattr(m, "chat", None)
|
|
250
|
+
if not c: return False
|
|
251
|
+
count = getattr(c, "member_count", 0)
|
|
252
|
+
if count < min_count: return False
|
|
253
|
+
if max_count is not None and count > max_count: return False
|
|
254
|
+
return True
|
|
255
|
+
return Filter(_filter)
|
|
256
|
+
|
|
257
|
+
def chat_type_is(chat_type: str):
|
|
258
|
+
|
|
259
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "type", None) == chat_type)
|
|
260
|
+
|
|
261
|
+
def chat_username_contains(keyword: str):
|
|
262
|
+
|
|
263
|
+
return Filter(lambda m: getattr(m, "chat", None) and keyword in getattr(m.chat, "username", ""))
|
|
264
|
+
|
|
265
|
+
def chat_username_equals(value: str):
|
|
266
|
+
|
|
267
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "username", "") == value)
|
|
268
|
+
|
|
269
|
+
def chat_has_link():
|
|
270
|
+
|
|
271
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "invite_link", None) is not None)
|
|
272
|
+
|
|
273
|
+
def chat_is_private():
|
|
274
|
+
|
|
275
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "type", None) in ["group", "channel"])
|
|
276
|
+
|
|
277
|
+
def chat_member_count_gt(count: int):
|
|
278
|
+
|
|
279
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "member_count", 0) > count)
|
|
280
|
+
|
|
281
|
+
def chat_member_count_lt(count: int):
|
|
282
|
+
|
|
283
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "member_count", 0) < count)
|
|
284
|
+
|
|
285
|
+
def chat_has_username():
|
|
286
|
+
|
|
287
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "username", None) is not None)
|
|
288
|
+
|
|
289
|
+
def chat_type_in(types: list):
|
|
290
|
+
|
|
291
|
+
return Filter(lambda m: getattr(m, "chat", None) and getattr(m.chat, "type", None) in types)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def chat_title_regex(pattern: str):
|
|
295
|
+
regex = re.compile(pattern)
|
|
296
|
+
return Filter(lambda m: getattr(m, "chat", None) and regex.search(getattr(m.chat, "title", "")))
|
|
297
|
+
|
|
298
|
+
def chat_username_regex(pattern: str):
|
|
299
|
+
regex = re.compile(pattern)
|
|
300
|
+
return Filter(lambda m: getattr(m, "chat", None) and regex.search(getattr(m.chat, "username", "")))
|
|
301
|
+
def custom(name):
|
|
302
|
+
def wrapper(func):
|
|
303
|
+
_custom_filters[name] = Filter(func)
|
|
304
|
+
return _custom_filters[name]
|
|
305
|
+
return wrapper
|
|
306
|
+
|
|
307
|
+
def get_custom(name):
|
|
308
|
+
return _custom_filters.get(name)
|
|
309
|
+
|
|
310
|
+
def and_(*filters):
|
|
311
|
+
return Filter(lambda m: all(f(m) for f in filters))
|
|
312
|
+
|
|
313
|
+
def or_(*filters):
|
|
314
|
+
return Filter(lambda m: any(f(m) for f in filters))
|
|
315
|
+
|
|
316
|
+
def not_(filter_):
|
|
317
|
+
return Filter(lambda m: not filter_(m))
|
|
@@ -190,8 +190,10 @@ from pathlib import Path
|
|
|
190
190
|
class Message:
|
|
191
191
|
def __init__(self, bot, chat_id, message_id, sender_id, text=None, raw_data=None):
|
|
192
192
|
self.bot = bot
|
|
193
|
-
self.chat_id = chat_id
|
|
194
193
|
self.raw_data = raw_data or {}
|
|
194
|
+
self.chat_id = chat_id
|
|
195
|
+
self.object_guid = chat_id
|
|
196
|
+
self.author_guid = self.raw_data.get("sender_id", sender_id)
|
|
195
197
|
self.message_id: str = self.raw_data.get("message_id", message_id)
|
|
196
198
|
self.text: str = self.raw_data.get("text", text)
|
|
197
199
|
self.sender_id: str = self.raw_data.get("sender_id", sender_id)
|
|
@@ -199,6 +201,7 @@ class Message:
|
|
|
199
201
|
self.is_edited: bool = self.raw_data.get("is_edited", False)
|
|
200
202
|
self.sender_type: str = self.raw_data.get("sender_type")
|
|
201
203
|
self.args = []
|
|
204
|
+
self.is_command = bool(self.text and self.text.startswith("/"))
|
|
202
205
|
self.is_user = self.chat_id.startswith("b")
|
|
203
206
|
self.is_private = self.chat_id.startswith("b")
|
|
204
207
|
self.is_group = self.chat_id.startswith("g")
|
|
@@ -212,7 +215,18 @@ class Message:
|
|
|
212
215
|
self.location = Location(self.raw_data["location"]) if "location" in self.raw_data else None
|
|
213
216
|
self.live_location = LiveLocation(self.raw_data["live_location"]) if "live_location" in self.raw_data else None
|
|
214
217
|
self.aux_data = AuxData(self.raw_data["aux_data"]) if "aux_data" in self.raw_data else None
|
|
215
|
-
|
|
218
|
+
self.is_reply = self.reply_to_message_id is not None
|
|
219
|
+
self.has_media = any([self.file, self.sticker, self.poll, self.location, self.live_location])
|
|
220
|
+
self.is_forwarded = self.forwarded_from is not None
|
|
221
|
+
self.is_text = bool(self.text and not self.has_media)
|
|
222
|
+
self.is_media = self.has_media
|
|
223
|
+
self.is_poll = self.poll is not None
|
|
224
|
+
self.is_location = self.location is not None
|
|
225
|
+
self.is_live_location = self.live_location is not None
|
|
226
|
+
self.is_contact = self.contact_message is not None
|
|
227
|
+
self.has_any_media = any([self.file, self.sticker, self.poll, self.location, self.live_location])
|
|
228
|
+
self.edited_text = self.raw_data.get("edited_text") if self.is_edited else None
|
|
229
|
+
self.info = {attr: value for attr, value in vars(self).items()}
|
|
216
230
|
@property
|
|
217
231
|
def session(self):
|
|
218
232
|
if self.chat_id not in self.bot.sessions:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|