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.

Files changed (211) hide show
  1. wappa/__init__.py +85 -0
  2. wappa/api/__init__.py +1 -0
  3. wappa/api/controllers/__init__.py +10 -0
  4. wappa/api/controllers/webhook_controller.py +441 -0
  5. wappa/api/dependencies/__init__.py +15 -0
  6. wappa/api/dependencies/whatsapp_dependencies.py +220 -0
  7. wappa/api/dependencies/whatsapp_media_dependencies.py +26 -0
  8. wappa/api/middleware/__init__.py +7 -0
  9. wappa/api/middleware/error_handler.py +158 -0
  10. wappa/api/middleware/owner.py +99 -0
  11. wappa/api/middleware/request_logging.py +184 -0
  12. wappa/api/routes/__init__.py +6 -0
  13. wappa/api/routes/health.py +102 -0
  14. wappa/api/routes/webhooks.py +211 -0
  15. wappa/api/routes/whatsapp/__init__.py +15 -0
  16. wappa/api/routes/whatsapp/whatsapp_interactive.py +429 -0
  17. wappa/api/routes/whatsapp/whatsapp_media.py +440 -0
  18. wappa/api/routes/whatsapp/whatsapp_messages.py +195 -0
  19. wappa/api/routes/whatsapp/whatsapp_specialized.py +516 -0
  20. wappa/api/routes/whatsapp/whatsapp_templates.py +431 -0
  21. wappa/api/routes/whatsapp_combined.py +35 -0
  22. wappa/cli/__init__.py +9 -0
  23. wappa/cli/main.py +199 -0
  24. wappa/core/__init__.py +6 -0
  25. wappa/core/config/__init__.py +5 -0
  26. wappa/core/config/settings.py +161 -0
  27. wappa/core/events/__init__.py +41 -0
  28. wappa/core/events/default_handlers.py +642 -0
  29. wappa/core/events/event_dispatcher.py +244 -0
  30. wappa/core/events/event_handler.py +247 -0
  31. wappa/core/events/webhook_factory.py +219 -0
  32. wappa/core/factory/__init__.py +15 -0
  33. wappa/core/factory/plugin.py +68 -0
  34. wappa/core/factory/wappa_builder.py +326 -0
  35. wappa/core/logging/__init__.py +5 -0
  36. wappa/core/logging/context.py +100 -0
  37. wappa/core/logging/logger.py +343 -0
  38. wappa/core/plugins/__init__.py +34 -0
  39. wappa/core/plugins/auth_plugin.py +169 -0
  40. wappa/core/plugins/cors_plugin.py +128 -0
  41. wappa/core/plugins/custom_middleware_plugin.py +182 -0
  42. wappa/core/plugins/database_plugin.py +235 -0
  43. wappa/core/plugins/rate_limit_plugin.py +183 -0
  44. wappa/core/plugins/redis_plugin.py +224 -0
  45. wappa/core/plugins/wappa_core_plugin.py +261 -0
  46. wappa/core/plugins/webhook_plugin.py +253 -0
  47. wappa/core/types.py +108 -0
  48. wappa/core/wappa_app.py +546 -0
  49. wappa/database/__init__.py +18 -0
  50. wappa/database/adapter.py +107 -0
  51. wappa/database/adapters/__init__.py +17 -0
  52. wappa/database/adapters/mysql_adapter.py +187 -0
  53. wappa/database/adapters/postgresql_adapter.py +169 -0
  54. wappa/database/adapters/sqlite_adapter.py +174 -0
  55. wappa/domain/__init__.py +28 -0
  56. wappa/domain/builders/__init__.py +5 -0
  57. wappa/domain/builders/message_builder.py +189 -0
  58. wappa/domain/entities/__init__.py +5 -0
  59. wappa/domain/enums/messenger_platform.py +123 -0
  60. wappa/domain/factories/__init__.py +6 -0
  61. wappa/domain/factories/media_factory.py +450 -0
  62. wappa/domain/factories/message_factory.py +497 -0
  63. wappa/domain/factories/messenger_factory.py +244 -0
  64. wappa/domain/interfaces/__init__.py +32 -0
  65. wappa/domain/interfaces/base_repository.py +94 -0
  66. wappa/domain/interfaces/cache_factory.py +85 -0
  67. wappa/domain/interfaces/cache_interface.py +199 -0
  68. wappa/domain/interfaces/expiry_repository.py +68 -0
  69. wappa/domain/interfaces/media_interface.py +311 -0
  70. wappa/domain/interfaces/messaging_interface.py +523 -0
  71. wappa/domain/interfaces/pubsub_repository.py +151 -0
  72. wappa/domain/interfaces/repository_factory.py +108 -0
  73. wappa/domain/interfaces/shared_state_repository.py +122 -0
  74. wappa/domain/interfaces/state_repository.py +123 -0
  75. wappa/domain/interfaces/tables_repository.py +215 -0
  76. wappa/domain/interfaces/user_repository.py +114 -0
  77. wappa/domain/interfaces/webhooks/__init__.py +1 -0
  78. wappa/domain/models/media_result.py +110 -0
  79. wappa/domain/models/platforms/__init__.py +15 -0
  80. wappa/domain/models/platforms/platform_config.py +104 -0
  81. wappa/domain/services/__init__.py +11 -0
  82. wappa/domain/services/tenant_credentials_service.py +56 -0
  83. wappa/messaging/__init__.py +7 -0
  84. wappa/messaging/whatsapp/__init__.py +1 -0
  85. wappa/messaging/whatsapp/client/__init__.py +5 -0
  86. wappa/messaging/whatsapp/client/whatsapp_client.py +417 -0
  87. wappa/messaging/whatsapp/handlers/__init__.py +13 -0
  88. wappa/messaging/whatsapp/handlers/whatsapp_interactive_handler.py +653 -0
  89. wappa/messaging/whatsapp/handlers/whatsapp_media_handler.py +579 -0
  90. wappa/messaging/whatsapp/handlers/whatsapp_specialized_handler.py +434 -0
  91. wappa/messaging/whatsapp/handlers/whatsapp_template_handler.py +416 -0
  92. wappa/messaging/whatsapp/messenger/__init__.py +5 -0
  93. wappa/messaging/whatsapp/messenger/whatsapp_messenger.py +904 -0
  94. wappa/messaging/whatsapp/models/__init__.py +61 -0
  95. wappa/messaging/whatsapp/models/basic_models.py +65 -0
  96. wappa/messaging/whatsapp/models/interactive_models.py +287 -0
  97. wappa/messaging/whatsapp/models/media_models.py +215 -0
  98. wappa/messaging/whatsapp/models/specialized_models.py +304 -0
  99. wappa/messaging/whatsapp/models/template_models.py +261 -0
  100. wappa/persistence/cache_factory.py +93 -0
  101. wappa/persistence/json/__init__.py +14 -0
  102. wappa/persistence/json/cache_adapters.py +271 -0
  103. wappa/persistence/json/handlers/__init__.py +1 -0
  104. wappa/persistence/json/handlers/state_handler.py +250 -0
  105. wappa/persistence/json/handlers/table_handler.py +263 -0
  106. wappa/persistence/json/handlers/user_handler.py +213 -0
  107. wappa/persistence/json/handlers/utils/__init__.py +1 -0
  108. wappa/persistence/json/handlers/utils/file_manager.py +153 -0
  109. wappa/persistence/json/handlers/utils/key_factory.py +11 -0
  110. wappa/persistence/json/handlers/utils/serialization.py +121 -0
  111. wappa/persistence/json/json_cache_factory.py +76 -0
  112. wappa/persistence/json/storage_manager.py +285 -0
  113. wappa/persistence/memory/__init__.py +14 -0
  114. wappa/persistence/memory/cache_adapters.py +271 -0
  115. wappa/persistence/memory/handlers/__init__.py +1 -0
  116. wappa/persistence/memory/handlers/state_handler.py +250 -0
  117. wappa/persistence/memory/handlers/table_handler.py +280 -0
  118. wappa/persistence/memory/handlers/user_handler.py +213 -0
  119. wappa/persistence/memory/handlers/utils/__init__.py +1 -0
  120. wappa/persistence/memory/handlers/utils/key_factory.py +11 -0
  121. wappa/persistence/memory/handlers/utils/memory_store.py +317 -0
  122. wappa/persistence/memory/handlers/utils/ttl_manager.py +235 -0
  123. wappa/persistence/memory/memory_cache_factory.py +76 -0
  124. wappa/persistence/memory/storage_manager.py +235 -0
  125. wappa/persistence/redis/README.md +699 -0
  126. wappa/persistence/redis/__init__.py +11 -0
  127. wappa/persistence/redis/cache_adapters.py +285 -0
  128. wappa/persistence/redis/ops.py +880 -0
  129. wappa/persistence/redis/redis_cache_factory.py +71 -0
  130. wappa/persistence/redis/redis_client.py +231 -0
  131. wappa/persistence/redis/redis_handler/__init__.py +26 -0
  132. wappa/persistence/redis/redis_handler/state_handler.py +176 -0
  133. wappa/persistence/redis/redis_handler/table.py +158 -0
  134. wappa/persistence/redis/redis_handler/user.py +138 -0
  135. wappa/persistence/redis/redis_handler/utils/__init__.py +12 -0
  136. wappa/persistence/redis/redis_handler/utils/key_factory.py +32 -0
  137. wappa/persistence/redis/redis_handler/utils/serde.py +146 -0
  138. wappa/persistence/redis/redis_handler/utils/tenant_cache.py +268 -0
  139. wappa/persistence/redis/redis_manager.py +189 -0
  140. wappa/processors/__init__.py +6 -0
  141. wappa/processors/base_processor.py +262 -0
  142. wappa/processors/factory.py +550 -0
  143. wappa/processors/whatsapp_processor.py +810 -0
  144. wappa/schemas/__init__.py +6 -0
  145. wappa/schemas/core/__init__.py +71 -0
  146. wappa/schemas/core/base_message.py +499 -0
  147. wappa/schemas/core/base_status.py +322 -0
  148. wappa/schemas/core/base_webhook.py +312 -0
  149. wappa/schemas/core/types.py +253 -0
  150. wappa/schemas/core/webhook_interfaces/__init__.py +48 -0
  151. wappa/schemas/core/webhook_interfaces/base_components.py +293 -0
  152. wappa/schemas/core/webhook_interfaces/universal_webhooks.py +348 -0
  153. wappa/schemas/factory.py +754 -0
  154. wappa/schemas/webhooks/__init__.py +3 -0
  155. wappa/schemas/whatsapp/__init__.py +6 -0
  156. wappa/schemas/whatsapp/base_models.py +285 -0
  157. wappa/schemas/whatsapp/message_types/__init__.py +93 -0
  158. wappa/schemas/whatsapp/message_types/audio.py +350 -0
  159. wappa/schemas/whatsapp/message_types/button.py +267 -0
  160. wappa/schemas/whatsapp/message_types/contact.py +464 -0
  161. wappa/schemas/whatsapp/message_types/document.py +421 -0
  162. wappa/schemas/whatsapp/message_types/errors.py +195 -0
  163. wappa/schemas/whatsapp/message_types/image.py +424 -0
  164. wappa/schemas/whatsapp/message_types/interactive.py +430 -0
  165. wappa/schemas/whatsapp/message_types/location.py +416 -0
  166. wappa/schemas/whatsapp/message_types/order.py +372 -0
  167. wappa/schemas/whatsapp/message_types/reaction.py +271 -0
  168. wappa/schemas/whatsapp/message_types/sticker.py +328 -0
  169. wappa/schemas/whatsapp/message_types/system.py +317 -0
  170. wappa/schemas/whatsapp/message_types/text.py +411 -0
  171. wappa/schemas/whatsapp/message_types/unsupported.py +273 -0
  172. wappa/schemas/whatsapp/message_types/video.py +344 -0
  173. wappa/schemas/whatsapp/status_models.py +479 -0
  174. wappa/schemas/whatsapp/validators.py +454 -0
  175. wappa/schemas/whatsapp/webhook_container.py +438 -0
  176. wappa/webhooks/__init__.py +17 -0
  177. wappa/webhooks/core/__init__.py +71 -0
  178. wappa/webhooks/core/base_message.py +499 -0
  179. wappa/webhooks/core/base_status.py +322 -0
  180. wappa/webhooks/core/base_webhook.py +312 -0
  181. wappa/webhooks/core/types.py +253 -0
  182. wappa/webhooks/core/webhook_interfaces/__init__.py +48 -0
  183. wappa/webhooks/core/webhook_interfaces/base_components.py +293 -0
  184. wappa/webhooks/core/webhook_interfaces/universal_webhooks.py +441 -0
  185. wappa/webhooks/factory.py +754 -0
  186. wappa/webhooks/whatsapp/__init__.py +6 -0
  187. wappa/webhooks/whatsapp/base_models.py +285 -0
  188. wappa/webhooks/whatsapp/message_types/__init__.py +93 -0
  189. wappa/webhooks/whatsapp/message_types/audio.py +350 -0
  190. wappa/webhooks/whatsapp/message_types/button.py +267 -0
  191. wappa/webhooks/whatsapp/message_types/contact.py +464 -0
  192. wappa/webhooks/whatsapp/message_types/document.py +421 -0
  193. wappa/webhooks/whatsapp/message_types/errors.py +195 -0
  194. wappa/webhooks/whatsapp/message_types/image.py +424 -0
  195. wappa/webhooks/whatsapp/message_types/interactive.py +430 -0
  196. wappa/webhooks/whatsapp/message_types/location.py +416 -0
  197. wappa/webhooks/whatsapp/message_types/order.py +372 -0
  198. wappa/webhooks/whatsapp/message_types/reaction.py +271 -0
  199. wappa/webhooks/whatsapp/message_types/sticker.py +328 -0
  200. wappa/webhooks/whatsapp/message_types/system.py +317 -0
  201. wappa/webhooks/whatsapp/message_types/text.py +411 -0
  202. wappa/webhooks/whatsapp/message_types/unsupported.py +273 -0
  203. wappa/webhooks/whatsapp/message_types/video.py +344 -0
  204. wappa/webhooks/whatsapp/status_models.py +479 -0
  205. wappa/webhooks/whatsapp/validators.py +454 -0
  206. wappa/webhooks/whatsapp/webhook_container.py +438 -0
  207. wappa-0.1.0.dist-info/METADATA +269 -0
  208. wappa-0.1.0.dist-info/RECORD +211 -0
  209. wappa-0.1.0.dist-info/WHEEL +4 -0
  210. wappa-0.1.0.dist-info/entry_points.txt +2 -0
  211. 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,11 @@
1
+ """
2
+ Domain services.
3
+
4
+ Contains business logic that doesn't belong to a specific entity.
5
+ """
6
+
7
+ from .tenant_credentials_service import TenantCredentialsService
8
+
9
+ __all__ = [
10
+ "TenantCredentialsService",
11
+ ]
@@ -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,7 @@
1
+ """Messaging interfaces and implementations for Wappa framework."""
2
+
3
+ from wappa.domain.interfaces.messaging_interface import IMessenger
4
+
5
+ from .whatsapp.messenger.whatsapp_messenger import WhatsAppMessenger
6
+
7
+ __all__ = ["IMessenger", "WhatsAppMessenger"]
@@ -0,0 +1 @@
1
+ """WhatsApp services package."""
@@ -0,0 +1,5 @@
1
+ """WhatsApp client package."""
2
+
3
+ from .whatsapp_client import WhatsAppClient, WhatsAppFormDataBuilder, WhatsAppUrlBuilder
4
+
5
+ __all__ = ["WhatsAppClient", "WhatsAppUrlBuilder", "WhatsAppFormDataBuilder"]