pyrobale 0.3.8.5__tar.gz → 0.3.9.1__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 (59) hide show
  1. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/.github/workflows/docs.yml +1 -1
  2. pyrobale-0.3.9.1/.github/workflows/pypi.yml +36 -0
  3. pyrobale-0.3.9.1/.gitignore +1 -0
  4. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/PKG-INFO +3 -2
  5. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyproject.toml +4 -4
  6. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/client/__init__.py +114 -3
  7. pyrobale-0.3.9.1/pyrobale/objects/peerdata.py +25 -0
  8. pyrobale-0.3.9.1/version.py +2 -0
  9. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/.github/ISSUE_TEMPLATE/issue-template-/342/204/271/357/270/217.md" +0 -0
  10. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/LICENSE +0 -0
  11. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/README.md +0 -0
  12. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/examples/command.py +0 -0
  13. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/examples/echo_bot.py +0 -0
  14. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/examples/handler_system.py +0 -0
  15. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/examples/inline_keyboard.py +0 -0
  16. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/StateMachine/__init__.py +0 -0
  17. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/__init__.py +0 -0
  18. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/exceptions/__init__.py +0 -0
  19. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/exceptions/common.py +0 -0
  20. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/filters/__init__.py +0 -0
  21. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/filters/enum_filters.py +0 -0
  22. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/filters/func_filters.py +0 -0
  23. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/__init__.py +0 -0
  24. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/animation.py +0 -0
  25. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/audio.py +0 -0
  26. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/callbackquery.py +0 -0
  27. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/chat.py +0 -0
  28. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/chatmember.py +0 -0
  29. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/chatphoto.py +0 -0
  30. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/contact.py +0 -0
  31. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/copytextbutton.py +0 -0
  32. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/document.py +0 -0
  33. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/enums.py +0 -0
  34. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/file.py +0 -0
  35. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/inlinekeyboardbutton.py +0 -0
  36. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/inlinekeyboardmarkup.py +0 -0
  37. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/inputfile.py +0 -0
  38. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/inputmedias.py +0 -0
  39. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/invoice.py +0 -0
  40. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/keyboardbutton.py +0 -0
  41. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/labeledprice.py +0 -0
  42. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/location.py +0 -0
  43. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/message.py +0 -0
  44. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/messageid.py +0 -0
  45. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/photosize.py +0 -0
  46. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/precheckoutquery.py +0 -0
  47. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/replykeyboardmarkup.py +0 -0
  48. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/sticker.py +0 -0
  49. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/stickerset.py +0 -0
  50. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/successfulpayment.py +0 -0
  51. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/update.py +0 -0
  52. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/user.py +0 -0
  53. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/utils.py +0 -0
  54. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/video.py +0 -0
  55. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/voice.py +0 -0
  56. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/webappdata.py +0 -0
  57. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale/objects/webappinfo.py +0 -0
  58. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobale.png +0 -0
  59. {pyrobale-0.3.8.5 → pyrobale-0.3.9.1}/pyrobaletext.png +0 -0
@@ -22,7 +22,7 @@ jobs:
22
22
 
23
23
  - name: Install dependencies
24
24
  run: |
25
- pip install pdoc aiohttp
25
+ pip install pdoc aiohttp beautifulsoup4
26
26
 
27
27
  - name: Generate documentation
28
28
  run: |
