pyrobale 0.3.5__py3-none-any.whl → 0.3.8__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.
- pyrobale/StateMachine/__init__.py +66 -0
- pyrobale/__init__.py +122 -0
- pyrobale/client/__init__.py +679 -35
- pyrobale/exceptions/__init__.py +1 -0
- pyrobale/exceptions/common.py +6 -0
- pyrobale/filters/__init__.py +2 -0
- pyrobale/filters/enum_filters.py +12 -0
- pyrobale/filters/func_filters.py +17 -0
- pyrobale/objects/__init__.py +3 -0
- pyrobale/objects/callbackquery.py +19 -24
- pyrobale/objects/chatmember.py +5 -4
- pyrobale/objects/enums.py +8 -0
- pyrobale/objects/inlinekeyboardmarkup.py +11 -4
- pyrobale/objects/message.py +33 -16
- pyrobale/objects/user.py +11 -9
- pyrobale/objects/utils.py +23 -3
- pyrobale-0.3.8.dist-info/METADATA +152 -0
- {pyrobale-0.3.5.dist-info → pyrobale-0.3.8.dist-info}/RECORD +20 -16
- {pyrobale-0.3.5.dist-info → pyrobale-0.3.8.dist-info}/licenses/LICENSE +2 -2
- pyrobale-0.3.5.dist-info/METADATA +0 -176
- {pyrobale-0.3.5.dist-info → pyrobale-0.3.8.dist-info}/WHEEL +0 -0
pyrobale/exceptions/__init__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
from .common import *
|
pyrobale/exceptions/common.py
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
def equals(expected_text: str):
|
2
|
+
"""
|
3
|
+
Check if the event text or caption is equal to the expected text.
|
4
|
+
|
5
|
+
Args:
|
6
|
+
expected_text (str): The expected text to compare with.
|
7
|
+
|
8
|
+
Returns:
|
9
|
+
Callable: A function that checks if the event text or caption is equal to the expected text.
|
10
|
+
"""
|
11
|
+
def check(event):
|
12
|
+
try:
|
13
|
+
return getattr(event, "text", None) == expected_text or getattr(event, "caption", None) == expected_text
|
14
|
+
except:
|
15
|
+
return False
|
16
|
+
return check
|
17
|
+
|
pyrobale/objects/__init__.py
CHANGED
@@ -1,13 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
|
3
|
-
if TYPE_CHECKING:
|
4
|
-
from .user import User
|
5
|
-
from .message import Message
|
6
|
-
from ..client import Client
|
7
|
-
|
8
|
-
from .user import User
|
9
|
-
from .message import Message
|
10
|
-
from .chat import Chat
|
1
|
+
from typing import Optional
|
11
2
|
|
12
3
|
|
13
4
|
class CallbackQuery:
|
@@ -16,27 +7,31 @@ class CallbackQuery:
|
|
16
7
|
def __init__(
|
17
8
|
self,
|
18
9
|
id: Optional[str] = None,
|
19
|
-
user: Optional[
|
20
|
-
message: Optional[
|
10
|
+
user: Optional[dict] = None,
|
11
|
+
message: Optional[dict] = None,
|
21
12
|
data: Optional[str] = None,
|
22
13
|
**kwargs
|
23
14
|
):
|
24
15
|
self.id = id
|
25
|
-
self.user
|
26
|
-
self.message
|
27
|
-
self.chat
|
16
|
+
self.user = None
|
17
|
+
self.message = None
|
18
|
+
self.chat = None
|
28
19
|
self.data = data if data else None
|
29
|
-
self.bot
|
20
|
+
self.bot = kwargs.get("kwargs", {}).get("client", None)
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
) -> bool:
|
34
|
-
"""Sends a response to the callback query.
|
22
|
+
if user:
|
23
|
+
from .user import User
|
35
24
|
|
36
|
-
|
25
|
+
self.user = User(**user)
|
37
26
|
|
38
|
-
|
27
|
+
if message:
|
28
|
+
from .message import Message
|
39
29
|
|
40
|
-
|
41
|
-
|
30
|
+
self.message = Message(**message)
|
31
|
+
self.chat = self.message.chat if self.message else None
|
32
|
+
|
33
|
+
async def answer(
|
34
|
+
self, text: Optional[str] = None, show_alert: bool = False
|
35
|
+
) -> bool:
|
36
|
+
"""Sends a response to the callback query."""
|
42
37
|
return await self.bot.answer_callback_query(self.id, text, show_alert)
|
pyrobale/objects/chatmember.py
CHANGED
@@ -4,10 +4,10 @@ from typing import Optional, Union
|
|
4
4
|
if TYPE_CHECKING:
|
5
5
|
from .utils import build_api_url
|
6
6
|
from .user import User
|
7
|
+
from ..client import Client
|
7
8
|
from .chat import Chat
|
8
9
|
from .user import User
|
9
10
|
from .enums import ChatType
|
10
|
-
from ..client import Client
|
11
11
|
|
12
12
|
|
13
13
|
class ChatMember:
|
@@ -79,8 +79,8 @@ class ChatMember:
|
|
79
79
|
"""Bans the chat member from the chat.
|
80
80
|
|
81
81
|
:param chat_id: The ID of the chat.
|
82
|
-
|
83
|
-
|
82
|
+
:return: True if the member was banned successfully, False
|
83
|
+
otherwise.
|
84
84
|
"""
|
85
85
|
data = await self.chat.ban(self.user.id)
|
86
86
|
return data
|
@@ -88,7 +88,8 @@ class ChatMember:
|
|
88
88
|
async def unban(self) -> bool:
|
89
89
|
"""Unbans the chat member from the chat.
|
90
90
|
|
91
|
-
:return: True if the member was unbanned successfully, False
|
91
|
+
:return: True if the member was unbanned successfully, False
|
92
|
+
otherwise.
|
92
93
|
"""
|
93
94
|
data = await self.chat.unban(self.user.id)
|
94
95
|
return data
|
pyrobale/objects/enums.py
CHANGED
@@ -10,6 +10,11 @@ class UpdatesTypes(Enum):
|
|
10
10
|
PRE_CHECKOUT_QUERY = "pre_checkout_query"
|
11
11
|
MEMBER_JOINED = "member_joined"
|
12
12
|
MEMBER_LEFT = "member_left"
|
13
|
+
SUCCESSFUL_PAYMENT = "successful_payment"
|
14
|
+
COMMAND = "message"
|
15
|
+
|
16
|
+
|
17
|
+
|
13
18
|
|
14
19
|
|
15
20
|
class ChatAction(Enum):
|
@@ -18,6 +23,9 @@ class ChatAction(Enum):
|
|
18
23
|
TYPING = "typing"
|
19
24
|
PHOTO = "upload_photo"
|
20
25
|
VIDEO = "upload_video"
|
26
|
+
REVORDVIDEO = "record_video"
|
27
|
+
VOICE = "upload_voice"
|
28
|
+
DOCUMENT = "upload_document"
|
21
29
|
|
22
30
|
|
23
31
|
class ChatType(Enum):
|
@@ -15,7 +15,7 @@ class InlineKeyboardMarkup:
|
|
15
15
|
callback_data: Optional[str] = None,
|
16
16
|
url: Optional[str] = None,
|
17
17
|
web_app: Optional[Union["WebAppInfo", str]] = None,
|
18
|
-
copy_text_button: Optional["CopyTextButton"] = None,
|
18
|
+
copy_text_button: Optional[Union["CopyTextButton", str]] = None,
|
19
19
|
**kwargs
|
20
20
|
) -> "InlineKeyboardMarkup":
|
21
21
|
"""Adds a button to the inline keyboard.
|
@@ -24,8 +24,8 @@ class InlineKeyboardMarkup:
|
|
24
24
|
text (str): The text to display on the button.
|
25
25
|
callback_data (str, optional): The callback data to send when the button is clicked.
|
26
26
|
url (str, optional): The URL to open when the button is clicked.
|
27
|
-
web_app (WebAppInfo, optional): The web app to open when the button is clicked.
|
28
|
-
copy_text_button (CopyTextButton, optional): The copy text button to add to the button.
|
27
|
+
web_app (WebAppInfo OR string, optional): The web app to open when the button is clicked.
|
28
|
+
copy_text_button (CopyTextButton OR string, optional): The copy text button to add to the button.
|
29
29
|
|
30
30
|
Returns:
|
31
31
|
InlineKeyboardMarkup: The updated InlineKeyboardMarkup object.
|
@@ -59,7 +59,14 @@ class InlineKeyboardMarkup:
|
|
59
59
|
"web_app must be a string URL or an object with to_dict() method."
|
60
60
|
)
|
61
61
|
elif copy_text_button:
|
62
|
-
|
62
|
+
if isinstance(copy_text_button, str):
|
63
|
+
button["copy_text"] = {"text": copy_text_button}
|
64
|
+
elif hasattr(copy_text_button, "text"):
|
65
|
+
button["copy_text"] = {"text": copy_text_button.text}
|
66
|
+
else:
|
67
|
+
raise ValueError(
|
68
|
+
"copy_text_button must be a string or an object with a 'text' attribute."
|
69
|
+
)
|
63
70
|
|
64
71
|
if not self.inline_keyboard:
|
65
72
|
self.inline_keyboard.append([])
|
pyrobale/objects/message.py
CHANGED
@@ -24,8 +24,7 @@ if TYPE_CHECKING:
|
|
24
24
|
from ..client import Client
|
25
25
|
from ..objects.chat import Chat
|
26
26
|
from ..objects.user import User
|
27
|
-
import
|
28
|
-
import aiohttp
|
27
|
+
from ..objects.inlinekeyboardmarkup import InlineKeyboardMarkup
|
29
28
|
|
30
29
|
|
31
30
|
class Message:
|
@@ -125,8 +124,11 @@ class Message:
|
|
125
124
|
reply_markup: Inline keyboard markup
|
126
125
|
**kwargs: Additional keyword arguments
|
127
126
|
"""
|
127
|
+
self.client: Client = kwargs.get("kwargs", {}).get("client")
|
128
128
|
self.id: int = message_id
|
129
|
-
self.user: "User" =
|
129
|
+
self.user: "User" = (
|
130
|
+
User(**from_user, kwargs={"client": self.client}) if from_user else None
|
131
|
+
)
|
130
132
|
self.date: int = date
|
131
133
|
self.chat: Optional["Chat"] = (
|
132
134
|
chat if isinstance(chat, Chat) else Chat(**chat) if chat else None
|
@@ -153,7 +155,7 @@ class Message:
|
|
153
155
|
self.successful_payment: Optional["SuccessfulPayment"] = successful_payment
|
154
156
|
self.web_app_data: Optional["WebAppData"] = web_app_data
|
155
157
|
self.reply_markup: Optional["InlineKeyboardMarkup"] = reply_markup
|
156
|
-
|
158
|
+
|
157
159
|
|
158
160
|
async def reply(
|
159
161
|
self,
|
@@ -168,13 +170,16 @@ class Message:
|
|
168
170
|
"""
|
169
171
|
if self.chat and self.chat.id:
|
170
172
|
await self.client.send_message(
|
171
|
-
self.chat.id,
|
173
|
+
self.chat.id,
|
174
|
+
text,
|
175
|
+
reply_to_message_id=self.id,
|
176
|
+
reply_markup=reply_markup,
|
172
177
|
)
|
173
178
|
|
174
179
|
async def edit(
|
175
180
|
self,
|
176
181
|
text: str,
|
177
|
-
reply_markup:
|
182
|
+
reply_markup: Optional[InlineKeyboardMarkup] = None,
|
178
183
|
):
|
179
184
|
"""Edit the current message text.
|
180
185
|
|
@@ -216,7 +221,11 @@ class Message:
|
|
216
221
|
"""
|
217
222
|
if self.chat and self.chat.id:
|
218
223
|
await self.client.send_photo(
|
219
|
-
self.chat.id,
|
224
|
+
self.chat.id,
|
225
|
+
photo=photo,
|
226
|
+
caption=caption,
|
227
|
+
reply_to_message_id=self.id,
|
228
|
+
reply_markup=reply_markup,
|
220
229
|
)
|
221
230
|
|
222
231
|
async def reply_video(
|
@@ -234,7 +243,11 @@ class Message:
|
|
234
243
|
"""
|
235
244
|
if self.chat and self.chat.id:
|
236
245
|
await self.client.send_video(
|
237
|
-
self.chat.id,
|
246
|
+
self.chat.id,
|
247
|
+
video=video,
|
248
|
+
caption=caption,
|
249
|
+
reply_to_message_id=self.id,
|
250
|
+
reply_markup=reply_markup,
|
238
251
|
)
|
239
252
|
|
240
253
|
async def reply_audio(
|
@@ -252,7 +265,11 @@ class Message:
|
|
252
265
|
"""
|
253
266
|
if self.chat and self.chat.id:
|
254
267
|
await self.client.send_audio(
|
255
|
-
self.chat.id,
|
268
|
+
self.chat.id,
|
269
|
+
audio=audio,
|
270
|
+
caption=caption,
|
271
|
+
reply_to_message_id=self.id,
|
272
|
+
reply_markup=reply_markup,
|
256
273
|
)
|
257
274
|
|
258
275
|
async def reply_document(
|
@@ -273,6 +290,7 @@ class Message:
|
|
273
290
|
self.chat.id,
|
274
291
|
document=document,
|
275
292
|
caption=caption,
|
293
|
+
reply_to_message_id=self.id,
|
276
294
|
reply_markup=reply_markup,
|
277
295
|
)
|
278
296
|
|
@@ -296,6 +314,7 @@ class Message:
|
|
296
314
|
self,
|
297
315
|
latitude: float,
|
298
316
|
longitude: float,
|
317
|
+
horizontal_accuracy: Optional[float] = None,
|
299
318
|
reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
|
300
319
|
):
|
301
320
|
"""Reply with a location to the current message.
|
@@ -310,6 +329,8 @@ class Message:
|
|
310
329
|
self.chat.id,
|
311
330
|
latitude=latitude,
|
312
331
|
longitude=longitude,
|
332
|
+
horizontal_accuracy=horizontal_accuracy,
|
333
|
+
reply_to_message_id=self.id,
|
313
334
|
reply_markup=reply_markup,
|
314
335
|
)
|
315
336
|
|
@@ -331,6 +352,7 @@ class Message:
|
|
331
352
|
self.chat.id,
|
332
353
|
phone_number=phone_number,
|
333
354
|
first_name=first_name,
|
355
|
+
reply_to_message_id=self.id,
|
334
356
|
reply_markup=reply_markup,
|
335
357
|
)
|
336
358
|
|
@@ -340,9 +362,7 @@ class Message:
|
|
340
362
|
description: str,
|
341
363
|
payload: str,
|
342
364
|
provider_token: str,
|
343
|
-
|
344
|
-
prices: list,
|
345
|
-
reply_markup: Union["ReplyKeyboardMarkup", "InlineKeyboardMarkup"] = None,
|
365
|
+
prices: list
|
346
366
|
):
|
347
367
|
"""Reply with an invoice to the current message.
|
348
368
|
|
@@ -351,7 +371,6 @@ class Message:
|
|
351
371
|
description: Product description
|
352
372
|
payload: Bot-defined invoice payload
|
353
373
|
provider_token: Payment provider token
|
354
|
-
currency: Three-letter ISO 4217 currency code
|
355
374
|
prices: Price breakdown (amount in smallest units)
|
356
375
|
reply_markup: Optional keyboard markup
|
357
376
|
"""
|
@@ -362,7 +381,5 @@ class Message:
|
|
362
381
|
description=description,
|
363
382
|
payload=payload,
|
364
383
|
provider_token=provider_token,
|
365
|
-
|
366
|
-
prices=prices,
|
367
|
-
reply_markup=reply_markup,
|
384
|
+
prices=prices
|
368
385
|
)
|
pyrobale/objects/user.py
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
-
from typing import Optional,
|
2
|
-
|
3
|
-
|
4
|
-
import
|
1
|
+
from typing import Optional, TYPE_CHECKING
|
2
|
+
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
from ..client import Client
|
5
5
|
|
6
6
|
|
7
7
|
class User:
|
8
8
|
def __init__(
|
9
9
|
self,
|
10
|
-
id: int,
|
11
|
-
is_bot: bool,
|
12
|
-
first_name: str,
|
13
|
-
last_name: Optional[str],
|
14
|
-
username: Optional[str],
|
10
|
+
id: int = None,
|
11
|
+
is_bot: bool = None,
|
12
|
+
first_name: str = None,
|
13
|
+
last_name: Optional[str] = None,
|
14
|
+
username: Optional[str] = None,
|
15
|
+
**kwargs
|
15
16
|
):
|
16
17
|
self.id = id
|
17
18
|
self.is_bot = is_bot
|
18
19
|
self.first_name = first_name
|
19
20
|
self.last_name = last_name
|
20
21
|
self.username = username
|
22
|
+
self.client: Optional["Client"] = kwargs.get("client", None)
|
pyrobale/objects/utils.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
from ..exceptions import *
|
2
2
|
import aiohttp
|
3
3
|
|
4
4
|
|
@@ -9,13 +9,33 @@ def build_api_url(base: str, endpoint: str) -> str:
|
|
9
9
|
async def make_post(url: str, data: dict = None, headers: dict = None) -> dict:
|
10
10
|
async with aiohttp.ClientSession() as session:
|
11
11
|
async with session.post(url, json=data, headers=headers) as response:
|
12
|
-
|
12
|
+
json = await response.json()
|
13
|
+
if json['ok']:
|
14
|
+
if 'result' in json.keys():
|
15
|
+
return json
|
16
|
+
else:
|
17
|
+
if json['error_code'] == 404:
|
18
|
+
raise NotFoundException(f"Error not found 404 : {json['description'] if json['description'] else 'No description returned in error'}")
|
19
|
+
elif json['error_code'] == 403:
|
20
|
+
raise ForbiddenException(f"Error Forbidden 403 : {json['description'] if json['description'] else 'No description returned in error'}")
|
21
|
+
else:
|
22
|
+
raise PyroBaleException(f"unknown error : {json['description'] if json['description'] else 'No description!'}")
|
13
23
|
|
14
24
|
|
15
25
|
async def make_get(url: str, headers: dict = None) -> dict:
|
16
26
|
async with aiohttp.ClientSession() as session:
|
17
27
|
async with session.get(url, headers=headers) as response:
|
18
|
-
|
28
|
+
json = await response.json()
|
29
|
+
if json['ok']:
|
30
|
+
if 'result' in json.keys():
|
31
|
+
return json
|
32
|
+
else:
|
33
|
+
if json['error_code'] == 404:
|
34
|
+
raise NotFoundException(f"Error not found 404 : {json['description'] if json['description'] else 'No description returned in error'}")
|
35
|
+
elif json['error_code'] == 403:
|
36
|
+
raise ForbiddenException(f"Error Forbidden 403 : {json['description'] if json['description'] else 'No description returned in error'}")
|
37
|
+
else:
|
38
|
+
raise PyroBaleException(f"unknown error : {json['description'] if json['description'] else 'No description'}")
|
19
39
|
|
20
40
|
|
21
41
|
def pythonize(dictionary: dict) -> dict:
|
@@ -0,0 +1,152 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pyrobale
|
3
|
+
Version: 0.3.8
|
4
|
+
Summary: A python wrapper for bale api
|
5
|
+
Project-URL: github, https://github.com/pyrobale/pyrobale
|
6
|
+
Project-URL: website, https://pyrobale.github.io
|
7
|
+
Author-email: Ali Safamanesh <darg.q.a.a@gmail.com>, Aydin Rahbaran <codewizaard9@gmail.com>
|
8
|
+
License: MIT License
|
9
|
+
|
10
|
+
Copyright (c) 2025 PyroBale Team
|
11
|
+
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
14
|
+
in the Software without restriction, including without limitation the rights
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
17
|
+
furnished to do so, subject to the following conditions:
|
18
|
+
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
20
|
+
copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
|
+
SOFTWARE.
|
29
|
+
License-File: LICENSE
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
31
|
+
Classifier: Operating System :: OS Independent
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
33
|
+
Requires-Python: >=3.9
|
34
|
+
Requires-Dist: aiohttp
|
35
|
+
Description-Content-Type: text/markdown
|
36
|
+
|
37
|
+

|
38
|
+
|
39
|
+
# Bale Bot API Python Library
|
40
|
+
|
41
|
+
A modern, easy-to-use Python wrapper for the Bale Bot API that makes building Bale bots simple and intuitive.
|
42
|
+
|
43
|
+
## Features
|
44
|
+
|
45
|
+
- 🚀 **Simple & Intuitive** - Clean, Pythonic API design
|
46
|
+
- 📨 **Full Message Support** - Text, photos, videos, documents, and more
|
47
|
+
- ⌨️ **Interactive Elements** - Inline keyboards, reply keyboards, and buttons
|
48
|
+
- 🔄 **Real-time Updates** - Webhook and polling support
|
49
|
+
- 📁 **File Handling** - Easy upload and download of media files
|
50
|
+
- 🛡️ **Error Handling** - Comprehensive exception handling
|
51
|
+
- 📖 **Type Hints** - Full typing support for better development experience
|
52
|
+
- ⚡ **Async Support** - asynchronous operations
|
53
|
+
|
54
|
+
## Installation
|
55
|
+
|
56
|
+
```bash
|
57
|
+
pip install pyrobale
|
58
|
+
```
|
59
|
+
|
60
|
+
## Quick Start
|
61
|
+
|
62
|
+
```python
|
63
|
+
from pyrobale.client import Client
|
64
|
+
from pyrobale.objects import Message, UpdatesTypes
|
65
|
+
|
66
|
+
bot = Client("YOUR_BOT_TOKEN")
|
67
|
+
|
68
|
+
@bot.on_message()
|
69
|
+
async def message_handler(message: Message):
|
70
|
+
await message.reply("Hello, world!")
|
71
|
+
|
72
|
+
bot.run()
|
73
|
+
```
|
74
|
+
|
75
|
+
## Examples
|
76
|
+
|
77
|
+
### Conversation Bot
|
78
|
+
```python
|
79
|
+
from pyrobale.objects import *
|
80
|
+
from pyrobale.client import Client, Message, UpdatesTypes
|
81
|
+
|
82
|
+
client = Client("YOUR_BOT_TOKEN")
|
83
|
+
|
84
|
+
async def handle_message(message: Message):
|
85
|
+
if message.text == "/start":
|
86
|
+
await message.reply("Hi! Im a pyrobale RoBot!")
|
87
|
+
await client.wait_for(UpdatesTypes.MESSAGE)
|
88
|
+
await message.reply("Okay! wait_for Test Compeleted")
|
89
|
+
|
90
|
+
client.add_handler(UpdatesTypes.MESSAGE, handle_message)
|
91
|
+
|
92
|
+
client.run()
|
93
|
+
```
|
94
|
+
|
95
|
+
### Echo Bot
|
96
|
+
```python
|
97
|
+
from pyrobale.client import Client
|
98
|
+
from pyrobale.objects import Message, UpdatesTypes
|
99
|
+
|
100
|
+
bot = Client("YOUR_BOT_TOKEN")
|
101
|
+
|
102
|
+
@bot.on_message()
|
103
|
+
async def message_handler(message: Message):
|
104
|
+
await message.reply(message.text)
|
105
|
+
|
106
|
+
bot.run()
|
107
|
+
```
|
108
|
+
|
109
|
+
### Inline Keyboard
|
110
|
+
```python
|
111
|
+
from pyrobale.client import Client
|
112
|
+
from pyrobale.objects import Message, UpdatesTypes, InlineKeyboardButton, InlineKeyboardMarkup, CopyTextButton
|
113
|
+
|
114
|
+
bot = Client("YOUR_BOT_TOKEN")
|
115
|
+
async def message_handler(message: Message):
|
116
|
+
buttons = InlineKeyboardMarkup()
|
117
|
+
buttons.add_button("URL", url="https://google.com")
|
118
|
+
buttons.add_button("Callback", callback_data="callback")
|
119
|
+
buttons.add_row()
|
120
|
+
buttons.add_button("WebApp", web_app="https://daradege.ir")
|
121
|
+
buttons.add_button("Copy", copy_text_button=CopyTextButton("TEXT"))
|
122
|
+
await message.reply("Hello, world!", reply_markup=buttons)
|
123
|
+
```
|
124
|
+
|
125
|
+
|
126
|
+
## Core Abilities
|
127
|
+
|
128
|
+
- **Message Handling** - Process text, commands, and media messages
|
129
|
+
- **Callback Queries** - Handle inline keyboard interactions
|
130
|
+
- **File Operations** - Send and receive photos, videos, documents
|
131
|
+
- **Chat Management** - Get chat info, member management
|
132
|
+
- **Custom Keyboards** - Create interactive user interfaces
|
133
|
+
- **Webhook Support** - Production-ready webhook handling
|
134
|
+
- **Middleware Support** - Add custom processing layers
|
135
|
+
|
136
|
+
## Documentation
|
137
|
+
|
138
|
+
For detailed documentation and advanced usage, visit our [documentation site](https://pyrobale.readthedocs.io).
|
139
|
+
|
140
|
+
## Contributing
|
141
|
+
|
142
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
143
|
+
|
144
|
+
## License
|
145
|
+
|
146
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
147
|
+
|
148
|
+
## Support
|
149
|
+
|
150
|
+
- 📖 [Documentation](https://pyrobale.readthedocs.io)
|
151
|
+
- 🐛 [Issue Tracker](https://github.com/pyrobale/pyrobale/issues)
|
152
|
+
- 💬 [Discussions](https://github.com/pyrobale/pyrobale/discussions)
|
@@ -1,28 +1,32 @@
|
|
1
|
-
pyrobale/__init__.py,sha256=
|
2
|
-
pyrobale/
|
3
|
-
pyrobale/
|
4
|
-
pyrobale/exceptions/
|
5
|
-
pyrobale/
|
1
|
+
pyrobale/__init__.py,sha256=tC4gr6RIg4tYdzoBDFQCU2CDigXytc-MQ7yH6BJzTzM,3651
|
2
|
+
pyrobale/StateMachine/__init__.py,sha256=TRCBwcr4UlnpU2Olik0vOtNASUOK7_O6RMAG6RrVYlM,1911
|
3
|
+
pyrobale/client/__init__.py,sha256=xl7TyimdjJLLEPmhpRGV_0-JIN8hCPISmYwle7a6eSI,45539
|
4
|
+
pyrobale/exceptions/__init__.py,sha256=oa412OuokRm9Vf3XlCJLqpZjz9ZcuxAKxnEBvOK7u2M,21
|
5
|
+
pyrobale/exceptions/common.py,sha256=6ubWjGNmbRbNuzM_ohPuLvGhLdCiCZ-RscEERnv3JMA,273
|
6
|
+
pyrobale/filters/__init__.py,sha256=Q-VFK1U5W9jMWneAqNLNlYSTZI2gjnAkwA-lcqF9GbU,55
|
7
|
+
pyrobale/filters/enum_filters.py,sha256=5kVtmZ1dCbhUx-_T7tPFbgx8KxAz0W3clwCjOvZy5R0,239
|
8
|
+
pyrobale/filters/func_filters.py,sha256=C4cIckRkHk5ISvWFdrvLVFZPmYA1nuNCzC84BpEdkc0,523
|
9
|
+
pyrobale/objects/__init__.py,sha256=uy0xBJc5d-1TnlPD6CgxAaUjBnIvQs-GuAgLeEKoXSQ,2239
|
6
10
|
pyrobale/objects/animation.py,sha256=jpM9V8AOaGLWkcENTDmsxKf57Abf-MArYBLfU6GwkD0,978
|
7
11
|
pyrobale/objects/audio.py,sha256=q14wz5WpC3SgKZkAlH-D9M554RYQNDwuCT2z7v7IZYU,696
|
8
|
-
pyrobale/objects/callbackquery.py,sha256=
|
12
|
+
pyrobale/objects/callbackquery.py,sha256=jALmTVXU6tc6OppTTrhGERCzugzazYrT39AhhGE-UeI,1018
|
9
13
|
pyrobale/objects/chat.py,sha256=gQ1wpmB63Ot51aeSBAiWzbw9lFgCpJjlm9hlYNBQJ88,16566
|
10
|
-
pyrobale/objects/chatmember.py,sha256=
|
14
|
+
pyrobale/objects/chatmember.py,sha256=IyAGmuZZ5HlJVYjrfXEKbLoNc7etMytrK-gOeKKo0CU,6895
|
11
15
|
pyrobale/objects/chatphoto.py,sha256=vOb5xzpr3oBiCloi2_ufBnVlUfmcPqSTmMMMTTBYdJo,533
|
12
16
|
pyrobale/objects/contact.py,sha256=6LDxT5RoGbY5Tsw64lg5-jvKSRmmvOiIJha1HqdTaG4,411
|
13
17
|
pyrobale/objects/copytextbutton.py,sha256=CbFWeY9Ebor7dnHJpQUMB1zYhJWl7b5a2T_cdmo1qQ0,134
|
14
18
|
pyrobale/objects/document.py,sha256=cI9_McPzySNKZaQmOma9eX75a3YsyzkVrLvUBDIuwsA,661
|
15
|
-
pyrobale/objects/enums.py,sha256
|
19
|
+
pyrobale/objects/enums.py,sha256=-8SQ6jvAk4n5oYTSU--E3rZ2kGABy51SbK9QruMQf-Y,720
|
16
20
|
pyrobale/objects/file.py,sha256=4PBfjouP0knd1vFDNs7mx_jwBoDQVBKS7ESjzF4Y6E8,360
|
17
21
|
pyrobale/objects/inlinekeyboardbutton.py,sha256=w4HehdisD7RQodS66gG-DJjaf0gO2U-6wYaVXaatTN8,617
|
18
|
-
pyrobale/objects/inlinekeyboardmarkup.py,sha256=
|
22
|
+
pyrobale/objects/inlinekeyboardmarkup.py,sha256=pMcJDCI3iTvn7OZFPOCV_xnsq9Atx7ixdfKyObdGG1M,3254
|
19
23
|
pyrobale/objects/inputfile.py,sha256=vjw96uJZzp4UargWd2p3OQKyvTpHu2PH_dR_RwwshRI,621
|
20
24
|
pyrobale/objects/inputmedias.py,sha256=2h5YKWNjrrLD1QKZ5J_iOfpCZIRpAZST9q7eBd8edo0,6248
|
21
25
|
pyrobale/objects/invoice.py,sha256=hI225mtsSSV7fYre6aFHp-o1NxUT8MLugJAD6NfAeIs,375
|
22
26
|
pyrobale/objects/keyboardbutton.py,sha256=J7c1ma7swjk3zkgcD7vnMdIMsBGExicmbm1bnP_puzU,459
|
23
27
|
pyrobale/objects/labeledprice.py,sha256=d-fbOLzpkBslfor13BXGeVoySKCcSxsXY4QVwub2Z9o,228
|
24
28
|
pyrobale/objects/location.py,sha256=w_9sRJRntLpNbn8Jk6JhRJVVigD9Bd4BxbjFyglxWhU,143
|
25
|
-
pyrobale/objects/message.py,sha256=
|
29
|
+
pyrobale/objects/message.py,sha256=cCe0qU0ClGc66S7tW6TexnDzqyAafeKgN_h0h8UZMfs,14532
|
26
30
|
pyrobale/objects/messageid.py,sha256=DrWKV8y9m9H8G_Fj68KgiJKwDJOGduNJGJ-Dyn8N580,95
|
27
31
|
pyrobale/objects/photosize.py,sha256=I4hnmi46uoU-cW7hPN_tTT9kn0u80BtG5QJ3uRjoUiE,298
|
28
32
|
pyrobale/objects/precheckoutquery.py,sha256=Rtjh1qqRc9TRZMJU1W5r0B8y7K5dayLMXX6WH9h1Ul4,470
|
@@ -31,13 +35,13 @@ pyrobale/objects/sticker.py,sha256=yLzWAm1fikMVISExdCG0R-rVu1_M31LLw6sHt0sBehE,3
|
|
31
35
|
pyrobale/objects/stickerset.py,sha256=xlSdlnb5TCzI_MCkB_bJsZPgELVevbO7R3BAYN2jIt8,269
|
32
36
|
pyrobale/objects/successfulpayment.py,sha256=aEAApcd60dByqPw253jEifG_CVsbLYiphB1ep3CEm2E,502
|
33
37
|
pyrobale/objects/update.py,sha256=cDR9hpcC8r4bJjixgMQD84Dg_-8ZrlZq1HninVVVDuQ,716
|
34
|
-
pyrobale/objects/user.py,sha256=
|
35
|
-
pyrobale/objects/utils.py,sha256=
|
38
|
+
pyrobale/objects/user.py,sha256=uCvG3k7rIbGP73fFQt_uy7-shS-BRWAL2aEcCEZWyWY,554
|
39
|
+
pyrobale/objects/utils.py,sha256=Odyy6y9wKexYBUrk-iErtrV-iEHHOWw-32yTU_iS_AU,2288
|
36
40
|
pyrobale/objects/video.py,sha256=DuZMGHio_w8yQvi87Vc3XpJOpEaltkM4_bNRSeocPZo,509
|
37
41
|
pyrobale/objects/voice.py,sha256=ZdsJFH2IsBwelEk4rb4oZfX9xrfJ2_DgfjsMc0e4Tmg,148
|
38
42
|
pyrobale/objects/webappdata.py,sha256=QlZlCa8Mylt8VmcdgdoHeyita5CVnz2WsT1yueEY1tY,78
|
39
43
|
pyrobale/objects/webappinfo.py,sha256=qnTvfNqx91Yzbc1gO5y4XQ3w6g0RpMUqMuF5wk_EZMc,75
|
40
|
-
pyrobale-0.3.
|
41
|
-
pyrobale-0.3.
|
42
|
-
pyrobale-0.3.
|
43
|
-
pyrobale-0.3.
|
44
|
+
pyrobale-0.3.8.dist-info/METADATA,sha256=386ZydRqEYd61G8-SgfJH_3eTz4YnNFgcb0l-nhp80A,5262
|
45
|
+
pyrobale-0.3.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
46
|
+
pyrobale-0.3.8.dist-info/licenses/LICENSE,sha256=rf_1ZkId-bcjw1kHBq6bV5t5TVob3RgjUyjfKr1CHAk,1070
|
47
|
+
pyrobale-0.3.8.dist-info/RECORD,,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
MIT License
|
2
2
|
|
3
|
-
Copyright (c) 2025
|
3
|
+
Copyright (c) 2025 PyroBale Team
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
21
|
+
SOFTWARE.
|