wappa 0.1.7__py3-none-any.whl → 0.1.9__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/cli/examples/init/.env.example +33 -0
- wappa/cli/examples/init/app/__init__.py +0 -0
- wappa/cli/examples/init/app/main.py +8 -0
- wappa/cli/examples/init/app/master_event.py +8 -0
- wappa/cli/examples/json_cache_example/.env.example +33 -0
- wappa/cli/examples/json_cache_example/app/__init__.py +1 -0
- wappa/cli/examples/json_cache_example/app/main.py +235 -0
- wappa/cli/examples/json_cache_example/app/master_event.py +419 -0
- wappa/cli/examples/json_cache_example/app/models/__init__.py +1 -0
- wappa/cli/examples/json_cache_example/app/models/json_demo_models.py +275 -0
- wappa/cli/examples/json_cache_example/app/scores/__init__.py +35 -0
- wappa/cli/examples/json_cache_example/app/scores/score_base.py +186 -0
- wappa/cli/examples/json_cache_example/app/scores/score_cache_statistics.py +248 -0
- wappa/cli/examples/json_cache_example/app/scores/score_message_history.py +190 -0
- wappa/cli/examples/json_cache_example/app/scores/score_state_commands.py +260 -0
- wappa/cli/examples/json_cache_example/app/scores/score_user_management.py +223 -0
- wappa/cli/examples/json_cache_example/app/utils/__init__.py +26 -0
- wappa/cli/examples/json_cache_example/app/utils/cache_utils.py +176 -0
- wappa/cli/examples/json_cache_example/app/utils/message_utils.py +246 -0
- wappa/cli/examples/openai_transcript/.gitignore +63 -4
- wappa/cli/examples/openai_transcript/app/__init__.py +0 -0
- wappa/cli/examples/openai_transcript/app/main.py +8 -0
- wappa/cli/examples/openai_transcript/app/master_event.py +53 -0
- wappa/cli/examples/openai_transcript/app/openai_utils/__init__.py +3 -0
- wappa/cli/examples/openai_transcript/app/openai_utils/audio_processing.py +76 -0
- wappa/cli/examples/redis_cache_example/.env.example +33 -0
- wappa/cli/examples/redis_cache_example/app/__init__.py +6 -0
- wappa/cli/examples/redis_cache_example/app/main.py +234 -0
- wappa/cli/examples/redis_cache_example/app/master_event.py +419 -0
- wappa/cli/examples/redis_cache_example/app/models/redis_demo_models.py +275 -0
- wappa/cli/examples/redis_cache_example/app/scores/__init__.py +35 -0
- wappa/cli/examples/redis_cache_example/app/scores/score_base.py +186 -0
- wappa/cli/examples/redis_cache_example/app/scores/score_cache_statistics.py +248 -0
- wappa/cli/examples/redis_cache_example/app/scores/score_message_history.py +190 -0
- wappa/cli/examples/redis_cache_example/app/scores/score_state_commands.py +260 -0
- wappa/cli/examples/redis_cache_example/app/scores/score_user_management.py +223 -0
- wappa/cli/examples/redis_cache_example/app/utils/__init__.py +26 -0
- wappa/cli/examples/redis_cache_example/app/utils/cache_utils.py +176 -0
- wappa/cli/examples/redis_cache_example/app/utils/message_utils.py +246 -0
- wappa/cli/examples/simple_echo_example/.env.example +33 -0
- wappa/cli/examples/simple_echo_example/app/__init__.py +7 -0
- wappa/cli/examples/simple_echo_example/app/main.py +183 -0
- wappa/cli/examples/simple_echo_example/app/master_event.py +209 -0
- wappa/cli/examples/wappa_full_example/.env.example +33 -0
- wappa/cli/examples/wappa_full_example/.gitignore +63 -4
- wappa/cli/examples/wappa_full_example/app/__init__.py +6 -0
- wappa/cli/examples/wappa_full_example/app/handlers/__init__.py +5 -0
- wappa/cli/examples/wappa_full_example/app/handlers/command_handlers.py +484 -0
- wappa/cli/examples/wappa_full_example/app/handlers/message_handlers.py +551 -0
- wappa/cli/examples/wappa_full_example/app/handlers/state_handlers.py +492 -0
- wappa/cli/examples/wappa_full_example/app/main.py +257 -0
- wappa/cli/examples/wappa_full_example/app/master_event.py +445 -0
- wappa/cli/examples/wappa_full_example/app/media/README.md +54 -0
- wappa/cli/examples/wappa_full_example/app/media/buttons/README.md +62 -0
- wappa/cli/examples/wappa_full_example/app/media/buttons/kitty.png +0 -0
- wappa/cli/examples/wappa_full_example/app/media/buttons/puppy.png +0 -0
- wappa/cli/examples/wappa_full_example/app/media/list/README.md +110 -0
- wappa/cli/examples/wappa_full_example/app/media/list/audio.mp3 +0 -0
- wappa/cli/examples/wappa_full_example/app/media/list/document.pdf +0 -0
- wappa/cli/examples/wappa_full_example/app/media/list/image.png +0 -0
- wappa/cli/examples/wappa_full_example/app/media/list/video.mp4 +0 -0
- wappa/cli/examples/wappa_full_example/app/models/__init__.py +5 -0
- wappa/cli/examples/wappa_full_example/app/models/state_models.py +425 -0
- wappa/cli/examples/wappa_full_example/app/models/user_models.py +287 -0
- wappa/cli/examples/wappa_full_example/app/models/webhook_metadata.py +301 -0
- wappa/cli/examples/wappa_full_example/app/utils/__init__.py +5 -0
- wappa/cli/examples/wappa_full_example/app/utils/cache_utils.py +483 -0
- wappa/cli/examples/wappa_full_example/app/utils/media_handler.py +473 -0
- wappa/cli/examples/wappa_full_example/app/utils/metadata_extractor.py +298 -0
- wappa/cli/main.py +8 -4
- wappa/core/config/settings.py +34 -2
- wappa/persistence/__init__.py +2 -2
- {wappa-0.1.7.dist-info → wappa-0.1.9.dist-info}/METADATA +1 -1
- {wappa-0.1.7.dist-info → wappa-0.1.9.dist-info}/RECORD +77 -13
- wappa/cli/examples/init/pyproject.toml +0 -7
- wappa/cli/examples/simple_echo_example/.python-version +0 -1
- wappa/cli/examples/simple_echo_example/pyproject.toml +0 -9
- {wappa-0.1.7.dist-info → wappa-0.1.9.dist-info}/WHEEL +0 -0
- {wappa-0.1.7.dist-info → wappa-0.1.9.dist-info}/entry_points.txt +0 -0
- {wappa-0.1.7.dist-info → wappa-0.1.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple Echo Example - Clean Architecture Implementation
|
|
3
|
+
|
|
4
|
+
This is a simplified version of the Redis cache example that demonstrates
|
|
5
|
+
basic Wappa functionality without complex dependencies.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Clean WappaEventHandler implementation
|
|
9
|
+
- Simple message echoing for all message types
|
|
10
|
+
- Proper dependency injection
|
|
11
|
+
- Professional logging and error handling
|
|
12
|
+
|
|
13
|
+
SETUP REQUIRED:
|
|
14
|
+
1. Create a .env file with your WhatsApp Business API credentials:
|
|
15
|
+
WP_ACCESS_TOKEN=your_access_token_here
|
|
16
|
+
WP_PHONE_ID=your_phone_number_id_here
|
|
17
|
+
WP_BID=your_business_id_here
|
|
18
|
+
|
|
19
|
+
USAGE:
|
|
20
|
+
- Direct Python: python -m app.main (from project root)
|
|
21
|
+
- FastAPI-style: uvicorn app.main:app --reload (from project root)
|
|
22
|
+
- Wappa CLI: wappa run app/main.py (from project root)
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Import core Wappa components
|
|
26
|
+
from wappa import Wappa, __version__
|
|
27
|
+
from wappa.core.config.settings import settings
|
|
28
|
+
from wappa.core.logging import get_logger
|
|
29
|
+
|
|
30
|
+
logger = get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
# Import our simple echo handler
|
|
33
|
+
from .master_event import SimpleEchoHandler
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def validate_configuration() -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Validate required configuration settings.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
True if configuration is valid, False otherwise
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# Check required WhatsApp credentials
|
|
45
|
+
missing_configs = []
|
|
46
|
+
|
|
47
|
+
if not settings.wp_access_token:
|
|
48
|
+
missing_configs.append("WP_ACCESS_TOKEN")
|
|
49
|
+
|
|
50
|
+
if not settings.wp_phone_id:
|
|
51
|
+
missing_configs.append("WP_PHONE_ID")
|
|
52
|
+
|
|
53
|
+
if not settings.wp_bid:
|
|
54
|
+
missing_configs.append("WP_BID")
|
|
55
|
+
|
|
56
|
+
if missing_configs:
|
|
57
|
+
logger.error(f"❌ Missing required configuration: {', '.join(missing_configs)}")
|
|
58
|
+
logger.error("💡 Create a .env file with the required credentials")
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
logger.info("✅ Configuration validation passed")
|
|
62
|
+
return True
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def display_startup_information() -> None:
|
|
66
|
+
"""
|
|
67
|
+
Display startup information and demo features.
|
|
68
|
+
"""
|
|
69
|
+
print(f"🚀 Wappa v{__version__} - Simple Echo Example")
|
|
70
|
+
print("=" * 70)
|
|
71
|
+
print()
|
|
72
|
+
|
|
73
|
+
print("📋 *CONFIGURATION STATUS:*")
|
|
74
|
+
print(f" • Access Token: {'✅ Configured' if settings.wp_access_token else '❌ Missing'}")
|
|
75
|
+
print(f" • Phone ID: {settings.wp_phone_id if settings.wp_phone_id else '❌ Missing'}")
|
|
76
|
+
print(f" • Business ID: {'✅ Configured' if settings.wp_bid else '❌ Missing'}")
|
|
77
|
+
print(f" • Environment: {'🛠️ Development' if settings.is_development else '🚀 Production'}")
|
|
78
|
+
print()
|
|
79
|
+
|
|
80
|
+
print("🎯 *DEMO FEATURES:*")
|
|
81
|
+
print(" • Send any text message → Get echo response")
|
|
82
|
+
print(" • Send media files → Get acknowledgment")
|
|
83
|
+
print(" • Send location → Get location confirmation")
|
|
84
|
+
print(" • Send contacts → Get contact confirmation")
|
|
85
|
+
print(" • All messages are counted and logged")
|
|
86
|
+
print()
|
|
87
|
+
|
|
88
|
+
print("🔧 *TECHNICAL FEATURES:*")
|
|
89
|
+
print(" • Clean WappaEventHandler implementation")
|
|
90
|
+
print(" • Proper dependency injection")
|
|
91
|
+
print(" • Multi-message-type support")
|
|
92
|
+
print(" • Professional error handling")
|
|
93
|
+
print(" • Structured logging")
|
|
94
|
+
print()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def create_wappa_application() -> Wappa:
|
|
98
|
+
"""
|
|
99
|
+
Create and configure the Wappa application.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Configured Wappa application instance
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
# Create Wappa instance with JSON cache (simple file-based cache for echo example)
|
|
107
|
+
logger.info("🏗️ Creating Wappa application with JSON cache...")
|
|
108
|
+
app = Wappa(cache="json")
|
|
109
|
+
|
|
110
|
+
logger.info("✅ Wappa application created successfully")
|
|
111
|
+
return app
|
|
112
|
+
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.error(f"❌ Failed to create Wappa application: {e}")
|
|
115
|
+
raise
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def main() -> None:
|
|
119
|
+
"""
|
|
120
|
+
Main application entry point.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
logger.info("🚀 Starting Simple Echo Example")
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
# Display startup information
|
|
127
|
+
display_startup_information()
|
|
128
|
+
|
|
129
|
+
# Validate configuration before proceeding
|
|
130
|
+
if not validate_configuration():
|
|
131
|
+
logger.error("❌ Configuration validation failed - cannot start application")
|
|
132
|
+
return
|
|
133
|
+
|
|
134
|
+
# Create Wappa application
|
|
135
|
+
app = create_wappa_application()
|
|
136
|
+
|
|
137
|
+
# Create and set the simple echo handler
|
|
138
|
+
handler = SimpleEchoHandler()
|
|
139
|
+
app.set_event_handler(handler)
|
|
140
|
+
|
|
141
|
+
logger.info("✅ Application initialization completed with SimpleEchoHandler")
|
|
142
|
+
|
|
143
|
+
print("🌐 Starting simple echo server...")
|
|
144
|
+
print("💡 Press CTRL+C to stop the server")
|
|
145
|
+
print("=" * 70)
|
|
146
|
+
print()
|
|
147
|
+
|
|
148
|
+
# Start the application
|
|
149
|
+
app.run()
|
|
150
|
+
|
|
151
|
+
except KeyboardInterrupt:
|
|
152
|
+
logger.info("👋 Application stopped by user")
|
|
153
|
+
print("\\n👋 Simple echo server stopped by user")
|
|
154
|
+
|
|
155
|
+
except Exception as e:
|
|
156
|
+
logger.error(f"❌ Application startup error: {e}", exc_info=True)
|
|
157
|
+
print(f"\\n❌ Server error: {e}")
|
|
158
|
+
|
|
159
|
+
finally:
|
|
160
|
+
logger.info("🏁 Simple echo example completed")
|
|
161
|
+
print("🏁 Simple echo example completed")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Module-level app instance for uvicorn compatibility
|
|
165
|
+
# This enables: uvicorn app.main:app --reload
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
logger.info("📦 Creating module-level Wappa application instance")
|
|
169
|
+
app = Wappa()
|
|
170
|
+
|
|
171
|
+
# Create and set the simple echo handler
|
|
172
|
+
handler = SimpleEchoHandler()
|
|
173
|
+
app.set_event_handler(handler)
|
|
174
|
+
|
|
175
|
+
logger.info("✅ Module-level application instance ready with SimpleEchoHandler")
|
|
176
|
+
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.error(f"❌ Failed to create module-level app instance: {e}")
|
|
179
|
+
raise
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if __name__ == "__main__":
|
|
183
|
+
main()
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Simple Echo Master Event Handler
|
|
3
|
+
|
|
4
|
+
A simplified, clean event handler that demonstrates basic echo functionality
|
|
5
|
+
following the same patterns as the redis_cache_example but without the complexity.
|
|
6
|
+
|
|
7
|
+
This handler shows:
|
|
8
|
+
- Clean WappaEventHandler implementation
|
|
9
|
+
- Simple message echoing
|
|
10
|
+
- Multi-message-type support
|
|
11
|
+
- Proper logging and error handling
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
|
|
17
|
+
from wappa import WappaEventHandler
|
|
18
|
+
from wappa.core.logging import get_logger
|
|
19
|
+
from wappa.webhooks import ErrorWebhook, IncomingMessageWebhook, StatusWebhook
|
|
20
|
+
|
|
21
|
+
logger = get_logger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SimpleEchoHandler(WappaEventHandler):
|
|
25
|
+
"""
|
|
26
|
+
Simple echo handler that replies to all messages.
|
|
27
|
+
|
|
28
|
+
This demonstrates the basic WappaEventHandler pattern without
|
|
29
|
+
the complexity of score modules or caching systems.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
"""Initialize the simple echo handler."""
|
|
34
|
+
super().__init__()
|
|
35
|
+
self._message_count = 0
|
|
36
|
+
logger.info("🔄 SimpleEchoHandler initialized - ready to echo messages")
|
|
37
|
+
|
|
38
|
+
async def process_message(self, webhook: IncomingMessageWebhook) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Process incoming messages with simple echo functionality.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
webhook: Incoming message webhook to process
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# Validate dependencies are properly injected
|
|
47
|
+
if not self.validate_dependencies():
|
|
48
|
+
logger.error("❌ Dependencies not properly injected - cannot process message")
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
self._message_count += 1
|
|
52
|
+
|
|
53
|
+
user_id = webhook.user.user_id
|
|
54
|
+
message_text = webhook.get_message_text()
|
|
55
|
+
message_type = webhook.get_message_type_name()
|
|
56
|
+
message_id = webhook.message.message_id
|
|
57
|
+
|
|
58
|
+
logger.info(f"📝 Message #{self._message_count}: {message_type} from {user_id}")
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
# Mark message as read with typing indicator
|
|
62
|
+
await self.messenger.mark_as_read(message_id=message_id, typing=True)
|
|
63
|
+
|
|
64
|
+
# Handle different message types
|
|
65
|
+
await self._handle_message_by_type(webhook, user_id, message_text, message_type)
|
|
66
|
+
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"❌ Error processing message: {e}", exc_info=True)
|
|
69
|
+
|
|
70
|
+
async def _handle_message_by_type(
|
|
71
|
+
self,
|
|
72
|
+
webhook: IncomingMessageWebhook,
|
|
73
|
+
user_id: str,
|
|
74
|
+
message_text: str,
|
|
75
|
+
message_type: str
|
|
76
|
+
) -> None:
|
|
77
|
+
"""Handle message based on its type."""
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
if message_type.lower() == "text":
|
|
81
|
+
await self._handle_text_message(webhook, user_id, message_text)
|
|
82
|
+
elif message_type.lower() in ["image", "video", "audio", "document", "sticker"]:
|
|
83
|
+
await self._handle_media_message(webhook, user_id, message_type)
|
|
84
|
+
elif message_type.lower() == "location":
|
|
85
|
+
await self._handle_location_message(webhook, user_id)
|
|
86
|
+
elif message_type.lower() == "contacts":
|
|
87
|
+
await self._handle_contact_message(webhook, user_id)
|
|
88
|
+
else:
|
|
89
|
+
await self._handle_other_message(webhook, user_id, message_type)
|
|
90
|
+
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logger.error(f"❌ Error handling {message_type} message: {e}")
|
|
93
|
+
|
|
94
|
+
async def _handle_text_message(self, webhook: IncomingMessageWebhook, user_id: str, message_text: str) -> None:
|
|
95
|
+
"""Handle text messages with simple echo."""
|
|
96
|
+
|
|
97
|
+
logger.info(f"💬 Echoing text: '{message_text}'")
|
|
98
|
+
|
|
99
|
+
# Create echo response
|
|
100
|
+
echo_response = f"🔄 Echo: {message_text}"
|
|
101
|
+
|
|
102
|
+
# Add some metadata for the first few messages
|
|
103
|
+
if self._message_count <= 3:
|
|
104
|
+
echo_response += f"\n\n📊 Message #{self._message_count} processed successfully!"
|
|
105
|
+
if self._message_count == 1:
|
|
106
|
+
echo_response += "\n👋 Welcome to the Simple Echo Example!"
|
|
107
|
+
|
|
108
|
+
# Send echo response
|
|
109
|
+
result = await self.messenger.send_text(
|
|
110
|
+
recipient=user_id,
|
|
111
|
+
text=echo_response,
|
|
112
|
+
reply_to_message_id=webhook.message.message_id
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if result.success:
|
|
116
|
+
logger.info(f"✅ Text echo sent successfully: {result.message_id}")
|
|
117
|
+
else:
|
|
118
|
+
logger.error(f"❌ Text echo failed: {result.error}")
|
|
119
|
+
|
|
120
|
+
async def _handle_media_message(self, webhook: IncomingMessageWebhook, user_id: str, message_type: str) -> None:
|
|
121
|
+
"""Handle media messages."""
|
|
122
|
+
|
|
123
|
+
logger.info(f"🎬 Processing {message_type} message")
|
|
124
|
+
|
|
125
|
+
response = f"📁 {message_type.title()} received! Simple echo doesn't download media, but message was processed successfully.\n\n📊 Total messages: {self._message_count}"
|
|
126
|
+
|
|
127
|
+
result = await self.messenger.send_text(
|
|
128
|
+
recipient=user_id,
|
|
129
|
+
text=response,
|
|
130
|
+
reply_to_message_id=webhook.message.message_id
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if result.success:
|
|
134
|
+
logger.info(f"✅ {message_type} response sent: {result.message_id}")
|
|
135
|
+
else:
|
|
136
|
+
logger.error(f"❌ {message_type} response failed: {result.error}")
|
|
137
|
+
|
|
138
|
+
async def _handle_location_message(self, webhook: IncomingMessageWebhook, user_id: str) -> None:
|
|
139
|
+
"""Handle location messages."""
|
|
140
|
+
|
|
141
|
+
logger.info("📍 Processing location message")
|
|
142
|
+
|
|
143
|
+
response = f"📍 Location received! Thanks for sharing your location.\n\n📊 Total messages: {self._message_count}"
|
|
144
|
+
|
|
145
|
+
result = await self.messenger.send_text(
|
|
146
|
+
recipient=user_id,
|
|
147
|
+
text=response,
|
|
148
|
+
reply_to_message_id=webhook.message.message_id
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
if result.success:
|
|
152
|
+
logger.info(f"✅ Location response sent: {result.message_id}")
|
|
153
|
+
else:
|
|
154
|
+
logger.error(f"❌ Location response failed: {result.error}")
|
|
155
|
+
|
|
156
|
+
async def _handle_contact_message(self, webhook: IncomingMessageWebhook, user_id: str) -> None:
|
|
157
|
+
"""Handle contact messages."""
|
|
158
|
+
|
|
159
|
+
logger.info("👥 Processing contact message")
|
|
160
|
+
|
|
161
|
+
response = f"👥 Contact shared! Thanks for the contact information.\n\n📊 Total messages: {self._message_count}"
|
|
162
|
+
|
|
163
|
+
result = await self.messenger.send_text(
|
|
164
|
+
recipient=user_id,
|
|
165
|
+
text=response,
|
|
166
|
+
reply_to_message_id=webhook.message.message_id
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
if result.success:
|
|
170
|
+
logger.info(f"✅ Contact response sent: {result.message_id}")
|
|
171
|
+
else:
|
|
172
|
+
logger.error(f"❌ Contact response failed: {result.error}")
|
|
173
|
+
|
|
174
|
+
async def _handle_other_message(self, webhook: IncomingMessageWebhook, user_id: str, message_type: str) -> None:
|
|
175
|
+
"""Handle other message types."""
|
|
176
|
+
|
|
177
|
+
logger.info(f"❓ Processing unsupported message type: {message_type}")
|
|
178
|
+
|
|
179
|
+
response = f"📨 {message_type.title()} message received! This message type is not fully supported yet, but was processed successfully.\n\n📊 Total messages: {self._message_count}"
|
|
180
|
+
|
|
181
|
+
result = await self.messenger.send_text(
|
|
182
|
+
recipient=user_id,
|
|
183
|
+
text=response,
|
|
184
|
+
reply_to_message_id=webhook.message.message_id
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
if result.success:
|
|
188
|
+
logger.info(f"✅ {message_type} response sent: {result.message_id}")
|
|
189
|
+
else:
|
|
190
|
+
logger.error(f"❌ {message_type} response failed: {result.error}")
|
|
191
|
+
|
|
192
|
+
async def process_status(self, webhook: StatusWebhook) -> None:
|
|
193
|
+
"""Process status webhooks with simple logging."""
|
|
194
|
+
|
|
195
|
+
status_value = webhook.status.value
|
|
196
|
+
recipient = webhook.recipient_id
|
|
197
|
+
|
|
198
|
+
logger.info(f"📊 Status update: {status_value.upper()} for recipient {recipient}")
|
|
199
|
+
|
|
200
|
+
async def process_error(self, webhook: ErrorWebhook) -> None:
|
|
201
|
+
"""Process error webhooks with simple logging."""
|
|
202
|
+
|
|
203
|
+
error_count = webhook.get_error_count()
|
|
204
|
+
primary_error = webhook.get_primary_error()
|
|
205
|
+
|
|
206
|
+
logger.error(
|
|
207
|
+
f"🚨 Platform error: {error_count} errors, "
|
|
208
|
+
f"primary: {primary_error.error_code} - {primary_error.error_title}"
|
|
209
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ================================================================
|
|
2
|
+
# WAPPA WHATSAPP FRAMEWORK CONFIGURATION
|
|
3
|
+
# ================================================================
|
|
4
|
+
|
|
5
|
+
# General Configuration
|
|
6
|
+
PORT=8000
|
|
7
|
+
TIME_ZONE=America/Bogota
|
|
8
|
+
|
|
9
|
+
# DEBUG or INFO or WARNING or ERROR or CRITICAL
|
|
10
|
+
LOG_LEVEL=DEBUG
|
|
11
|
+
LOG_DIR=./logs
|
|
12
|
+
## Environment DEV or PROD
|
|
13
|
+
ENVIRONMENT=DEV
|
|
14
|
+
|
|
15
|
+
# WhatsApp Graph API
|
|
16
|
+
BASE_URL=https://graph.facebook.com/
|
|
17
|
+
API_VERSION=v23.0
|
|
18
|
+
|
|
19
|
+
# WhatsApp Business API Credentials
|
|
20
|
+
WP_ACCESS_TOKEN=
|
|
21
|
+
WP_PHONE_ID=
|
|
22
|
+
WP_BID=
|
|
23
|
+
|
|
24
|
+
# Webhook Configuration
|
|
25
|
+
WHATSAPP_WEBHOOK_VERIFY_TOKEN=
|
|
26
|
+
|
|
27
|
+
# Redis Configuration (Optional - uncomment to enable Redis persistence)
|
|
28
|
+
REDIS_URL=redis://localhost:6379/
|
|
29
|
+
REDIS_MAX_CONNECTIONS=64
|
|
30
|
+
|
|
31
|
+
# Optional: AI Tools
|
|
32
|
+
# OPENAI_API_KEY=
|
|
33
|
+
|
|
@@ -1,10 +1,69 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Wappa
|
|
2
|
+
logs/
|
|
3
|
+
|
|
4
|
+
# Environment variables
|
|
5
|
+
.env
|
|
6
|
+
.env.local
|
|
7
|
+
.env.development
|
|
8
|
+
.env.production
|
|
9
|
+
|
|
10
|
+
# Python
|
|
2
11
|
__pycache__/
|
|
3
|
-
*.py[
|
|
12
|
+
*.py[cod]
|
|
13
|
+
*$py.class
|
|
14
|
+
*.so
|
|
15
|
+
.Python
|
|
4
16
|
build/
|
|
17
|
+
develop-eggs/
|
|
5
18
|
dist/
|
|
19
|
+
downloads/
|
|
20
|
+
eggs/
|
|
21
|
+
.eggs/
|
|
22
|
+
lib/
|
|
23
|
+
lib64/
|
|
24
|
+
parts/
|
|
25
|
+
sdist/
|
|
26
|
+
var/
|
|
6
27
|
wheels/
|
|
7
|
-
|
|
28
|
+
share/python-wheels/
|
|
29
|
+
*.egg-info/
|
|
30
|
+
.installed.cfg
|
|
31
|
+
*.egg
|
|
32
|
+
MANIFEST
|
|
8
33
|
|
|
9
34
|
# Virtual environments
|
|
10
|
-
.venv
|
|
35
|
+
.venv/
|
|
36
|
+
venv/
|
|
37
|
+
ENV/
|
|
38
|
+
env/
|
|
39
|
+
|
|
40
|
+
# IDE
|
|
41
|
+
.vscode/
|
|
42
|
+
.idea/
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
|
|
46
|
+
# OS
|
|
47
|
+
.DS_Store
|
|
48
|
+
Thumbs.db
|
|
49
|
+
|
|
50
|
+
# Logs
|
|
51
|
+
app/logs/
|
|
52
|
+
logs/
|
|
53
|
+
*.log
|
|
54
|
+
|
|
55
|
+
# Redis dumps
|
|
56
|
+
dump.rdb
|
|
57
|
+
|
|
58
|
+
# Temporary files
|
|
59
|
+
.tmp/
|
|
60
|
+
temp/
|
|
61
|
+
tmp/
|
|
62
|
+
|
|
63
|
+
# Coverage reports
|
|
64
|
+
htmlcov/
|
|
65
|
+
.tox/
|
|
66
|
+
.coverage
|
|
67
|
+
.coverage.*
|
|
68
|
+
.cache
|
|
69
|
+
.pytest_cache/
|