waclient 0.1.3__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.
waclient-0.1.3/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Surenthar S
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: waclient
3
+ Version: 0.1.3
4
+ Summary: Simplified Python SDK for WhatsApp Business Cloud API
5
+ Author-email: Surenthar <surentharsenthilkumar2003@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Bug Reports, https://github.com/Start-up-Kraft/waclient/issues
8
+ Project-URL: Source, https://github.com/Start-up-Kraft/waclient
9
+ Project-URL: Documentation, https://github.com/Start-up-Kraft/waclient#readme
10
+ Keywords: whatsapp,business,api,cloud,meta,facebook,messaging
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Communications :: Chat
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: requests>=2.25.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=6.0; extra == "dev"
27
+ Requires-Dist: pytest-cov>=2.0; extra == "dev"
28
+ Requires-Dist: black>=21.0; extra == "dev"
29
+ Requires-Dist: flake8>=3.9; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # WhatsApp Biz
33
+
34
+ **Simplified Python SDK for WhatsApp Business Cloud API**
35
+
36
+ [![PyPI version](https://badge.fury.io/py/waclient.svg)](https://badge.fury.io/py/waclient)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
38
+ [![Python Versions](https://img.shields.io/pypi/pyversions/waclient.svg)](https://pypi.org/project/waclient/)
39
+
40
+ `waclient` is a clean, easy-to-use Python wrapper for the WhatsApp Business Cloud API. It handles authentication, message composition (text, media, interactive), and media management, allowing you to build WhatsApp bots and integrations quickly.
41
+
42
+ ## Features
43
+
44
+ - **Easy Authentication**: Simple client initialization.
45
+ - **Rich Messaging**: Send Text, Image, Video, Audio, Document, Sticker, Location, and Contact messages.
46
+ - **Interactive Elements**: Support for Reply Buttons and List Messages.
47
+ - **Templates**: Full support for WhatsApp Template Messages.
48
+ - **Media Handling**: Upload and retrieve media easily.
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install waclient
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ from waclient import WhatsAppClient
60
+
61
+ client = WhatsAppClient(
62
+ phone_number_id="YOUR_PHONE_ID",
63
+ access_token="YOUR_ACCESS_TOKEN"
64
+ )
65
+
66
+ client.messages.send_text(to="15551234567", body="Hello form WhatsApp Biz!")
67
+ ```
68
+
69
+ ## Documentation
70
+
71
+ - **[User Manual](USER_MANUAL.md)**: Detailed verification of all features, code examples, and configuration.
72
+ - **[Developer Guide](DEVELOPER_GUIDE.md)**: Setup for contributors, running tests, and project structure.
73
+
74
+ ## Examples
75
+
76
+ Check the `examples/` directory for ready-to-run scripts:
77
+ - `examples/verify_features.py`: comprehensive tour of features.
78
+ - `examples/verify_delivery.py`: delivery status verification.
79
+
80
+ ## License
81
+
82
+ This project is licensed under the MIT License - see the LICENSE file for details.
83
+
84
+ ## Author
85
+
86
+ **Surenthar**
87
+ Email: surentharsenthilkumar2003@gmail.com
@@ -0,0 +1,56 @@
1
+ # WhatsApp Biz
2
+
3
+ **Simplified Python SDK for WhatsApp Business Cloud API**
4
+
5
+ [![PyPI version](https://badge.fury.io/py/waclient.svg)](https://badge.fury.io/py/waclient)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Python Versions](https://img.shields.io/pypi/pyversions/waclient.svg)](https://pypi.org/project/waclient/)
8
+
9
+ `waclient` is a clean, easy-to-use Python wrapper for the WhatsApp Business Cloud API. It handles authentication, message composition (text, media, interactive), and media management, allowing you to build WhatsApp bots and integrations quickly.
10
+
11
+ ## Features
12
+
13
+ - **Easy Authentication**: Simple client initialization.
14
+ - **Rich Messaging**: Send Text, Image, Video, Audio, Document, Sticker, Location, and Contact messages.
15
+ - **Interactive Elements**: Support for Reply Buttons and List Messages.
16
+ - **Templates**: Full support for WhatsApp Template Messages.
17
+ - **Media Handling**: Upload and retrieve media easily.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install waclient
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```python
28
+ from waclient import WhatsAppClient
29
+
30
+ client = WhatsAppClient(
31
+ phone_number_id="YOUR_PHONE_ID",
32
+ access_token="YOUR_ACCESS_TOKEN"
33
+ )
34
+
35
+ client.messages.send_text(to="15551234567", body="Hello form WhatsApp Biz!")
36
+ ```
37
+
38
+ ## Documentation
39
+
40
+ - **[User Manual](USER_MANUAL.md)**: Detailed verification of all features, code examples, and configuration.
41
+ - **[Developer Guide](DEVELOPER_GUIDE.md)**: Setup for contributors, running tests, and project structure.
42
+
43
+ ## Examples
44
+
45
+ Check the `examples/` directory for ready-to-run scripts:
46
+ - `examples/verify_features.py`: comprehensive tour of features.
47
+ - `examples/verify_delivery.py`: delivery status verification.
48
+
49
+ ## License
50
+
51
+ This project is licensed under the MIT License - see the LICENSE file for details.
52
+
53
+ ## Author
54
+
55
+ **Surenthar**
56
+ Email: surentharsenthilkumar2003@gmail.com
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "waclient"
7
+ version = "0.1.3"
8
+ description = "Simplified Python SDK for WhatsApp Business Cloud API"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = "MIT"
12
+ authors = [
13
+ {name = "Surenthar", email = "surentharsenthilkumar2003@gmail.com"},
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Topic :: Communications :: Chat",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.7",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ ]
27
+ keywords = ["whatsapp", "business", "api", "cloud", "meta", "facebook", "messaging"]
28
+ dependencies = [
29
+ "requests>=2.25.0",
30
+ ]
31
+
32
+ [project.urls]
33
+ "Bug Reports" = "https://github.com/Start-up-Kraft/waclient/issues"
34
+ "Source" = "https://github.com/Start-up-Kraft/waclient"
35
+ "Documentation" = "https://github.com/Start-up-Kraft/waclient#readme"
36
+
37
+ [project.optional-dependencies]
38
+ dev = [
39
+ "pytest>=6.0",
40
+ "pytest-cov>=2.0",
41
+ "black>=21.0",
42
+ "flake8>=3.9",
43
+ ]
44
+
45
+ [tool.setuptools]
46
+ packages = ["waclient"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,143 @@
1
+ """
2
+ Basic tests for whatsapp-biz package
3
+ """
4
+
5
+
6
+ def test_import():
7
+ """Test if package imports correctly"""
8
+ try:
9
+ from waclient import WhatsAppClient
10
+
11
+ print("[PASS] Import successful!")
12
+ return True
13
+ except ImportError as e:
14
+ print(f"[FAIL] Import failed: {e}")
15
+ return False
16
+
17
+
18
+ def test_client_creation():
19
+ """Test if client can be instantiated"""
20
+ try:
21
+ from waclient import WhatsAppClient
22
+
23
+ client = WhatsAppClient(
24
+ phone_number_id="461166093735990",
25
+ access_token="EAAfLlnmBVq4BO75McWDhNHgL1DW9LKmdOCmLmlQbtjZBdEZCt65ub7z35gBW9gFiRjJpZC3LZA9cSTZC5Uw9lpxz3xGSyDai1FoKZAdqtRZA2huRNHrv3ymxfUljrQZAZCMs7zGEf7vzJLktSoLsZA83BHZBt9H3M06sl5ETgz4YZC7ToCBZASwnwAUC8gxGndieOSv5Y16oxhqTWPStgseH6",
26
+ )
27
+
28
+ print("[PASS] Client created successfully!")
29
+ print(f" Phone ID: {client.phone_number_id}")
30
+ print(f" Base URL: {client.base_url}")
31
+ return True
32
+ except Exception as e:
33
+ print(f"[FAIL] Client creation failed: {e}")
34
+ return False
35
+
36
+
37
+ def test_message_builder():
38
+ """Test message builders"""
39
+ try:
40
+ from waclient.messages import MessageBuilder
41
+
42
+ builder = MessageBuilder()
43
+
44
+ # Test text message
45
+ msg = builder.text_message("919342585854", "Hello!")
46
+ assert msg["type"] == "text"
47
+ assert msg["text"]["body"] == "Hello!"
48
+
49
+ print("[PASS] Message builder works!")
50
+ return True
51
+ except Exception as e:
52
+ print(f"[FAIL] Message builder failed: {e}")
53
+ return False
54
+
55
+
56
+ def test_template_builder():
57
+ """Test template builders"""
58
+ try:
59
+ from waclient.templates import TemplateBuilder
60
+
61
+ component = TemplateBuilder.body_parameters("value1", "value2")
62
+ assert component["type"] == "body"
63
+ assert len(component["parameters"]) == 2
64
+
65
+ print("[PASS] Template builder works!")
66
+ return True
67
+ except Exception as e:
68
+ print(f"[FAIL] Template builder failed: {e}")
69
+ return False
70
+
71
+
72
+ def test_utils():
73
+ """Test utility functions"""
74
+ try:
75
+ from waclient.utils import format_phone_number, validate_phone_number
76
+
77
+ # Test phone formatting
78
+ phone = format_phone_number("9342585854")
79
+ assert phone == "919342585854"
80
+
81
+ # Test validation
82
+ assert validate_phone_number("919342585854") == True
83
+
84
+ print("[PASS] Utils work!")
85
+ return True
86
+ except Exception as e:
87
+ print(f"[FAIL] Utils failed: {e}")
88
+ return False
89
+
90
+
91
+ def test_exceptions():
92
+ """Test custom exceptions"""
93
+ try:
94
+ from waclient.exceptions import (
95
+ WhatsAppError,
96
+ AuthenticationError,
97
+ MessageError,
98
+ MediaError,
99
+ )
100
+
101
+ # Test exception creation
102
+ error = WhatsAppError("Test error")
103
+ assert str(error) == "Test error"
104
+
105
+ print("[PASS] Exceptions work!")
106
+ return True
107
+ except Exception as e:
108
+ print(f"[FAIL] Exceptions test failed: {e}")
109
+ return False
110
+
111
+
112
+ if __name__ == "__main__":
113
+ print("=" * 50)
114
+ print("[TEST] Testing whatsapp-biz Package")
115
+ print("=" * 50)
116
+
117
+ tests = [
118
+ test_import,
119
+ test_client_creation,
120
+ test_message_builder,
121
+ test_template_builder,
122
+ test_utils,
123
+ test_exceptions,
124
+ ]
125
+
126
+ passed = 0
127
+ failed = 0
128
+
129
+ for test in tests:
130
+ print(f"\n[RUN] Running: {test.__name__}")
131
+ try:
132
+ if test():
133
+ passed += 1
134
+ else:
135
+ failed += 1
136
+ except Exception as e:
137
+ print(f"[FAIL] Test crashed: {e}")
138
+ failed += 1
139
+
140
+ print("\n" + "=" * 50)
141
+ print(f"[PASS] Passed: {passed}")
142
+ print(f"[FAIL] Failed: {failed}")
143
+ print("=" * 50)
File without changes
File without changes
File without changes
@@ -0,0 +1,22 @@
1
+ """WhatsApp Business Cloud API - Simplified Python SDK"""
2
+
3
+ __version__ = "0.1.0"
4
+ __author__ = "Your Name"
5
+
6
+ from .client import WhatsAppClient
7
+ from .exceptions import (
8
+ WhatsAppError,
9
+ AuthenticationError,
10
+ MessageError,
11
+ MediaError,
12
+ WebhookError
13
+ )
14
+
15
+ __all__ = [
16
+ "WhatsAppClient",
17
+ "WhatsAppError",
18
+ "AuthenticationError",
19
+ "MessageError",
20
+ "MediaError",
21
+ "WebhookError"
22
+ ]
@@ -0,0 +1,283 @@
1
+ """
2
+ File: waclient/client.py
3
+ Main WhatsApp Business Cloud API Client
4
+ """
5
+
6
+ import requests
7
+ import json
8
+ from typing import Optional, Dict, List, Any
9
+ from .exceptions import WhatsAppError, AuthenticationError, MessageError
10
+ from .messages import MessageBuilder
11
+ from .media import MediaHandler
12
+
13
+
14
+ class WhatsAppClient:
15
+ """
16
+ WhatsApp Business Cloud API Client
17
+
18
+ Example:
19
+ client = WhatsAppClient(
20
+ phone_number_id="461166093735990",
21
+ access_token="EAAfLlnmBVq4BO75McWDhNHgL1DW9LKmdOCmLmlQbtjZBdEZCt65ub7z35gBW9gFiRjJpZC3LZA9cSTZC5Uw9lpxz3xGSyDai1FoKZAdqtRZA2huRNHrv3ymxfUljrQZAZCMs7zGEf7vzJLktSoLsZA83BHZBt9H3M06sl5ETgz4YZC7ToCBZASwnwAUC8gxGndieOSv5Y16oxhqTWPStgseH6"
22
+ )
23
+ client.send_text("919342585854", "Hello!")
24
+ """
25
+
26
+ BASE_URL = "https://graph.facebook.com/v21.0"
27
+
28
+ def __init__(
29
+ self,
30
+ phone_number_id: str,
31
+ access_token: str,
32
+ api_version: str = "v21.0"
33
+ ):
34
+ """
35
+ Initialize WhatsApp Client
36
+
37
+ Args:
38
+ phone_number_id: Your WhatsApp Business phone number ID
39
+ access_token: Your WhatsApp Business API access token
40
+ api_version: API version (default: v21.0)
41
+ """
42
+ self.phone_number_id = phone_number_id
43
+ self.access_token = access_token
44
+ self.api_version = api_version
45
+ self.base_url = f"https://graph.facebook.com/{api_version}"
46
+ self.headers = {
47
+ "Authorization": f"Bearer {access_token}",
48
+ "Content-Type": "application/json"
49
+ }
50
+ self.message_builder = MessageBuilder()
51
+ self.media_handler = MediaHandler(self)
52
+
53
+ def _make_request(
54
+ self,
55
+ method: str,
56
+ endpoint: str,
57
+ data: Optional[Dict] = None,
58
+ params: Optional[Dict] = None
59
+ ) -> Dict:
60
+ """Make HTTP request to WhatsApp API"""
61
+ url = f"{self.base_url}/{self.phone_number_id}/{endpoint}"
62
+
63
+ try:
64
+ response = requests.request(
65
+ method=method,
66
+ url=url,
67
+ headers=self.headers,
68
+ json=data,
69
+ params=params,
70
+ timeout=30
71
+ )
72
+
73
+ response_data = response.json()
74
+
75
+ if response.status_code >= 400:
76
+ error_msg = response_data.get("error", {}).get("message", "Unknown error")
77
+ error_code = response_data.get("error", {}).get("code", 0)
78
+
79
+ if response.status_code == 401:
80
+ raise AuthenticationError(f"Authentication failed: {error_msg}")
81
+ else:
82
+ raise MessageError(f"API Error ({error_code}): {error_msg}")
83
+
84
+ return response_data
85
+
86
+ except requests.exceptions.RequestException as e:
87
+ raise WhatsAppError(f"Request failed: {str(e)}")
88
+
89
+ def send_text(
90
+ self,
91
+ to: str,
92
+ message: str,
93
+ preview_url: bool = False
94
+ ) -> Dict:
95
+ """
96
+ Send a text message
97
+
98
+ Args:
99
+ to: Recipient phone number (with country code, no + sign)
100
+ message: Text message to send
101
+ preview_url: Enable URL preview
102
+
103
+ Returns:
104
+ API response with message ID
105
+
106
+ Example:
107
+ response = client.send_text("919342585854", "Hello World!")
108
+ """
109
+ payload = self.message_builder.text_message(to, message, preview_url)
110
+ return self._make_request("POST", "messages", data=payload)
111
+
112
+ def send_template(
113
+ self,
114
+ to: str,
115
+ template_name: str,
116
+ language: str = "en",
117
+ components: Optional[List[Dict]] = None,
118
+ **kwargs
119
+ ) -> Dict:
120
+ """
121
+ Send a template message
122
+
123
+ Args:
124
+ to: Recipient phone number
125
+ template_name: Approved template name
126
+ language: Template language code (default: en)
127
+ components: Template components (parameters, buttons, etc.)
128
+ **kwargs: Additional template parameters
129
+
130
+ Returns:
131
+ API response with message ID
132
+
133
+ Example:
134
+ client.send_template(
135
+ to="919342585854",
136
+ template_name="order_confirmation",
137
+ language="en",
138
+ components=[{
139
+ "type": "body",
140
+ "parameters": [
141
+ {"type": "text", "text": "Order123"},
142
+ {"type": "text", "text": "₹499"}
143
+ ]
144
+ }]
145
+ )
146
+ """
147
+ payload = self.message_builder.template_message(
148
+ to, template_name, language, components
149
+ )
150
+ return self._make_request("POST", "messages", data=payload)
151
+
152
+ def send_image(
153
+ self,
154
+ to: str,
155
+ image_url: Optional[str] = None,
156
+ image_id: Optional[str] = None,
157
+ caption: Optional[str] = None
158
+ ) -> Dict:
159
+ """
160
+ Send an image message
161
+
162
+ Args:
163
+ to: Recipient phone number
164
+ image_url: Public URL of the image (or use image_id)
165
+ image_id: Media ID from uploaded image
166
+ caption: Optional image caption
167
+
168
+ Returns:
169
+ API response with message ID
170
+ """
171
+ payload = self.message_builder.media_message(
172
+ to, "image", image_url, image_id, caption
173
+ )
174
+ return self._make_request("POST", "messages", data=payload)
175
+
176
+ def send_document(
177
+ self,
178
+ to: str,
179
+ document_url: Optional[str] = None,
180
+ document_id: Optional[str] = None,
181
+ caption: Optional[str] = None,
182
+ filename: Optional[str] = None
183
+ ) -> Dict:
184
+ """Send a document (PDF, DOC, etc.)"""
185
+ payload = self.message_builder.media_message(
186
+ to, "document", document_url, document_id, caption, filename
187
+ )
188
+ return self._make_request("POST", "messages", data=payload)
189
+
190
+ def send_video(
191
+ self,
192
+ to: str,
193
+ video_url: Optional[str] = None,
194
+ video_id: Optional[str] = None,
195
+ caption: Optional[str] = None
196
+ ) -> Dict:
197
+ """Send a video message"""
198
+ payload = self.message_builder.media_message(
199
+ to, "video", video_url, video_id, caption
200
+ )
201
+ return self._make_request("POST", "messages", data=payload)
202
+
203
+ def send_audio(
204
+ self,
205
+ to: str,
206
+ audio_url: Optional[str] = None,
207
+ audio_id: Optional[str] = None
208
+ ) -> Dict:
209
+ """Send an audio message"""
210
+ payload = self.message_builder.media_message(
211
+ to, "audio", audio_url, audio_id
212
+ )
213
+ return self._make_request("POST", "messages", data=payload)
214
+
215
+ def send_location(
216
+ self,
217
+ to: str,
218
+ latitude: float,
219
+ longitude: float,
220
+ name: Optional[str] = None,
221
+ address: Optional[str] = None
222
+ ) -> Dict:
223
+ """Send a location message"""
224
+ payload = self.message_builder.location_message(
225
+ to, latitude, longitude, name, address
226
+ )
227
+ return self._make_request("POST", "messages", data=payload)
228
+
229
+ def send_contacts(
230
+ self,
231
+ to: str,
232
+ contacts: List[Dict]
233
+ ) -> Dict:
234
+ """Send contact card(s)"""
235
+ payload = self.message_builder.contacts_message(to, contacts)
236
+ return self._make_request("POST", "messages", data=payload)
237
+
238
+ def send_interactive(
239
+ self,
240
+ to: str,
241
+ interactive_type: str,
242
+ body_text: str,
243
+ **kwargs
244
+ ) -> Dict:
245
+ """
246
+ Send interactive message (buttons, lists)
247
+
248
+ Args:
249
+ to: Recipient phone number
250
+ interactive_type: 'button' or 'list'
251
+ body_text: Message body text
252
+ **kwargs: Additional parameters (buttons, sections, etc.)
253
+ """
254
+ payload = self.message_builder.interactive_message(
255
+ to, interactive_type, body_text, **kwargs
256
+ )
257
+ return self._make_request("POST", "messages", data=payload)
258
+
259
+ def mark_as_read(self, message_id: str) -> Dict:
260
+ """Mark a message as read"""
261
+ payload = {
262
+ "messaging_product": "whatsapp",
263
+ "status": "read",
264
+ "message_id": message_id
265
+ }
266
+ return self._make_request("POST", "messages", data=payload)
267
+
268
+ def upload_media(self, file_path: str, mime_type: str) -> str:
269
+ """
270
+ Upload media file and get media ID
271
+
272
+ Args:
273
+ file_path: Path to the media file
274
+ mime_type: MIME type (e.g., 'image/jpeg', 'application/pdf')
275
+
276
+ Returns:
277
+ Media ID to use in send methods
278
+ """
279
+ return self.media_handler.upload(file_path, mime_type)
280
+
281
+ def get_media_url(self, media_id: str) -> str:
282
+ """Get download URL for a media ID"""
283
+ return self.media_handler.get_url(media_id)