@@ -0,0 +1,36 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v4
16
+ with:
17
+ python-version: '3.x'
18
+
19
+ - name: Extract version info
20
+ id: version
21
+ run: |
22
+ STABLE=$(python -c "from version import stable; print(str(stable).lower())")
23
+ VERSION=$(python -c "from version import version; print(version)")
24
+ echo "stable=$STABLE" >> $GITHUB_OUTPUT
25
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
26
+ echo "Stable: $STABLE, Version: $VERSION"
27
+
28
+ - name: Build and publish
29
+ if: steps.version.outputs.stable == 'true'
30
+ run: |
31
+ pip install build twine
32
+ python -m build
33
+ twine upload dist/* --username __token__ --password ${{ secrets.PYPI }}
34
+ env:
35
+ TWINE_USERNAME: __token__
36
+ TWINE_PASSWORD: ${{ secrets.PYPI }}
@@ -0,0 +1 @@
1
+ dist
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrobale
3
- Version: 0.3.8.5
3
+ Version: 0.3.9.1
4
4
  Summary: A python wrapper for bale api
5
5
  Project-URL: github, https://github.com/pyrobale/pyrobale
6
6
  Project-URL: website, https://pyrobale.github.io
7
- Author-email: Ali Safamanesh <darg.q.a.a@gmail.com>, Aydin Rahbaran <codewizaard9@gmail.com>
7
+ Author-email: Ali Safamanesh <daradege@proton.me>, Aydin Rahbaran <codewizaard9@gmail.com>
8
8
  License: MIT License
9
9
 
10
10
  Copyright (c) 2025 PyroBale Team
@@ -32,6 +32,7 @@ Classifier: Operating System :: OS Independent
32
32
  Classifier: Programming Language :: Python :: 3
33
33
  Requires-Python: >=3.9
34
34
  Requires-Dist: aiohttp
35
+ Requires-Dist: beautifulsoup4
35
36
  Description-Content-Type: text/markdown
36
37
 
37
38
  ![pyrobaletext](https://raw.githubusercontent.com/pyrobale/pyrobale/refs/heads/main/pyrobaletext.png)
@@ -1,9 +1,9 @@
1
1
  [project]
2
2
  name = "pyrobale"
3
- version = "0.3.8.5"
3
+ version = "0.3.9.1"
4
4
  authors = [
5
- { name = "Ali Safamanesh", email = "darg.q.a.a@gmail.com" },
6
- { name = "Aydin Rahbaran", email = "codewizaard9@gmail.com"},
5
+ { name = "Ali Safamanesh", email = "daradege@proton.me" },
6
+ { name = "Aydin Rahbaran", email = "codewizaard9@gmail.com"}
7
7
  ]
8
8
  description = "A python wrapper for bale api"
9
9
  readme = "README.md"
@@ -14,7 +14,7 @@ classifiers = [
14
14
  "Operating System :: OS Independent",
15
15
  ]
16
16
  license = { file = "LICENSE" }
17
- dependencies = ["aiohttp"]
17
+ dependencies = ["aiohttp", "beautifulsoup4"]
18
18
  [project.urls]
19
19
  github = "https://github.com/pyrobale/pyrobale"
20
20
  website = "https://pyrobale.github.io"
@@ -37,13 +37,16 @@ from ..objects.voice import Voice
37
37
  from ..objects.webappdata import WebAppData
38
38
  from ..objects.webappinfo import WebAppInfo
39
39
  from ..objects.utils import *
40
- import asyncio
41
- from enum import Enum
42
40
  from ..objects.enums import UpdatesTypes, ChatAction, ChatType
41
+ from ..objects.peerdata import PeerData
43
42
  from ..filters import Filters, equals
44
43
  from ..StateMachine import StateMachine
45
44
  from ..exceptions import NotFoundException, InvalidTokenException, PyroBaleException
46
45
 
46
+ from enum import Enum
47
+ import asyncio
48
+ from bs4 import BeautifulSoup
49
+ from json import loads, JSONDecodeError
47
50
 
48
51
  class Client:
49
52
  """A client for interacting with the Bale messenger API.
@@ -64,6 +67,9 @@ class Client:
64
67
  self.last_update_id = 0
65
68
  self.state_machine = StateMachine()
66
69
 
70
+ self.check_defined_message = True
71
+ self.defined_messages = {}
72
+
67
73
  async def get_updates(
68
74
  self,
69
75
  offset: Optional[int] = None,
@@ -725,7 +731,100 @@ class Client:
725
731
  self.requests_base + "/getChat", data={"chat_id": chat_id}
726
732
  )
727
733
  return Chat(**pythonize(data["result"]))
728
-
734
+
735
+ @staticmethod
736
+ async def get_ble_ir_page(username_or_phone_number: str) -> Union[dict, PeerData]:
737
+ """Get BleIR user/group information.
738
+
739
+ Args:
740
+ username_or_phone_number (str): Username or phone number
741
+
742
+ Returns:
743
+ Union[dict, PeerData]: User/group information or error dict
744
+ """
745
+ url = f"https://ble.ir/{username_or_phone_number}"
746
+
747
+ async with aiohttp.ClientSession() as session:
748
+ async with session.get(url) as response:
749
+ req = await response.text()
750
+
751
+ if """<p class="__404_title__lxIKL">گفتگوی مورد نظر وجود ندارد.</p>""" in req:
752
+ return PeerData(
753
+ is_ok=False,
754
+ avatar=None,
755
+ description=None,
756
+ name=None,
757
+ is_bot=None,
758
+ is_verified=None,
759
+ is_private=None,
760
+ members=None,
761
+ last_message=None,
762
+ user_id=None,
763
+ username=None,
764
+ )
765
+
766
+ soup = BeautifulSoup(req, "html.parser")
767
+ json_data = {}
768
+
769
+ try:
770
+ json_script = soup.find("script", id="__NEXT_DATA__").text
771
+ json_data = loads(json_script)
772
+ page_props = json_data.get("props", {}).get("pageProps", {})
773
+ user_data = page_props.get("user", {})
774
+ group_data = page_props.get("group", {})
775
+ messages = page_props.get("messages", [])
776
+ except (AttributeError, KeyError, JSONDecodeError):
777
+ pass
778
+
779
+ try:
780
+ avatar = soup.find("img", class_="Avatar_img___C2_3")["src"]
781
+ except (AttributeError, KeyError):
782
+ avatar = None
783
+
784
+ try:
785
+ description = soup.find("div", class_="Profile_description__YTAr_").text
786
+ except AttributeError:
787
+ description = None
788
+
789
+ try:
790
+ name = soup.find("h1", class_="Profile_name__pQglx").text
791
+ except AttributeError:
792
+ name = None
793
+
794
+ is_bot = user_data.get("isBot", False)
795
+ is_verified = user_data.get("isVerified", group_data.get("isVerified", False))
796
+ is_private = user_data.get("isPrivate", group_data.get("isPrivate", False))
797
+ members = group_data.get("members")
798
+ username = user_data.get("nick")
799
+ user_id = page_props.get("peer", {}).get("id")
800
+
801
+ last_message = None
802
+ if messages:
803
+ try:
804
+ last_msg = messages[-1]["message"]
805
+ last_message = (
806
+ last_msg.get("documentMessage", {}).get("caption", {}).get("text")
807
+ or last_msg.get("textMessage", {}).get("text")
808
+ )
809
+ if last_message:
810
+ last_message = last_message.replace("&zwnj;", "")
811
+ except (KeyError, IndexError):
812
+ pass
813
+
814
+ return PeerData(
815
+ True,
816
+ avatar,
817
+ description,
818
+ name,
819
+ is_bot,
820
+ is_verified,
821
+ is_private,
822
+ members,
823
+ last_message,
824
+ user_id,
825
+ username
826
+ )
827
+
729
828
  async def get_chat_members_count(self, chat_id: int) -> int:
730
829
  """Get the number of members in a chat.
731
830
 
@@ -941,6 +1040,16 @@ class Client:
941
1040
  if update_id:
942
1041
  self.last_update_id = update_id + 1
943
1042
 
1043
+ if self.check_defined_message:
1044
+ try:
1045
+ update_raw = update['message']
1046
+ if update_raw.get("text") in self.defined_messages.keys():
1047
+ await self.send_message(update_raw.get('chat').get('id'), self.defined_messages.get(update_raw.get("text")), update.get('message_id'))
1048
+ except KeyError:
1049
+ pass
1050
+ except Exception as e:
1051
+ print(e)
1052
+
944
1053
  for waiter in list(self._waiters):
945
1054
  w_type, check, future = waiter
946
1055
  if w_type.value in update:
@@ -956,6 +1065,8 @@ class Client:
956
1065
  update_type = handler["type"].value
957
1066
  if update_type in update:
958
1067
  raw_event = update[update_type]
1068
+
1069
+
959
1070
  event = self._convert_event(handler["type"], raw_event)
960
1071
 
961
1072
  if handler["type"] == UpdatesTypes.COMMAND:
@@ -0,0 +1,25 @@
1
+ class PeerData:
2
+ """A class to parse data received from ble.ir pages."""
3
+ def __init__(self,
4
+ is_ok: bool,
5
+ avatar: str,
6
+ description: str,
7
+ name: str,
8
+ is_bot: bool,
9
+ is_verified: bool,
10
+ is_private: bool,
11
+ members: int,
12
+ last_message: str,
13
+ user_id: int,
14
+ username: str):
15
+ self.is_ok = is_ok
16
+ self.avatar = avatar
17
+ self.description = description
18
+ self.name = name
19
+ self.is_bot = is_bot
20
+ self.is_verified = is_verified
21
+ self.is_private = is_private
22
+ self.members = members
23
+ self.last_message = last_message
24
+ self.user_id = user_id
25
+ self.username = username
@@ -0,0 +1,2 @@
1
+ stable = True
2
+ version = "0.3.9.1"
File without changes
File without changes
File without changes
File without changes