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,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Media result models for platform-agnostic media operations.
|
|
3
|
+
|
|
4
|
+
These models represent the results of media operations across different
|
|
5
|
+
messaging platforms, providing consistent response structures while
|
|
6
|
+
maintaining compatibility with platform-specific response formats.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
from wappa.schemas.core.types import PlatformType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MediaUploadResult(BaseModel):
|
|
17
|
+
"""Result of a media upload operation.
|
|
18
|
+
|
|
19
|
+
Standard response model for media upload operations across platforms.
|
|
20
|
+
Based on WhatsApp Cloud API response: {"id": "<MEDIA_ID>"}
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
success: bool
|
|
24
|
+
platform: PlatformType = PlatformType.WHATSAPP
|
|
25
|
+
media_id: str | None = None
|
|
26
|
+
media_url: str | None = None
|
|
27
|
+
file_size: int | None = None
|
|
28
|
+
mime_type: str | None = None
|
|
29
|
+
error: str | None = None
|
|
30
|
+
error_code: str | None = None
|
|
31
|
+
uploaded_at: datetime = Field(default_factory=datetime.utcnow)
|
|
32
|
+
tenant_id: str | None = None # phone_number_id in WhatsApp context
|
|
33
|
+
|
|
34
|
+
class Config:
|
|
35
|
+
use_enum_values = True
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MediaInfoResult(BaseModel):
|
|
39
|
+
"""Result of a media info retrieval operation.
|
|
40
|
+
|
|
41
|
+
Standard response model for media info operations.
|
|
42
|
+
Based on WhatsApp Cloud API response:
|
|
43
|
+
{
|
|
44
|
+
"messaging_product": "whatsapp",
|
|
45
|
+
"url": "<URL>",
|
|
46
|
+
"mime_type": "<MIME_TYPE>",
|
|
47
|
+
"sha256": "<HASH>",
|
|
48
|
+
"file_size": "<FILE_SIZE>",
|
|
49
|
+
"id": "<MEDIA_ID>"
|
|
50
|
+
}
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
success: bool
|
|
54
|
+
platform: PlatformType = PlatformType.WHATSAPP
|
|
55
|
+
media_id: str | None = None
|
|
56
|
+
url: str | None = None
|
|
57
|
+
mime_type: str | None = None
|
|
58
|
+
file_size: int | None = None
|
|
59
|
+
sha256: str | None = None
|
|
60
|
+
error: str | None = None
|
|
61
|
+
error_code: str | None = None
|
|
62
|
+
retrieved_at: datetime = Field(default_factory=datetime.utcnow)
|
|
63
|
+
tenant_id: str | None = None
|
|
64
|
+
|
|
65
|
+
class Config:
|
|
66
|
+
use_enum_values = True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class MediaDownloadResult(BaseModel):
|
|
70
|
+
"""Result of a media download operation.
|
|
71
|
+
|
|
72
|
+
Standard response model for media download operations.
|
|
73
|
+
Compatible with existing handle_media.py download patterns.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
success: bool
|
|
77
|
+
platform: PlatformType = PlatformType.WHATSAPP
|
|
78
|
+
file_data: bytes | None = None
|
|
79
|
+
file_path: str | None = None
|
|
80
|
+
mime_type: str | None = None
|
|
81
|
+
file_size: int | None = None
|
|
82
|
+
sha256: str | None = None
|
|
83
|
+
error: str | None = None
|
|
84
|
+
error_code: str | None = None
|
|
85
|
+
downloaded_at: datetime = Field(default_factory=datetime.utcnow)
|
|
86
|
+
tenant_id: str | None = None
|
|
87
|
+
|
|
88
|
+
class Config:
|
|
89
|
+
use_enum_values = True
|
|
90
|
+
# Allow bytes in file_data field
|
|
91
|
+
arbitrary_types_allowed = True
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class MediaDeleteResult(BaseModel):
|
|
95
|
+
"""Result of a media delete operation.
|
|
96
|
+
|
|
97
|
+
Standard response model for media delete operations.
|
|
98
|
+
Based on WhatsApp Cloud API response: {"success": true}
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
success: bool
|
|
102
|
+
platform: PlatformType = PlatformType.WHATSAPP
|
|
103
|
+
media_id: str | None = None
|
|
104
|
+
error: str | None = None
|
|
105
|
+
error_code: str | None = None
|
|
106
|
+
deleted_at: datetime = Field(default_factory=datetime.utcnow)
|
|
107
|
+
tenant_id: str | None = None
|
|
108
|
+
|
|
109
|
+
class Config:
|
|
110
|
+
use_enum_values = True
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Platform configuration models."""
|
|
2
|
+
|
|
3
|
+
from .platform_config import (
|
|
4
|
+
PlatformCapabilities,
|
|
5
|
+
PlatformConfig,
|
|
6
|
+
PlatformCredentials,
|
|
7
|
+
PlatformLimits,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"PlatformConfig",
|
|
12
|
+
"PlatformCredentials",
|
|
13
|
+
"PlatformCapabilities",
|
|
14
|
+
"PlatformLimits",
|
|
15
|
+
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Platform configuration models for messenger platforms.
|
|
3
|
+
|
|
4
|
+
Defines configuration structure for messenger platforms similar to
|
|
5
|
+
payment provider configuration but adapted for messaging platforms.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PlatformCapabilities(BaseModel):
|
|
14
|
+
"""Platform-specific capabilities and limits."""
|
|
15
|
+
|
|
16
|
+
max_text_length: int = Field(
|
|
17
|
+
default=4096, description="Maximum text message length"
|
|
18
|
+
)
|
|
19
|
+
max_media_size: int = Field(
|
|
20
|
+
default=16 * 1024 * 1024, description="Maximum media file size in bytes"
|
|
21
|
+
)
|
|
22
|
+
supports_threads: bool = Field(
|
|
23
|
+
default=False, description="Whether platform supports message threads"
|
|
24
|
+
)
|
|
25
|
+
supports_reactions: bool = Field(
|
|
26
|
+
default=True, description="Whether platform supports message reactions"
|
|
27
|
+
)
|
|
28
|
+
supports_editing: bool = Field(
|
|
29
|
+
default=False, description="Whether platform supports message editing"
|
|
30
|
+
)
|
|
31
|
+
supported_message_types: list[str] = Field(
|
|
32
|
+
default_factory=list, description="Supported message types"
|
|
33
|
+
)
|
|
34
|
+
supported_interactive_types: list[str] = Field(
|
|
35
|
+
default_factory=list, description="Supported interactive message types"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class PlatformCredentials(BaseModel):
|
|
40
|
+
"""Platform-specific credentials and API keys."""
|
|
41
|
+
|
|
42
|
+
access_token: str | None = Field(default=None, description="Platform access token")
|
|
43
|
+
app_id: str | None = Field(default=None, description="Application ID")
|
|
44
|
+
app_secret: str | None = Field(default=None, description="Application secret")
|
|
45
|
+
phone_id: str | None = Field(default=None, description="Phone number ID (WhatsApp)")
|
|
46
|
+
business_id: str | None = Field(default=None, description="Business account ID")
|
|
47
|
+
webhook_verify_token: str | None = Field(
|
|
48
|
+
default=None, description="Webhook verification token"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def is_configured(self) -> bool:
|
|
52
|
+
"""Check if minimum required credentials are present."""
|
|
53
|
+
# For WhatsApp, we need access_token and phone_id
|
|
54
|
+
if self.access_token and self.phone_id:
|
|
55
|
+
return True
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PlatformLimits(BaseModel):
|
|
60
|
+
"""Platform-specific rate limits and constraints."""
|
|
61
|
+
|
|
62
|
+
max_requests_per_minute: int = Field(
|
|
63
|
+
default=1000, description="Maximum API requests per minute"
|
|
64
|
+
)
|
|
65
|
+
max_recipients_per_message: int = Field(
|
|
66
|
+
default=1, description="Maximum recipients per message"
|
|
67
|
+
)
|
|
68
|
+
max_buttons_per_message: int = Field(
|
|
69
|
+
default=3, description="Maximum buttons per interactive message"
|
|
70
|
+
)
|
|
71
|
+
max_list_sections: int = Field(
|
|
72
|
+
default=10, description="Maximum sections in list messages"
|
|
73
|
+
)
|
|
74
|
+
max_list_rows_per_section: int = Field(
|
|
75
|
+
default=10, description="Maximum rows per list section"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class PlatformConfig(BaseModel):
|
|
80
|
+
"""Complete platform configuration."""
|
|
81
|
+
|
|
82
|
+
platform_name: str = Field(description="Internal platform name (lowercase)")
|
|
83
|
+
display_name: str = Field(description="Human-readable platform name")
|
|
84
|
+
is_enabled: bool = Field(default=True, description="Whether platform is enabled")
|
|
85
|
+
is_test_mode: bool = Field(
|
|
86
|
+
default=False, description="Whether platform is in test mode"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
credentials: PlatformCredentials = Field(description="Platform credentials")
|
|
90
|
+
capabilities: PlatformCapabilities = Field(description="Platform capabilities")
|
|
91
|
+
limits: PlatformLimits = Field(description="Platform limits")
|
|
92
|
+
|
|
93
|
+
webhook_events: list[str] = Field(
|
|
94
|
+
default_factory=list, description="Supported webhook events"
|
|
95
|
+
)
|
|
96
|
+
webhook_url_template: str = Field(description="Webhook URL template")
|
|
97
|
+
|
|
98
|
+
platform_settings: dict[str, Any] = Field(
|
|
99
|
+
default_factory=dict, description="Platform-specific settings"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def is_configured(self) -> bool:
|
|
103
|
+
"""Check if platform is properly configured."""
|
|
104
|
+
return self.credentials.is_configured()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tenant credentials service for managing tenant-specific WhatsApp credentials.
|
|
3
|
+
|
|
4
|
+
Currently uses settings for single tenant, but will be migrated to database
|
|
5
|
+
for multi-tenant support in the future.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from wappa.core.config.settings import settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TenantCredentialsService:
|
|
12
|
+
"""Service to get tenant-specific WhatsApp credentials.
|
|
13
|
+
|
|
14
|
+
Currently uses settings for single tenant, but will be migrated to database
|
|
15
|
+
for multi-tenant support in the future.
|
|
16
|
+
|
|
17
|
+
Note: In WhatsApp Business API, the phone_number_id IS the tenant identifier.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def get_whatsapp_access_token(phone_number_id: str) -> str:
|
|
22
|
+
"""Get WhatsApp access token for tenant.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
phone_number_id: WhatsApp Business phone number ID (this IS the tenant_id)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
WhatsApp access token for this tenant
|
|
29
|
+
|
|
30
|
+
Future: This will query the database using phone_number_id as the key:
|
|
31
|
+
SELECT access_token FROM tenants WHERE phone_number_id = ?
|
|
32
|
+
"""
|
|
33
|
+
# TODO: Replace with database query when migrating to multi-tenant
|
|
34
|
+
# For now, use settings computed properties (DEV/PROD switching)
|
|
35
|
+
return settings.wp_access_token
|
|
36
|
+
|
|
37
|
+
@staticmethod
|
|
38
|
+
def validate_tenant(phone_number_id: str) -> bool:
|
|
39
|
+
"""Validate that the tenant exists and is active.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
phone_number_id: WhatsApp Business phone number ID
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
True if tenant is valid and active, False otherwise
|
|
46
|
+
|
|
47
|
+
Future: This will validate against the database
|
|
48
|
+
"""
|
|
49
|
+
# TODO: Replace with database validation when migrating to multi-tenant
|
|
50
|
+
# For now, check if we have valid credentials in settings
|
|
51
|
+
try:
|
|
52
|
+
token = settings.wp_access_token
|
|
53
|
+
configured_phone_id = settings.wp_phone_id
|
|
54
|
+
return bool(token and configured_phone_id == phone_number_id)
|
|
55
|
+
except Exception:
|
|
56
|
+
return False
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""WhatsApp services package."""
|