wappa 0.1.0__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.
Potentially problematic release.
This version of wappa might be problematic. Click here for more details.
- wappa/__init__.py +85 -0
- wappa/api/__init__.py +1 -0
- wappa/api/controllers/__init__.py +10 -0
- wappa/api/controllers/webhook_controller.py +441 -0
- wappa/api/dependencies/__init__.py +15 -0
- wappa/api/dependencies/whatsapp_dependencies.py +220 -0
- wappa/api/dependencies/whatsapp_media_dependencies.py +26 -0
- wappa/api/middleware/__init__.py +7 -0
- wappa/api/middleware/error_handler.py +158 -0
- wappa/api/middleware/owner.py +99 -0
- wappa/api/middleware/request_logging.py +184 -0
- wappa/api/routes/__init__.py +6 -0
- wappa/api/routes/health.py +102 -0
- wappa/api/routes/webhooks.py +211 -0
- wappa/api/routes/whatsapp/__init__.py +15 -0
- wappa/api/routes/whatsapp/whatsapp_interactive.py +429 -0
- wappa/api/routes/whatsapp/whatsapp_media.py +440 -0
- wappa/api/routes/whatsapp/whatsapp_messages.py +195 -0
- wappa/api/routes/whatsapp/whatsapp_specialized.py +516 -0
- wappa/api/routes/whatsapp/whatsapp_templates.py +431 -0
- wappa/api/routes/whatsapp_combined.py +35 -0
- wappa/cli/__init__.py +9 -0
- wappa/cli/main.py +199 -0
- wappa/core/__init__.py +6 -0
- wappa/core/config/__init__.py +5 -0
- wappa/core/config/settings.py +161 -0
- wappa/core/events/__init__.py +41 -0
- wappa/core/events/default_handlers.py +642 -0
- wappa/core/events/event_dispatcher.py +244 -0
- wappa/core/events/event_handler.py +247 -0
- wappa/core/events/webhook_factory.py +219 -0
- wappa/core/factory/__init__.py +15 -0
- wappa/core/factory/plugin.py +68 -0
- wappa/core/factory/wappa_builder.py +326 -0
- wappa/core/logging/__init__.py +5 -0
- wappa/core/logging/context.py +100 -0
- wappa/core/logging/logger.py +343 -0
- wappa/core/plugins/__init__.py +34 -0
- wappa/core/plugins/auth_plugin.py +169 -0
- wappa/core/plugins/cors_plugin.py +128 -0
- wappa/core/plugins/custom_middleware_plugin.py +182 -0
- wappa/core/plugins/database_plugin.py +235 -0
- wappa/core/plugins/rate_limit_plugin.py +183 -0
- wappa/core/plugins/redis_plugin.py +224 -0
- wappa/core/plugins/wappa_core_plugin.py +261 -0
- wappa/core/plugins/webhook_plugin.py +253 -0
- wappa/core/types.py +108 -0
- wappa/core/wappa_app.py +546 -0
- wappa/database/__init__.py +18 -0
- wappa/database/adapter.py +107 -0
- wappa/database/adapters/__init__.py +17 -0
- wappa/database/adapters/mysql_adapter.py +187 -0
- wappa/database/adapters/postgresql_adapter.py +169 -0
- wappa/database/adapters/sqlite_adapter.py +174 -0
- wappa/domain/__init__.py +28 -0
- wappa/domain/builders/__init__.py +5 -0
- wappa/domain/builders/message_builder.py +189 -0
- wappa/domain/entities/__init__.py +5 -0
- wappa/domain/enums/messenger_platform.py +123 -0
- wappa/domain/factories/__init__.py +6 -0
- wappa/domain/factories/media_factory.py +450 -0
- wappa/domain/factories/message_factory.py +497 -0
- wappa/domain/factories/messenger_factory.py +244 -0
- wappa/domain/interfaces/__init__.py +32 -0
- wappa/domain/interfaces/base_repository.py +94 -0
- wappa/domain/interfaces/cache_factory.py +85 -0
- wappa/domain/interfaces/cache_interface.py +199 -0
- wappa/domain/interfaces/expiry_repository.py +68 -0
- wappa/domain/interfaces/media_interface.py +311 -0
- wappa/domain/interfaces/messaging_interface.py +523 -0
- wappa/domain/interfaces/pubsub_repository.py +151 -0
- wappa/domain/interfaces/repository_factory.py +108 -0
- wappa/domain/interfaces/shared_state_repository.py +122 -0
- wappa/domain/interfaces/state_repository.py +123 -0
- wappa/domain/interfaces/tables_repository.py +215 -0
- wappa/domain/interfaces/user_repository.py +114 -0
- wappa/domain/interfaces/webhooks/__init__.py +1 -0
- wappa/domain/models/media_result.py +110 -0
- wappa/domain/models/platforms/__init__.py +15 -0
- wappa/domain/models/platforms/platform_config.py +104 -0
- wappa/domain/services/__init__.py +11 -0
- wappa/domain/services/tenant_credentials_service.py +56 -0
- wappa/messaging/__init__.py +7 -0
- wappa/messaging/whatsapp/__init__.py +1 -0
- wappa/messaging/whatsapp/client/__init__.py +5 -0
- wappa/messaging/whatsapp/client/whatsapp_client.py +417 -0
- wappa/messaging/whatsapp/handlers/__init__.py +13 -0
- wappa/messaging/whatsapp/handlers/whatsapp_interactive_handler.py +653 -0
- wappa/messaging/whatsapp/handlers/whatsapp_media_handler.py +579 -0
- wappa/messaging/whatsapp/handlers/whatsapp_specialized_handler.py +434 -0
- wappa/messaging/whatsapp/handlers/whatsapp_template_handler.py +416 -0
- wappa/messaging/whatsapp/messenger/__init__.py +5 -0
- wappa/messaging/whatsapp/messenger/whatsapp_messenger.py +904 -0
- wappa/messaging/whatsapp/models/__init__.py +61 -0
- wappa/messaging/whatsapp/models/basic_models.py +65 -0
- wappa/messaging/whatsapp/models/interactive_models.py +287 -0
- wappa/messaging/whatsapp/models/media_models.py +215 -0
- wappa/messaging/whatsapp/models/specialized_models.py +304 -0
- wappa/messaging/whatsapp/models/template_models.py +261 -0
- wappa/persistence/cache_factory.py +93 -0
- wappa/persistence/json/__init__.py +14 -0
- wappa/persistence/json/cache_adapters.py +271 -0
- wappa/persistence/json/handlers/__init__.py +1 -0
- wappa/persistence/json/handlers/state_handler.py +250 -0
- wappa/persistence/json/handlers/table_handler.py +263 -0
- wappa/persistence/json/handlers/user_handler.py +213 -0
- wappa/persistence/json/handlers/utils/__init__.py +1 -0
- wappa/persistence/json/handlers/utils/file_manager.py +153 -0
- wappa/persistence/json/handlers/utils/key_factory.py +11 -0
- wappa/persistence/json/handlers/utils/serialization.py +121 -0
- wappa/persistence/json/json_cache_factory.py +76 -0
- wappa/persistence/json/storage_manager.py +285 -0
- wappa/persistence/memory/__init__.py +14 -0
- wappa/persistence/memory/cache_adapters.py +271 -0
- wappa/persistence/memory/handlers/__init__.py +1 -0
- wappa/persistence/memory/handlers/state_handler.py +250 -0
- wappa/persistence/memory/handlers/table_handler.py +280 -0
- wappa/persistence/memory/handlers/user_handler.py +213 -0
- wappa/persistence/memory/handlers/utils/__init__.py +1 -0
- wappa/persistence/memory/handlers/utils/key_factory.py +11 -0
- wappa/persistence/memory/handlers/utils/memory_store.py +317 -0
- wappa/persistence/memory/handlers/utils/ttl_manager.py +235 -0
- wappa/persistence/memory/memory_cache_factory.py +76 -0
- wappa/persistence/memory/storage_manager.py +235 -0
- wappa/persistence/redis/README.md +699 -0
- wappa/persistence/redis/__init__.py +11 -0
- wappa/persistence/redis/cache_adapters.py +285 -0
- wappa/persistence/redis/ops.py +880 -0
- wappa/persistence/redis/redis_cache_factory.py +71 -0
- wappa/persistence/redis/redis_client.py +231 -0
- wappa/persistence/redis/redis_handler/__init__.py +26 -0
- wappa/persistence/redis/redis_handler/state_handler.py +176 -0
- wappa/persistence/redis/redis_handler/table.py +158 -0
- wappa/persistence/redis/redis_handler/user.py +138 -0
- wappa/persistence/redis/redis_handler/utils/__init__.py +12 -0
- wappa/persistence/redis/redis_handler/utils/key_factory.py +32 -0
- wappa/persistence/redis/redis_handler/utils/serde.py +146 -0
- wappa/persistence/redis/redis_handler/utils/tenant_cache.py +268 -0
- wappa/persistence/redis/redis_manager.py +189 -0
- wappa/processors/__init__.py +6 -0
- wappa/processors/base_processor.py +262 -0
- wappa/processors/factory.py +550 -0
- wappa/processors/whatsapp_processor.py +810 -0
- wappa/schemas/__init__.py +6 -0
- wappa/schemas/core/__init__.py +71 -0
- wappa/schemas/core/base_message.py +499 -0
- wappa/schemas/core/base_status.py +322 -0
- wappa/schemas/core/base_webhook.py +312 -0
- wappa/schemas/core/types.py +253 -0
- wappa/schemas/core/webhook_interfaces/__init__.py +48 -0
- wappa/schemas/core/webhook_interfaces/base_components.py +293 -0
- wappa/schemas/core/webhook_interfaces/universal_webhooks.py +348 -0
- wappa/schemas/factory.py +754 -0
- wappa/schemas/webhooks/__init__.py +3 -0
- wappa/schemas/whatsapp/__init__.py +6 -0
- wappa/schemas/whatsapp/base_models.py +285 -0
- wappa/schemas/whatsapp/message_types/__init__.py +93 -0
- wappa/schemas/whatsapp/message_types/audio.py +350 -0
- wappa/schemas/whatsapp/message_types/button.py +267 -0
- wappa/schemas/whatsapp/message_types/contact.py +464 -0
- wappa/schemas/whatsapp/message_types/document.py +421 -0
- wappa/schemas/whatsapp/message_types/errors.py +195 -0
- wappa/schemas/whatsapp/message_types/image.py +424 -0
- wappa/schemas/whatsapp/message_types/interactive.py +430 -0
- wappa/schemas/whatsapp/message_types/location.py +416 -0
- wappa/schemas/whatsapp/message_types/order.py +372 -0
- wappa/schemas/whatsapp/message_types/reaction.py +271 -0
- wappa/schemas/whatsapp/message_types/sticker.py +328 -0
- wappa/schemas/whatsapp/message_types/system.py +317 -0
- wappa/schemas/whatsapp/message_types/text.py +411 -0
- wappa/schemas/whatsapp/message_types/unsupported.py +273 -0
- wappa/schemas/whatsapp/message_types/video.py +344 -0
- wappa/schemas/whatsapp/status_models.py +479 -0
- wappa/schemas/whatsapp/validators.py +454 -0
- wappa/schemas/whatsapp/webhook_container.py +438 -0
- wappa/webhooks/__init__.py +17 -0
- wappa/webhooks/core/__init__.py +71 -0
- wappa/webhooks/core/base_message.py +499 -0
- wappa/webhooks/core/base_status.py +322 -0
- wappa/webhooks/core/base_webhook.py +312 -0
- wappa/webhooks/core/types.py +253 -0
- wappa/webhooks/core/webhook_interfaces/__init__.py +48 -0
- wappa/webhooks/core/webhook_interfaces/base_components.py +293 -0
- wappa/webhooks/core/webhook_interfaces/universal_webhooks.py +441 -0
- wappa/webhooks/factory.py +754 -0
- wappa/webhooks/whatsapp/__init__.py +6 -0
- wappa/webhooks/whatsapp/base_models.py +285 -0
- wappa/webhooks/whatsapp/message_types/__init__.py +93 -0
- wappa/webhooks/whatsapp/message_types/audio.py +350 -0
- wappa/webhooks/whatsapp/message_types/button.py +267 -0
- wappa/webhooks/whatsapp/message_types/contact.py +464 -0
- wappa/webhooks/whatsapp/message_types/document.py +421 -0
- wappa/webhooks/whatsapp/message_types/errors.py +195 -0
- wappa/webhooks/whatsapp/message_types/image.py +424 -0
- wappa/webhooks/whatsapp/message_types/interactive.py +430 -0
- wappa/webhooks/whatsapp/message_types/location.py +416 -0
- wappa/webhooks/whatsapp/message_types/order.py +372 -0
- wappa/webhooks/whatsapp/message_types/reaction.py +271 -0
- wappa/webhooks/whatsapp/message_types/sticker.py +328 -0
- wappa/webhooks/whatsapp/message_types/system.py +317 -0
- wappa/webhooks/whatsapp/message_types/text.py +411 -0
- wappa/webhooks/whatsapp/message_types/unsupported.py +273 -0
- wappa/webhooks/whatsapp/message_types/video.py +344 -0
- wappa/webhooks/whatsapp/status_models.py +479 -0
- wappa/webhooks/whatsapp/validators.py +454 -0
- wappa/webhooks/whatsapp/webhook_container.py +438 -0
- wappa-0.1.0.dist-info/METADATA +269 -0
- wappa-0.1.0.dist-info/RECORD +211 -0
- wappa-0.1.0.dist-info/WHEEL +4 -0
- wappa-0.1.0.dist-info/entry_points.txt +2 -0
- wappa-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Expiry repository interface.
|
|
3
|
+
|
|
4
|
+
Defines contract for TTL-based workflow management in Redis.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import abstractmethod
|
|
8
|
+
from datetime import timedelta
|
|
9
|
+
|
|
10
|
+
from .base_repository import IBaseRepository
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class IExpiryRepository(IBaseRepository):
|
|
14
|
+
"""
|
|
15
|
+
Interface for TTL-based workflow management.
|
|
16
|
+
|
|
17
|
+
Handles expiry triggers and time-based automation with context binding.
|
|
18
|
+
Uses the 'expiry' Redis pool (database 8).
|
|
19
|
+
|
|
20
|
+
This interface mirrors the RedisTrigger implementation:
|
|
21
|
+
- create_expiry_trigger(action, identifier, ttl) -> set(action, identifier, ttl_seconds)
|
|
22
|
+
- delete_expiry_trigger(action, identifier) -> delete(action, identifier)
|
|
23
|
+
- delete_all_expiry_triggers_by_id(identifier) -> delete_all_by_identifier(identifier)
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
async def create_expiry_trigger(
|
|
28
|
+
self, action: str, identifier: str, ttl: timedelta
|
|
29
|
+
) -> str:
|
|
30
|
+
"""
|
|
31
|
+
Create expiry trigger for automated workflow.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
action: Action name to trigger when expired (e.g., "reservation_reminder")
|
|
35
|
+
identifier: Unique identifier for this trigger (e.g., transaction_ref)
|
|
36
|
+
ttl: Time until trigger fires
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Trigger key identifier
|
|
40
|
+
"""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
async def delete_expiry_trigger(self, action: str, identifier: str) -> bool:
|
|
45
|
+
"""
|
|
46
|
+
Delete specific expiry trigger.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
action: Action name of the trigger
|
|
50
|
+
identifier: Unique identifier of the trigger
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
True if trigger was deleted
|
|
54
|
+
"""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
async def delete_all_expiry_triggers_by_id(self, identifier: str) -> bool:
|
|
59
|
+
"""
|
|
60
|
+
Delete all expiry triggers for a specific identifier.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
identifier: Unique identifier to delete all triggers for
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
True if triggers were deleted
|
|
67
|
+
"""
|
|
68
|
+
pass
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Media handling interface for platform-agnostic media operations.
|
|
3
|
+
|
|
4
|
+
This interface defines the contract for media handling operations that can be
|
|
5
|
+
implemented across different messaging platforms (WhatsApp, Telegram, Teams, etc.).
|
|
6
|
+
|
|
7
|
+
Based on existing WhatsAppServiceMedia implementation from handle_media.py
|
|
8
|
+
and WhatsApp Cloud API 2025 specifications for the 4 core endpoints:
|
|
9
|
+
- POST /PHONE_NUMBER_ID/media (upload)
|
|
10
|
+
- GET /MEDIA_ID (get info/URL)
|
|
11
|
+
- DELETE /MEDIA_ID (delete)
|
|
12
|
+
- GET /MEDIA_URL (download)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from abc import ABC, abstractmethod
|
|
16
|
+
from collections.abc import AsyncIterator
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import BinaryIO
|
|
19
|
+
|
|
20
|
+
from wappa.domain.models.media_result import (
|
|
21
|
+
MediaDeleteResult,
|
|
22
|
+
MediaDownloadResult,
|
|
23
|
+
MediaInfoResult,
|
|
24
|
+
MediaUploadResult,
|
|
25
|
+
)
|
|
26
|
+
from wappa.schemas.core.types import PlatformType
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class IMediaHandler(ABC):
|
|
30
|
+
"""
|
|
31
|
+
Platform-agnostic media handling interface.
|
|
32
|
+
|
|
33
|
+
Provides consistent media operations across different messaging platforms
|
|
34
|
+
while abstracting platform-specific implementations.
|
|
35
|
+
|
|
36
|
+
Based on existing WhatsAppServiceMedia methods:
|
|
37
|
+
- upload_media() -> upload_media()
|
|
38
|
+
- get_media_url() -> get_media_info()
|
|
39
|
+
- download_media() -> download_media()
|
|
40
|
+
- delete_media() -> delete_media()
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def platform(self) -> PlatformType:
|
|
46
|
+
"""Get the platform this handler manages."""
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
@abstractmethod
|
|
51
|
+
def tenant_id(self) -> str:
|
|
52
|
+
"""Get the tenant ID this handler serves.
|
|
53
|
+
|
|
54
|
+
Note: In WhatsApp context, this is the phone_number_id.
|
|
55
|
+
Different platforms may use different tenant identifiers.
|
|
56
|
+
"""
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
@abstractmethod
|
|
61
|
+
def supported_media_types(self) -> set[str]:
|
|
62
|
+
"""Get supported MIME types for this platform.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Set of supported MIME type strings
|
|
66
|
+
"""
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def max_file_size(self) -> dict[str, int]:
|
|
72
|
+
"""Get maximum file sizes in bytes by media category.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Dictionary mapping media categories to max sizes in bytes
|
|
76
|
+
Example: {"image": 5242880, "video": 16777216, "audio": 16777216, "document": 104857600}
|
|
77
|
+
"""
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
# Upload Operations (POST /PHONE_NUMBER_ID/media)
|
|
81
|
+
@abstractmethod
|
|
82
|
+
async def upload_media(
|
|
83
|
+
self,
|
|
84
|
+
file_path: str | Path,
|
|
85
|
+
media_type: str | None = None,
|
|
86
|
+
filename: str | None = None,
|
|
87
|
+
) -> MediaUploadResult:
|
|
88
|
+
"""
|
|
89
|
+
Upload media file to platform.
|
|
90
|
+
|
|
91
|
+
Based on existing WhatsAppServiceMedia.upload_media() method.
|
|
92
|
+
Implements POST /PHONE_NUMBER_ID/media endpoint.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
file_path: Path to the file to upload
|
|
96
|
+
media_type: MIME type (auto-detected if None)
|
|
97
|
+
filename: Original filename (extracted from path if None)
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
MediaUploadResult with upload status and media ID
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
FileNotFoundError: If file doesn't exist
|
|
104
|
+
ValueError: If MIME type unsupported or file too large
|
|
105
|
+
Platform-specific exceptions for API failures
|
|
106
|
+
"""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
async def upload_media_from_bytes(
|
|
111
|
+
self, file_data: bytes, media_type: str, filename: str
|
|
112
|
+
) -> MediaUploadResult:
|
|
113
|
+
"""
|
|
114
|
+
Upload media from bytes data.
|
|
115
|
+
|
|
116
|
+
Extension of existing upload functionality for in-memory files.
|
|
117
|
+
Implements POST /PHONE_NUMBER_ID/media endpoint.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
file_data: Binary file data
|
|
121
|
+
media_type: MIME type of the data
|
|
122
|
+
filename: Filename for the upload
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
MediaUploadResult with upload status and media ID
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
ValueError: If MIME type unsupported or file too large
|
|
129
|
+
Platform-specific exceptions for API failures
|
|
130
|
+
"""
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
@abstractmethod
|
|
134
|
+
async def upload_media_from_stream(
|
|
135
|
+
self,
|
|
136
|
+
file_stream: BinaryIO,
|
|
137
|
+
media_type: str,
|
|
138
|
+
filename: str,
|
|
139
|
+
file_size: int | None = None,
|
|
140
|
+
) -> MediaUploadResult:
|
|
141
|
+
"""
|
|
142
|
+
Upload media from file stream.
|
|
143
|
+
|
|
144
|
+
Extension of existing upload functionality for streaming uploads.
|
|
145
|
+
Implements POST /PHONE_NUMBER_ID/media endpoint.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
file_stream: Binary file stream
|
|
149
|
+
media_type: MIME type of the data
|
|
150
|
+
filename: Filename for the upload
|
|
151
|
+
file_size: Size of the file (for progress tracking)
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
MediaUploadResult with upload status and media ID
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
ValueError: If MIME type unsupported or file too large
|
|
158
|
+
Platform-specific exceptions for API failures
|
|
159
|
+
"""
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
# Retrieval Operations (GET /MEDIA_ID)
|
|
163
|
+
@abstractmethod
|
|
164
|
+
async def get_media_info(self, media_id: str) -> MediaInfoResult:
|
|
165
|
+
"""
|
|
166
|
+
Get media information by ID.
|
|
167
|
+
|
|
168
|
+
Based on existing WhatsAppServiceMedia.get_media_url() method.
|
|
169
|
+
Implements GET /MEDIA_ID endpoint.
|
|
170
|
+
|
|
171
|
+
WhatsApp API Response:
|
|
172
|
+
{
|
|
173
|
+
"messaging_product": "whatsapp",
|
|
174
|
+
"url": "<URL>",
|
|
175
|
+
"mime_type": "<MIME_TYPE>",
|
|
176
|
+
"sha256": "<HASH>",
|
|
177
|
+
"file_size": "<FILE_SIZE>",
|
|
178
|
+
"id": "<MEDIA_ID>"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
media_id: Platform-specific media identifier
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
MediaInfoResult with media info or error details
|
|
186
|
+
|
|
187
|
+
Note:
|
|
188
|
+
URLs expire after 5 minutes in WhatsApp Cloud API.
|
|
189
|
+
Call this method again if URL expires.
|
|
190
|
+
"""
|
|
191
|
+
pass
|
|
192
|
+
|
|
193
|
+
# Download Operations (GET /MEDIA_URL)
|
|
194
|
+
@abstractmethod
|
|
195
|
+
async def download_media(
|
|
196
|
+
self,
|
|
197
|
+
media_id: str,
|
|
198
|
+
destination_path: str | Path | None = None,
|
|
199
|
+
sender_id: str | None = None,
|
|
200
|
+
) -> MediaDownloadResult:
|
|
201
|
+
"""
|
|
202
|
+
Download media by ID.
|
|
203
|
+
|
|
204
|
+
Based on existing WhatsAppServiceMedia.download_media() method.
|
|
205
|
+
Implements workflow: GET /MEDIA_ID -> GET /MEDIA_URL
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
media_id: Platform-specific media identifier
|
|
209
|
+
destination_path: Optional path to save file
|
|
210
|
+
sender_id: Optional sender ID for filename generation
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
MediaDownloadResult with file data and metadata
|
|
214
|
+
|
|
215
|
+
Note:
|
|
216
|
+
If destination_path provided, saves file to disk.
|
|
217
|
+
If not provided, returns file data in memory.
|
|
218
|
+
Handles URL expiration by re-fetching URL if needed.
|
|
219
|
+
"""
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
@abstractmethod
|
|
223
|
+
async def stream_media(
|
|
224
|
+
self, media_id: str, chunk_size: int = 8192
|
|
225
|
+
) -> AsyncIterator[bytes]:
|
|
226
|
+
"""
|
|
227
|
+
Stream media by ID for large files.
|
|
228
|
+
|
|
229
|
+
Extension of download functionality for memory-efficient streaming.
|
|
230
|
+
Implements workflow: GET /MEDIA_ID -> GET /MEDIA_URL with streaming.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
media_id: Platform-specific media identifier
|
|
234
|
+
chunk_size: Size of chunks to yield
|
|
235
|
+
|
|
236
|
+
Yields:
|
|
237
|
+
Bytes chunks of the media file
|
|
238
|
+
|
|
239
|
+
Raises:
|
|
240
|
+
Platform-specific exceptions for API failures or URL expiration
|
|
241
|
+
"""
|
|
242
|
+
pass
|
|
243
|
+
|
|
244
|
+
# Delete Operations (DELETE /MEDIA_ID)
|
|
245
|
+
@abstractmethod
|
|
246
|
+
async def delete_media(self, media_id: str) -> MediaDeleteResult:
|
|
247
|
+
"""
|
|
248
|
+
Delete media by ID.
|
|
249
|
+
|
|
250
|
+
Based on existing WhatsAppServiceMedia.delete_media() method.
|
|
251
|
+
Implements DELETE /MEDIA_ID endpoint.
|
|
252
|
+
|
|
253
|
+
WhatsApp API Response:
|
|
254
|
+
{
|
|
255
|
+
"success": true
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
media_id: Platform-specific media identifier to delete
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
MediaDeleteResult with deletion status
|
|
263
|
+
|
|
264
|
+
Note:
|
|
265
|
+
Media files persist for 30 days unless deleted earlier.
|
|
266
|
+
Deletion is permanent and cannot be undone.
|
|
267
|
+
"""
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
# Validation Operations
|
|
271
|
+
@abstractmethod
|
|
272
|
+
def validate_media_type(self, mime_type: str) -> bool:
|
|
273
|
+
"""
|
|
274
|
+
Validate if MIME type is supported by platform.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
mime_type: MIME type to validate
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
True if supported, False otherwise
|
|
281
|
+
"""
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
@abstractmethod
|
|
285
|
+
def validate_file_size(self, file_size: int, mime_type: str) -> bool:
|
|
286
|
+
"""
|
|
287
|
+
Validate if file size is within platform limits.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
file_size: File size in bytes
|
|
291
|
+
mime_type: MIME type of the file
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
True if within limits, False otherwise
|
|
295
|
+
"""
|
|
296
|
+
pass
|
|
297
|
+
|
|
298
|
+
@abstractmethod
|
|
299
|
+
def get_media_limits(self) -> dict[str, any]:
|
|
300
|
+
"""
|
|
301
|
+
Get platform-specific media limits and constraints.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Dictionary containing platform-specific limits
|
|
305
|
+
Example: {
|
|
306
|
+
"max_sizes": {"image": 5242880, "video": 16777216},
|
|
307
|
+
"supported_types": ["image/jpeg", "video/mp4"],
|
|
308
|
+
"url_expiry_minutes": 5
|
|
309
|
+
}
|
|
310
|
+
"""
|
|
311
|
+
pass
|